00:00:00当你准备启动一个新项目并需要数据库时,你首先想到
00:00:03的选项是什么?SQLite?大概率是 SQLite,对吧?它确实很棒且可靠,
00:00:09零配置,又是行业标准。但随着本地数据变得越来越重,查询
00:00:14变得越来越复杂,我们开始触及单线程文件锁定
00:00:20引擎的性能天花板。但现在,出现了一个试图解决这些问题的新选手。
00:00:25它叫作 Stulab,是一个完全用 Rust 编写的数据库引擎,它刚刚发布了
00:00:31一个原生 Node.js 驱动程序,坦白说,它的表现非常强劲。
00:00:36这个数据库比 SQLite 快 138 倍。所以在这段视频中,我们将深入了解
00:00:43Stulab 的底层原理,看看它是如何运作的,并进行现场基准测试,看看它是否真的
00:00:50如宣传的那样强大。这会非常有趣,让我们开始吧。那么 Stulab 到底是什么?
00:01:00从核心来看,Stulab 是一个嵌入式 OLAP,即在线分析处理数据库。如果你
00:01:06习惯了像 SQLite 或 Postgres 这样的标准数据库,它们通常是 OLTP,即在线
00:01:14事务处理数据库,顾名思义,它们是为事务优化的。
00:01:20但 Stulab 不同。它是为分析工作负载设计的,从底层开始就用 Rust 构建,
00:01:27专注于高速数据处理。你可以把它想象成拥有 SQLite 文件般的便携性,
00:01:33但具备像 DuckDB 或 BigQuery 那样的原始分析能力。但最酷的一点是,
00:01:39得益于它的原生 Node 驱动程序,你现在可以在 Node.js 中使用它。当我提到
00:01:45它是“原生驱动”时,我指的不是某种普通的封装。通常,当数据库
00:01:49是用 Rust 或 C++ 等不同语言编写时,你的 Node.js 应用必须通过桥接与之通信。
00:01:56这通常意味着要把数据转换为 JSON 或其他格式,通过本地网络
00:02:02套接字发送,然后在另一端再转换回来。这被称为序列化开销,
00:02:08它是性能的巨大杀手。但 Stulab Node 的做法不同。它使用了 NAPI-RS,
00:02:15这是一个允许将 Rust 引擎编译为原生二进制文件,并直接加载到
00:02:21Node.js 进程中的框架。因此,中间没有桥接,也没有翻译器。当你发送
00:02:27查询时,Node.js 和 Rust 基本上共享同一块内存空间。Stulab 极速运行有三个
00:02:33主要原因。首先,它使用了 MVCC,即多版本并发控制。
00:02:40不像 SQLite 那样单个写入者就会锁定整个数据库,Stulab 允许
00:02:47多个读取者和写入者同时工作。其次,它采用并行执行。Stulab 使用了一个
00:02:53名为 Rayon 的调度器。有了 Rayon,当你运行海量查询时,它不会只在一个 CPU 核心上运行,
00:03:00而是会拆分该查询,并利用机器上的每一个核心。第三,它使用基于成本的
00:03:06优化器。所以它不会盲目地执行 SQL,而是会分析数据,估算
00:03:13不同路径的成本,并选择最快的方式来获取结果。这些就是让 Stulab
00:03:19比 SQLite 快得多的理论依据。但让我们来实测一下,看看是否属实。
00:03:25在这次测试中,我们将使用一个简单的 Node.js 项目,并安装 Stulab 和
00:03:30SQLite 作为依赖。Stulab 表现最出色的场景之一是使用 count distinct(去重计数)。
00:03:37所以我很想知道事实是否真的如此。我设置了一个简单的脚本,启动了
00:03:43每个数据库的内存版本,并创建了一个简单的销售表。然后我们为该表
00:03:49填充 10,000 行随机销售数据,每行代表一个用户的销售额,用户 ID 从
00:03:560 到 1,000 不等,并具有特定的类别。我们将对两个数据库进行
00:04:03批量数据插入,然后运行基准测试,查询特定用户在特定类别下
00:04:10销售额的去重计数,并计算每个数据库的性能。现在我必须
00:04:16指出,目前安装的包无法正常工作,这有点令人沮丧。如果我们现在
00:04:22运行基准测试,会看到它报错缺少原生绑定。显然,该项目的
00:04:28作者忘记添加二进制文件,或者没有将正确的二进制文件链接到包中。所以我不得不
00:04:34从源码构建。我克隆了代码仓库,在内部运行了构建,然后回到
00:04:39我的基准测试项目,并将我的源码目录链接为依赖项。目前这
00:04:44确实有点麻烦,希望项目作者以后能修复。但尽管如此,
00:04:49完成这些步骤后,我们终于可以运行基准测试了。现在就开始吧。
00:04:54如你所见,count distinct 操作在 Stulab 上确实快得多,虽然
00:05:01没有广告宣传的那么夸张。它只快了 4 倍。如果我们把要填充的
00:05:07数据量再增加一个零,用 1,000,000 行数据再次测试会怎样?我们试一下。
00:05:12即便是在 100 万行数据下,Stulab 也只快了 6 倍,而不是 138 倍。但尽管如此,
00:05:20这仍然是一个很棒的结果。这就是去重计数测试。我决定再做一个
00:05:26基准测试,来测试 distinct + order by(去重后排序)操作。在第二次测试中,
00:05:33我设置了一个环境,摄取一些带有不同 IP 地址和状态码的随机日志,然后尝试
00:05:39根据 IP 地址和状态码对寻找唯一日志,并按 IP 升序和状态码
00:05:47降序排列。可以看到,运行测试后,Stulab 的性能依然优于 SQLite,
00:05:53但不是 14 倍,仅快了 1 到 1.5 倍。所以在我看来,这里列出的数据
00:06:01有点夸大了。不过,正如我们在测试中看到的,Stulab 确实比 SQLite 更快。
00:06:08公平起见,作者也提到了 SQLite 表现依然优于 Stulab 的领域。
00:06:13这些主要是执行单行操作的场景。所以 Stulab 擅长的是
00:06:19分析型和复杂的查询。那么 Stulab 是 SQLite 的杀手吗?老实说,不是。它们是
00:06:26为了完全不同的目标而构建的。SQLite 依然是你处理事务时可靠的日常工具,
00:06:32而 Stulab 可能是你进行数据分析的高性能赛车。但我们现在拥有了
00:06:38一个纯 Rust 编写的分析引擎,并能通过 NAPI-RS 轻松集成到 Node.js 项目中,
00:06:45这真的很棒。项目所有者只需要修复目前的 NPM 包,
00:06:50这样我们就不用从源码构建了。以上就是 Stulab 的简要介绍。
00:06:55你觉得它怎么样?这种性能提升值得让你切换到 Stulab 吗?还是你会坚持
00:07:01使用可靠的 SQLite?请在评论区告诉我们。各位,如果你觉得
00:07:06这个视频有用,请点击视频下方的点赞按钮让我知道。另外,
00:07:11别忘了订阅我们的频道。我是来自 Better Stack 的 Andris,我们
00:07:17下期视频再见。