Igor Suhorukov:我的 PostgreSQL 比你的更快,而且几乎追上了 ClickHouse

💡 原文英文,约2100词,阅读约需8分钟。
📝

内容提要

作者开发了pg_vexec向量化执行器、ch_table_engines(将ClickHouse的MergeTree引擎接入PostgreSQL)和iheap(原地更新表访问方法),均无需修改内核。在ClickBench测试中,PostgreSQL 19查询耗时从715毫秒降至49.9毫秒,仅比ClickHouse慢约3倍,而原生PostgreSQL慢39倍。作者认为多数项目无需维护多种数据库,PostgreSQL足以胜任。

🔎

延伸解读

性能提升的关键不在向量化本身

文章揭示了一个反直觉的发现:单纯引入向量化执行器(pg_vexec)在堆表上仅带来约18%的提速,因为函数内核只占执行时间的0–2%,而宽行解构和页面复制才是主要瓶颈。真正的飞跃来自将ClickHouse的MergeTree引擎作为表访问方法接入,使数据按列读取并跳过无关页面。这提醒读者,优化分析查询时,存储格式与数据访问路径往往比执行器本身更关键。

无需修改内核的工程取舍

作者强调所有扩展(pg_vexec、ch_table_engines、iheap)均未修改PostgreSQL内核,而是利用标准扩展机制实现。这降低了升级和维护成本,但也带来限制:例如MergeTree需静态链接大量子模块,且因PostgreSQL多进程模型需额外适配。这种“不fork内核”的路线适合希望保持生态兼容的团队,但可能牺牲部分极致性能或增加扩展自身的复杂度。

iheap对更新密集型场景的意义

iheap通过原地更新和undo日志避免表膨胀,解决了PostgreSQL长期存在的UPDATE产生死元组问题。文章指出,其undo存放在表的主fork中,因此WAL、崩溃恢复、复制和备份行为与普通表一致。对于需要频繁更新且同时运行长事务的系统,iheap可减少autovacuum压力,但读者需注意它仍是扩展实现,且文章未提供与原生堆表在并发更新下的详细对比数据。

适用边界与实测局限

作者在笔记本上对1000万行数据测试,PostgreSQL 19加扩展后几何平均查询耗时49.9毫秒,约为ClickHouse(16.8毫秒)的3倍,而原生PostgreSQL慢39倍。这一结果基于ClickBench单节点场景,未涵盖多节点、超大规模或混合负载。文章也承认,若数据规模达到大型强子对撞机或谷歌级别,专用数据库仍有必要。因此,该方案更适合中小规模、需统一事务与分析的项目,而非替代所有专用系统。

❓

Q&A

Igor Suhorukov 开发了哪些 PostgreSQL 扩展?它们分别解决什么问题?

他开发了三个扩展:pg_vexec(向量化执行器,提升查询处理速度)、ch_table_engines(将 ClickHouse 的 MergeTree 表引擎接入 PostgreSQL,用于分析型存储)、iheap(原地更新表访问方法,避免表膨胀)。三者均无需修改 PostgreSQL 内核。

在 ClickBench 测试中,PostgreSQL 19 配合这些扩展的查询性能相比原生 PostgreSQL 和 ClickHouse 如何?

在 1000 万行数据上,PostgreSQL 19 配合扩展的几何平均查询时间为 49.9 毫秒,仅比 ClickHouse 的 16.8 毫秒慢约 3 倍;而原生 PostgreSQL 慢 39 倍。相比最初堆表无向量化的 715 毫秒,查询时间大幅降低。

为什么仅靠向量化执行器(pg_vexec)在堆表上提升有限?

因为堆表按行存储,读取时需整页加载,且表 API 一次只返回一行,无法按列读取或跳过不需要的页。性能分析显示,行解构和页复制消耗了大量 CPU 周期,而函数内核仅占 0–2%。因此向量化在堆表上仅带来约 18–19% 的提升。

iheap 表访问方法如何避免 UPDATE 导致的表膨胀?

iheap 在原地覆盖同一 TID 的行,旧版本写入 undo 日志,仅当读者的快照需要时才重建。undo 存放在表的主 fork 中,WAL、崩溃恢复、复制等照常工作。行锁也是 undo 记录,因此没有 MultiXact 和冻结问题。索引更新时只修改键变化的索引,避免全索引更新。

ch_table_engines 是如何将 ClickHouse 的 MergeTree 集成到 PostgreSQL 中的?

作者静态链接了 MergeTree 所需的约 28 个 ClickHouse 子模块,生成 libchte_engine.so,并解决了多进程访问冲突(PostgreSQL 每个连接一个进程,而 MergeTree 原为单服务进程模型)。通过 CREATE TABLE ... USING mergetree 即可使用,但必须配合 pg_vexec 向量化执行器才能发挥性能,否则 MergeTree 甚至比堆表还慢。

作者认为在什么场景下使用 PostgreSQL 配合这些扩展比维护多种数据库更合适?

对于需要跨多表 JOIN、系统内数据一致性、且不想维护多种数据库(如 PostgreSQL、ClickHouse、Elasticsearch、MongoDB)的日常项目,PostgreSQL 配合扩展足以胜任。除非数据规模达到大型强子对撞机或谷歌的级别,否则专用数据库带来的开发和维护复杂性不值得。

🏷️

标签

➡️

继续阅读