一个用Rust重写Postgres执行引擎的项目pgrust,上周放出了0.2版本,甩出一组扎眼的数字:比自己的上一版快10倍,在OLTP负载上比原生Postgres快30%,在ClickHouse维护的分析型基准ClickBench上比Postgres快300倍——顺带把ClickHouse也甩在了后面。作者用一个五亿行浮点数求和的查询做示范:Postgres跑了约20秒,等价的Rust原生循环只要358毫秒,快了55倍左右。
这组数字里,真正扛得住推敲的部分是查询引擎的优化——通过批处理、算子融合和SIMD,作者把一个精简版Postgres执行器从1.3秒压到135毫秒,贡献了约10倍提速,逻辑清楚、代码可读、原理站得住。但“整体300倍”和“超越ClickHouse”这两句话,牵扯的东西比查询引擎优化本身多得多——它们建立在一场热缓存、单机、简化查询集的benchmark上,而这类benchmark历来是数据库圈里最容易被过度解读的东西。
从磁盘时代走出来的执行器,省的是哪部分开销
Postgres的执行器诞生于上世纪80年代磁盘I/O还是主要瓶颈的年代,用的是经典的“Volcano模型”:每个算子的next()方法一次只吐出一行,层层调用、层层判断。这套设计在磁盘慢、内存贵的年代很合理,但过去十年三件事把局面倒过来了——内存价格下降让不少数据集能整个塞进RAM,分析型负载的瓶颈从磁盘吞吐挪到了CPU和内存带宽,NVMe又把磁盘本身的速度拉快了几百倍。逐行调用的开销,在这个新环境里显得格外碍事。
批处理把逐行调用换成整批处理,省掉大部分函数调用和分支预测失败的成本,时间从1.3秒降到480毫秒。算子融合把扫描和求和硬编码成一个节点,跳过中间结果的内存拷贝,降到358毫秒——作者也承认这是“作弊”,真实场景里查询千变万化,靠人工硬编码撑不住,得靠JIT编译动态生成融合后的代码,这部分pgrust留到了下一篇再讲。最后上SIMD,让CPU一条指令同时处理多个浮点数,时间压到135毫秒,这也是作者说“查询引擎贡献了300倍里约10倍”的来源。
这一段的可信度是高的:三种优化手法都是数据库圈子里成熟的共识做法,DuckDB、ClickHouse、DataFusion这些新一代分析引擎走的也是同一条路——用批处理和列式内存布局取代逐行迭代。pgrust把这套思路搬进Postgres执行核心,方向没问题。
剩下的20多倍,出在哪里没人细说
真正让人皱眉的,是“300倍”里剩下的那20多倍从哪儿来——原文没有拆解。ClickBench由ClickHouse自己维护,标准配置是约一亿行网络分析数据、43条分析型SQL查询,运行环境是c8g.4xlarge(Graviton4架构,16个vCPU、32GiB内存)这样的ARM实例。它的规则里藏着一个容易被忽略的条款:条目可以使用数据库特定的调优、索引、分区甚至改写过的SQL,一个经过精心调优的Postgres条目,未必能代表默认配置下普通用户跑出来的Postgres。
更关键的问题是:pgrust在ClickBench里读取的数据,到底是Postgres原生的堆表格式,还是转换成列式布局之后的结果?如果是后者,300倍里有多少该算给“查询引擎重写”,有多少该算给“把数据换成了列式存储”——这是两件性质完全不同的事,前者是执行层优化,后者相当于换了存储引擎。原文把功劳全记在查询引擎账上,这个归因目前站不住脚,至少缺少证据支撑。
- 提醒.把执行器优化和存储格式转换混在一起算成一个数字,是数据库benchmark最常见的水分来源。
“超越ClickHouse”忽略了ClickHouse真正的强项
ClickHouse跑得快,靠的不只是执行器。压缩列存、稀疏索引、MergeTree排序键、分布式执行,这些存储层和调度层的设计才是它在真实海量数据场景里的核心优势。ClickBench的热缓存单机测试,恰好是这些优势发挥最不充分的场景——数据都在内存里,用不上磁盘I/O优化,也用不上跨机调度。pgrust在这种场景下领先,说明“简单扫描+聚合”这类查询它的执行器做得干净,但不能倒推成全面超过了ClickHouse。
跑分领先的场景,往往正是对手优势发挥最少的场景
原文自己也留了一条诚实的尾巴:作者主动说20秒对358毫秒的对比“不是苹果对苹果”,Postgres真正慢在锁机制和存储格式解析上,而不单是执行器逐行调用。这句自我修正值得留意,它和外界的质疑方向是一致的——存储层和执行层的开销被混在一起讲了。
谁该盯着看,谁不用急着换
对拿Postgres跑分析查询的团队来说,pgrust现在的证据只够支撑一句谨慎判断:简单的扫描、过滤、聚合查询,执行器换成批处理加SIMD确实能省下真实CPU开销,这个结论可以信。但连接、高基数分组、窗口函数、字符串和decimal处理、内存溢出这些更复杂的负载下pgrust表现如何,原文没有覆盖,也没有公开per-query的完整结果和可复现脚本。真想拿pgrust替换现有分析型数据库的团队,等下一篇关于JIT编译的说明和更广的负载测试出来,比现在下注划算。
Postgres生态里用Rust重写执行核心这条路子本身没问题——性能压力摆在那儿,磁盘时代的设计确实该改。但一份自己发布、自己解释、自己挑场景的benchmark,终究只是候选答案,不是终审判决。
