小数据失落的十年?
TL;DR: 我们在 2012 年的 MacBook Pro 上对 DuckDB 进行基准测试,以决定:我们是否在追求分布式数据分析架构上浪费了十年?
关于数据实际上并没有那么“大”,以及硬件创新速度如何超越有用数据集增长的问题,已经说了很多,我们自己也说了很多。我们甚至可能预测在不久的将来会出现数据奇点,届时 99% 的有用数据集都可以轻松地在单个节点上查询。正如最近显示,Amazon Redshift 和 Snowflake 中的中位数扫描读取了可处理的 100 MB 数据,而 99.9% 的扫描读取量小于 300 GB。所以奇点可能比我们想象的更近。
但我们开始思考,这种发展究竟是从什么时候开始的?个人电脑,比如无处不在的 MacBook Pro(通常被用来运行 Chrome),是从什么时候开始成为它们今天这样的数据处理强者的?
让我们把注意力转向 2012 年的 Retina MacBook Pro,很多人(包括我自己)当时因为其华丽的“Retina”显示屏而购买了这款电脑。数百万台被售出。尽管当时失业,我甚至还挥霍地升级了 16 GB 内存。但这款机器还有一个经常被遗忘的革命性变化:它是第一款内置固态硬盘(SSD)并且拥有具有竞争力的4 核 2.6 GHz “Core i7” CPU 的 MacBook。再次观看发布会很有趣,他们确实强调了“全闪存架构”的性能方面。

旁注:MacBook Air 实际上是第一款在 2008 年就(可选)内置 SSD 的 MacBook。但遗憾的是,它没有 Pro 的 CPU 火力。
巧合的是,我仍然在 DuckDB Labs 办公室里保留着这台笔记本电脑,目前我的孩子们用它来用巨大的字体输入他们的名字,或者在他们来的时候在 YouTube 上看《布鲁伊》。但是,这台“古董”还能运行现代的 DuckDB 吗?它的性能与现代 MacBook 相比如何?我们现在看到的数据革命是否早在 2012 年就可能发生了?让我们一探究竟!
软件
首先,操作系统怎么样?为了让这个跨越十年的比较更公平,我们实际上将 Retina 笔记本电脑的操作系统降级到了 OS X 10.8.5 “Mountain Lion”,这是该笔记本电脑于 2012 年 7 月发布几周后随附的操作系统版本。尽管 Retina 实际上可以运行 10.15 (Catalina),但我们觉得真正的 2012 年比较也应该使用那个时代的操作系统。下面是用户界面的截图,献给那些有时感到有点老的人。

接着是 DuckDB 本身:在 DuckDB,我们对可移植性和依赖性(或者说缺乏依赖性)有些痴迷。这意味着为了让 DuckDB 在古老的 Mountain Lion 上运行,我们几乎不需要做什么:默认情况下,DuckDB 的原生二进制文件构建时就向后兼容 OS X 11.0 (Big Sur),但简单地更改标志并重新编译就足以让 DuckDB 1.2.2 在 Mountain Lion 上运行。我们本想也使用 2012 年的编译器来构建 DuckDB,但是,唉,C++ 11 在 2012 年出人意料地太新了,编译器无法完全支持。无论如何,二进制文件运行良好,也可以通过解决编译器错误来生成。或者我们也可以像其他人那样手工编写汇编代码。
基准测试
但我们不关心合成 CPU 分数,我们感兴趣的是合成 SQL 分数!为了看看这台旧机器在执行严肃数据处理时的表现,我们使用了目前有些老套但众所周知的 TPC-H 基准测试,规模因子为 1000。这意味着两个主要表 lineitem
和 orders
分别包含 60 亿和 15 亿行。当存储为 DuckDB 数据库时,数据库大小约为 265 GB。
从 TPC 网站上的审计结果来看,在单个节点上以这种规模因子运行基准测试似乎需要花费数十万美元的硬件。
我们对 22 个基准查询中的每一个都运行了五次,并取中位数运行时间以消除噪音。然而,由于内存量(16 GB)远小于数据库大小(256 GB),所以输入数据无法在缓冲区管理器中缓存太多,因此这些并不是人们有时所说的“热”运行。

以下是按查询划分的结果,单位为秒
查询 | 延迟 |
---|---|
1 | 142.2 |
2 | 23.2 |
3 | 262.7 |
4 | 167.5 |
5 | 185.9 |
6 | 127.7 |
7 | 278.3 |
8 | 248.4 |
9 | 675.0 |
10 | 1266.1 |
11 | 33.4 |
12 | 161.7 |
13 | 384.7 |
14 | 215.9 |
15 | 197.6 |
16 | 100.7 |
17 | 243.7 |
18 | 2076.1 |
19 | 283.9 |
20 | 200.1 |
21 | 1011.9 |
22 | 57.7 |
但这些冰冷的数字到底意味着什么?隐藏的惊喜是,我们实际上有了这些数字,这台旧电脑竟然可以使用 DuckDB 完成所有的基准测试查询!如果我们仔细看看时间,我们会发现查询耗时从一分钟到半小时不等。对于这类数据上的分析查询来说,这些等待时间绝不是不合理的。甚至在 2012 年,你可能需要等待更长的时间,Hadoop YARN 才会首先接收你的作业,最终却只是向你抛出堆栈跟踪。
2023年的改进
但这些结果与现代 MacBook 相比如何?作为比较点,我们使用了一台碰巧放在同一张桌上的现代基于 ARM 的M3 Max MacBook Pro。这两台 MacBook 代表了十多年的硬件发展。
单看 GeekBench 5 基准测试分数,我们发现使用所有核心时,原始 CPU 速度大约有 7 倍的差异,而单核速度大约有 3 倍的差异。当然,RAM 和 SSD 速度也有很大的差异。有趣的是,显示屏尺寸和分辨率几乎没有变化。
以下是并排显示的结果
查询 | 旧版延迟 | 新版延迟 | 加速 |
---|---|---|---|
1 | 142.2 | 19.6 | 7.26 |
2 | 23.2 | 2.0 | 11.60 |
3 | 262.7 | 21.8 | 12.05 |
4 | 167.5 | 11.1 | 15.09 |
5 | 185.9 | 15.5 | 11.99 |
6 | 127.7 | 6.6 | 19.35 |
7 | 278.3 | 14.9 | 18.68 |
8 | 248.4 | 14.5 | 17.13 |
9 | 675.0 | 33.3 | 20.27 |
10 | 1266.1 | 23.6 | 53.65 |
11 | 33.4 | 2.2 | 15.18 |
12 | 161.7 | 10.1 | 16.01 |
13 | 384.7 | 24.4 | 15.77 |
14 | 215.9 | 9.2 | 23.47 |
15 | 197.6 | 8.2 | 24.10 |
16 | 100.7 | 4.1 | 24.56 |
17 | 243.7 | 15.3 | 15.93 |
18 | 2076.1 | 47.6 | 43.62 |
19 | 283.9 | 23.1 | 12.29 |
20 | 200.1 | 10.9 | 18.36 |
21 | 1011.9 | 47.8 | 21.17 |
22 | 57.7 | 4.3 | 13.42 |
我们确实看到了显著的加速,从 7 倍到高达 53 倍不等。几何平均值从 218 提高到 12,提升了大约 20 倍。
可重现性
二进制文件、脚本、查询和结果都可在 GitHub 上查阅。我们还提供了TPC-H SF1000 数据库文件供下载,这样您就不必生成它了。但请注意,这是一个大文件。
讨论
我们已经看到这台十年历史的 MacBook Pro Retina 如何完成了复杂的分析基准测试。一台更新的笔记本电脑能够显著缩短这些时间。但绝对的加速数字在这里有点毫无意义。差异纯粹是数量上的,而非质量上的。
从用户的角度来看,更重要的是这些查询能在合理的时间内完成,而不是花费 10 秒还是 100 秒。我们几乎可以用这两台笔记本电脑处理相同类型的数据问题,只是需要耐心等待更长的时间。考虑到 DuckDB 的离核处理能力,这尤其正确,它允许在需要时将查询中间结果溢出到磁盘。
也许更有趣的是,早在 2012 年,就已经完全有可能出现像 DuckDB 这样的单节点 SQL 引擎,它能够在可管理的时间内对包含 60 亿行数据的数据库运行复杂的分析型 SQL 查询——而且这次我们甚至不需要将其浸入干冰中。
历史充满了“如果”:如果像 DuckDB 这样的东西在 2012 年就存在了呢?主要条件都已具备,向量化查询处理在2005 年就已被发明。那么,现在看来有些愚蠢的向分布式系统进行数据分析的举动是否还会发生?我们基准测试数据库的数据集大小与 2024 年分析查询输入数据量的 99.9% 百分位数惊人地接近。虽然 Retina MacBook Pro 在 2012 年是一台高端机器,但到 2014 年,许多其他供应商也开始提供内置 SSD 存储的笔记本电脑,并且更大的内存容量变得更加普及。
所以,是的,我们确实浪费了整整十年。