作者 | Cloudberry Database 团队
翻译 | 王殿进
审阅 | Tom Shawn, Max Yang
本文由 Cloudberry Database 社区编译自 MotherDuck 官网博文《PERF IS NOT ENOUGH》,原作者为 Jordan Tigani( MontherDuck 联合创始人兼 CEO),译文较原文稍有调整。
数据库圈存在的性能崇拜
我从西雅图的家出门到旧金山办公室大约需要 4.5 小时。我们打个比方:假设你制造了一架高超声速飞机,其最高速度比普通波音 737-Max 快 10 倍。算上我打优步去机场,排队等安检、登机、飞机滑行、起降、等登机口、等行李,再加上打优步去办公室,这一路下来,已经完成了一些惊人的工程壮举,但可能也就只节省了总旅行时间的 20%。这很不错了,但我还是赶不上上午 10 点的会。
数据库圈一直专注于制造速度更快的飞机。与此同时,安检队伍变得更长、行李出现丢失。如果你的数据在一个稍有问题的 CSV 文件中,或者你要提的问题很难用 SQL 表述,那么理想的查询优化器也将无济于事。
性能是像我这样的数据库书呆子用来衡量我们重要性的最常见指标,像体育迷一样,我们倾向于选择我们支持的团队。如果你最喜欢的数据库赢得了基准测试之战,你就有权高谈阔论不断吹嘘。然后秀测评结果、写博客发文章,向愿意买账的人证明,你喜欢的数据库拿了冠军。
一般而言,性能特别是通用基准测试,不是选择数据库的好方法。你最好根据易用性、生态、更新速度或与现有工作流的集成完整度来做出决策。充其量,性能只是完成某些特定任务所需时间的即时观察指标;往坏了说,太关注性能反而导致我们会在错误的事情上做优化。
性能评测之战已结束
2019 年,GigaOm 发布了一篇云数仓的基准评测报告。他们在三大云服务商外加 Snowflake 上都运行了 TPC-H 和 TPC-DS 测试。结果如何呢?Azure Data Warehouse 最快,Redshift 紧随其后,Snowflake 和 BigQuery 远远落后。
当时我正在 BigQuery 工作,很多人都被吓坏了……我们怎么会比 Azure 慢那么多呢?然而,评测结果与我们从用户那里得到的反馈不太匹配。每次客户拿我们和 Azure 对比评估时,客户最终都会选择 BigQuery。当时的市场结果几乎与基准测试结果相反:Snowflake 和 BigQuery 销售比 Redshift 好得多,Redshift 又比 Azure 卖的好得多。
如果基准测试与客户体验不匹配,那么要么是基准测试做错了,要么是基准测试测错了东西,或者证明性能压根就没那么重要。我们做了很多探索,这不是第一次;GigaOM 的人非常擅长搞基准测试,方法也很合理。他们跑的基准测试 TPC-H 和 TPC-DS 是行业标准,而且这也是我们自己为了判断性能同时在内部运行的基准测试。虽然人们可以拿数据大小或它们与实际工作负载的相关性来吹毛求疵,但它们仍是行业里面最好的基准测试工具。
因此,如果基准测试能很好地代表性能,并且客户最终购买了在基准测试中表现不佳的系统,那么我们有理由相信,可能还有比性能更重要的事情。
什么叫快?
在我从事云数据库工作的 15 年里,我注意到整个行业存在一种反面模式(anti-pattern):打造数据库的人往往专注在用户从点击“运行”按钮到结果就绪之间的时间。很容易理解为什么数据库人员只关注数据库服务器时间;毕竟,这是他们最能控制的事情。但真正对用户产生影响的是完成一项任务所需的时间,这不是一回事。
在 BigQuery 的时候,我们将构建 JDBC 驱动程序外包给了一家专门构建数据库连接器的公司。可以这么简单理解 JDBC:它们提供了一个通用接口,程序员和 BI 工具可以使用该接口连接到数据库。在当时,找一位外部知名专家来构建接口还是很有意义的。
几年以后,在无数客户投诉之后,我们发现 JDBC 驱动程序中的错误拉低了性能。从我们的角度来看,查询运行得很快,只需一两秒。但是,驱动程序轮询查询完成并拉取结果的方式让查询看起来像是要多花几秒甚至几分钟。当有大量查询结果时,这种影响就会加剧,因为即使用户不需要查看所有结果,驱动程序通常也会一次性拉取全部结果。有时,甚至会因为内存不足导致崩溃。
我们投入了大量人力来提高查询速度,将查询时间缩短几秒,但大多数用户使用连接器所增加的延迟远比我们省出来的时间长得多。更重要的是,我们对这一事实完全视而不见。在 Google 没人真正用过 JDBC 驱动程序,虽然我们每晚都要运行全套基准测试,但这些基准测试实际上并没有反映出用户所看到的端到端性能。
“头疼医头,脚痛医脚”,我们的眼光只盯在我们能测量的服务器性能上。用户看到的查询时间对我们来说不可见,我们认为这是别人的问题。要真正解决这个问题,不仅是贴个创可贴就完事,还需要重新定义我们该如何看待性能。
性能具有主观性
性能必须从用户角度来衡量,而不是从数据库角度来衡量。这是一个用户体验问题,和其他用户体验问题一样,不能单纯用一个数字来描述。这个观点会让许多人感到惊讶,因为他们认为性能如同赛车是一件客观的事情,好比你说兰博基尼比普锐斯(译者注:丰田汽车品牌)快,也应该能说我的数据库比你的数据库快。但就像兰博基尼不一定比普锐斯(或自行车,如果发生堵车)快一样,数据库的实际工作负载将决定哪个更快。
主观性得到的评价不高;人们会这么说:“嗯,没办法判断哪个更好,所以选哪个不重要。”但仅仅因为福特 F150 皮卡和特斯拉 Roadster(译者注:特斯拉电动敞篷跑车)之间的差异是主观的,并不意味着我对两者的体验就是一样的。数据库也是如此;如果我们说 Clickhouse 和 Redshift 之间的性能差异是主观的,并不意味着它们是等同的。这只是意味着哪个更快取决于它们的使用方式。
几年前,Clickhouse 发布了 Clickbench,该基准测试显示 Clickhouse 比他们测试的几十个数据库都要快。这让我大吃一惊,因为当时我在 SingleStore 工作,我们认为我们比 Clickhouse 要快得多。在深入研究基准测试之后,我们发现基准测试不包含任何 JOIN 操作,仅仅是对单表的查询,并且特别依赖对单表 COUNT(DISTINCT) 这类查询。
虽然你可能觉得发布一个只执行单表扫描的基准测试很俗气,但 Clickbench 实际上在展示许多实际工作负载方面做得很好。如果你进行了大量的日志分析,并且需要计算网站的不同用户,这可能是个很好的性能指标。也就是说,如果你使用星型模型运行更传统的数据仓库工作负载,那么 Clickbench 会产生误导。
厂商们的基准测试倾向于“王婆卖瓜”,重点会放在自己擅长的方向。下面图表摘自《Fair Benchmarking Considered Difficult》,描述了典型的厂商基准测试结果。
数据库基准测试存在大量陷阱,经验表明,基准测试通常很难全面反映用户对性能的感受。例如,BigQuery 在基准测试中表现得很差,但许多人的实际体验是,其性能表现很出色。因为 BigQuery 没有任何障碍,而且很大程度上是自动调优,所以其在人们心中的形象非常好。一个经过高度调优的 SingleStore 实例在大多数任务中都超越 BigQuery,但你有时间调优自己的 Schema 吗?当你添加新的工作负载时,又会出现什么情况呢?
DuckDB 官网曾发表免责声明,称:“请不要抱怨性能问题,我们会在追求速度之前先保证正确性。”并非所有数据库都采取这种方法。你可以通过移除安全气囊、牵引力控制、吸能区、排放控制等安全装备让汽车开得更快,但大多数人并不想开这样的汽车。数据库也不例外,如果你移除溢出检查,不做刷盘写入,为某些操作提供近似结果,或者不提供 ACID 保证,就能让大多数数据库运行地更快。一些数据库在基准测试中走这些捷径拿到了不错的测试结果,但除非在特定情况下,否则我不会用它们。
演化速率
去年,当我开始着手在 DuckDB 之上创建一家公司时,许多人向我指出,如果你在谷歌上搜索 DuckDB 的性能,就会看到一个基准测试,在该测试中 DuckDB 表现很糟。难道我不担心吗?为什么不选一个“更快”的数据库呢?
我之所以不担心,有两个原因。首先,我认为性能是次要的。其次,DuckDB 展示了一些东西,使当前的基准测试变得毫无意义,同时 DuckDB 改进得也非常快。部分原因是一些架构决策,部分是因为代码库较新和干净,部分是因为参与的工程师们非常有才华,DuckDB 的进度速度非同一般。
事实证明,我不担心是对的。基于最新版本 DuckDB 的同一基准测试的最新结果显示,DuckDB 已从中间位置跃居领先地位,并且领先优势十分明显。
更重要的是,当你选择了一个数据库,该数据库并不会在那个点上止步不前。一旦选型,你很可能会坚持用上几年。从现在到明年,你选择的数据库的性能和功能将发生很大变化,更不用说从现在到五年以后了。
因此,一个非常重要的变量就是不仅要看数据库现在能做什么,而是看它未来一年能做什么。如果只因数据库中的一个 Bug 就让你选择了它的竞品,那么在短短几周内这个 Bug 修复了,再看你的选型理由就显得比较愚蠢。性能也是如此;如果两个数据库以不同的速度改进,你最好选发展更快的那个数据库。未来的你会感谢你现在的决定。
没有魔法豆
比如说有一组数据库产品,它们的迭代维护都很活跃,那么几年内性能将会趋于一致。如果 Clickhouse 采用了一种技术使其在扫描速度上占据优势,那么在一两年内 Snowflake 也会拥有这项技术。如果 Snowflake 添加了增量物化视图,BigQuery 很快就会跟进。随着时间的推移,重要的性能差异不太可能持续存在。
尽管这些公司的工程师们都非常聪明,但他们都没有无法复制的神秘咒语或方法。每个数据库都使用不同的技巧组合来获得良好的性能。一些数据库可能将查询编译成机器代码,另一些可能将数据缓存在本地 SSD 上,还有一些可能使用专用网络硬件来进行 shuffle 处理。假以时日,任何人都可以实现这些技术。如果它们效果好,那么它们可能会随处可见。
Fivetran CEO George Fraser 写过一篇很有意思的文章,比较了主要数据仓库厂商的性能在一段时间内的表现;虽然 2020 年各厂商的性能表现存在很大差异,但到 2022 年,它们之间的差异已经大大缩小。2020 年,最快的时间是 8 秒,最慢的是 18 秒;而 2022 年,其中 3 家厂商的时间都在 7 秒左右,最慢的也有 9 秒。
当然,这一规则有个例外,就是很难克服架构上的差异。与共享磁盘架构(shared disk)相比,无共享架构(Shared nothing)数据库处于不利地位,Redshift 花了多年时间才转向以共享磁盘为主的架构。依赖将元数据持久化到对象存储的湖仓在快速更新时会遇到困难;这是该模型的固有缺陷。但这些类型的差异通常只会影响利润;例如,从长远来看,Redshift 并不一定比 Snowflake 更快或更慢。
问题在于人机交互
和数据库交互体验
对用户来说,衡量性能的重要指标是他们提出问题到得到答案之间的时间;这与数据库运行查询所用的时间可能大不相同。
让我们退一步,从用户的角度来看,你可以使用很多杠杆来将提问与获取答案之间的间隔缩到最短。你可以让提问变得更简单。你可以使查询结果更方便地转化为用户可理解的内容。当用户没问对问题时,你可以帮助用户获得反馈。当数据有问题时,你可以帮助他们理解。你可以帮助他们从正确的位置并以正确的形式获取所需的数据,以便能够第一时间提出问题。虽然这些通常不被认为是性能问题,但与更好的查询计划相比,这些改进可以在更大程度上加快分析师和数据工程师的工作流程。
Snowflake 在查询编写支持方面做得非常出色。许多 SQL 方言都坚持语法的一致性,认为应该有“一种方法”来处理所有事情,而 Snowflake 设计师的目标是让用户输入的 SQL“有效”。例如,在 Snowflake SQL 中,如果你想计算两个日期之间的差异,你可以使用 DATEDIFF 或 TIMEDIFF;两者都可以与任何合理的类型一起使用。你可以指定粒度,也可以不指定。你可以在粒度周围使用引号,也可以不使用。因此,只要可以从查询中推断出意图,那么它就应该“有效”。这是分析师喜欢 Snowflake 的原因之一,因为他们不必花费时间查阅文档。
DuckDB 也在这方面有所创新,推出了“更友好的 SQL”功能,该功能在 SQL 语言中增加了许多创新点,使得编写查询更加简单。例如,“GROUP BY ALL”。编写聚合查询时,你可能很容易忘记在 GROUP BY 子句中列出某个字段。这种情况在修改查询时尤其常见,因为你需要在多个不同的地方进行修改。GROUP BY ALL 语法使你能够更轻松地编写和维护查询,因为你只需要在一个地方(即 SELECT 列表)而不是聚合中进行更改。这一功能非常实用,因此该功能发布后不久,其他几个数据库厂商便争相添加了类似功能。
数据并不总以易于查询的格式存储。世界上大量的数据存储在 CSV 文件中,其中许多文件的结构并不完善。尽管如此,大多数数据库厂商并不重视它们。在 BigQuery 中,我编写了我们的第一个 CSV 拆分器,但当问题比预期更为棘手时,我们派了一名刚毕业的工程师来解决这个问题。但实际效果并不理想,不能进行推断,如果不同的文件模式稍有不同就会很麻烦。事实证明,CSV 解析实际上非常难。
如果两位工程师使用两个不同的数据库读取 CSV 数据并计算结果,那么导入 CSV 文件最轻松的那个则最有可能先得到答案,此刻可以忽略掉数据库执行查询速度有多快。因此,可以将 CSV 文件推断视为一种性能特性。
数据库处理结果的方式对用户体验有巨大影响。例如,很多时候,人们会运行 SELECT * 查询来试图理解表中的内容。根据数据库系统的体系结构,该查询可以瞬间完成(返回第一页和游标,如 MySQL),对于大表可能需要数小时(如果必须在服务器端复制表,如 BigQuery),或者可能耗尽内存(如果尝试将所有数据拉取到客户端)。客户端是否与服务器建立了长时间连接,这可能会遇到网络停顿?或者它们进行轮询,这意味着查询可以在轮询周期之间完成,从而使查询看起来更慢?
吃不到葡萄说葡萄酸?
我是 DuckDB 公司 MotherDuck 的联合创始人。本篇博客可能听起来像是某人在研究一个开发速度不快、基准测试成绩不佳或不注重性能的数据库时写的东西。因此,我应该提一下, DuckDB 的速度很快。我不会花太多时间为 DuckDB 的性能辩护,但是 DuckDB 在 ClickBench 中的一些机器(例如 c6a.4xlarge)和 h20.ai 上的大多数基准测试中排名都很靠前。而且,DuckDB 在 TPC-H 和 TPC-DS 上的表现也不赖。
如前所述,你的体验可能会有所不同!所以在你选择数据库时,最好先在你的工作负载上测试一下。不要仅仅靠基于流行度或普遍认知来做出决策。
总 结
最成功的数据库公司,不是靠性能快过竞争对手而成功。Redshift 曾经风靡一时,但让 Snowflake 撬开市场的是可维护性,而不是性能基准测试。那些以性能为主要卖点的数据库在市场上表现不佳,而那些让客户工作更容易的数据库却表现更好。
总而言之:
查询速度更快当然比慢好。但是,如果你正在选型数据库,最好也将速度之外的其他因素纳入考量来做决策。