Postgres 17 与 18 版本性能对比
Postgres 18 于数周前发布,其带来的改进引发了广泛热议。最值得关注的是,Postgres 18引入了io_method配置选项,使用户能够更精细地控制磁盘I/O处理方式。
将该选项设为sync时,行为与17及更早版本一致,所有I/O均通过同步请求处理。
18版本新增两种替代方案:worker和io_uring。worker(新默认值)会让Postgres使用专用的后台工作进程处理所有I/O操作。io_uring因性能优势备受期待,它利用Linux的io_uring接口实现所有磁盘读取的异步处理,有望显著提升I/O性能。
我们通过详细基准测试对比了Postgres 17与18的性能表现,验证这些改进是否名副其实。
基准测试配置
测试采用sysbench执行。由于io_uring优化仅适用于读取操作,本文将重点关注oltp_read_only基准测试。该测试涵盖点查询以及由--range_size参数控制的范围扫描和聚合查询。虽然同时测试写入及读写混合性能也很有意义,但专注于只读场景有助于聚焦讨论重点。数据规模设定为TABLES=100且SCALE=13000000,生成约300GB数据库(100张表,每张含1300万行)。
测试在四种EC2实例配置上进行:
| Instance | vCPUs | RAM | Disk | Disk type | IOPS | Throughput |
|---|---|---|---|---|---|---|
| r7i.2xlarge | 8 | 64 GB | 700 GB | gp3 | 3,000 | 125 MB/s |
| r7i.2xlarge | 8 | 64 GB | 700 GB | gp3 | 10,000 | 500 MB/s |
| r7i.2xlarge | 8 | 64 GB | 700 GB | io2 | 16,000 | – |
| i7i.2xlarge | 8 | 64 GB | 1,875 GB | NVMe | 300,000 | – |
所有实例均运行于相同(或高度相似)的英特尔CPU平台。我们纳入i7i实例以展示Postgres在高速本地NVMe驱动器上的性能潜力。此配置正是我们PlanetScale Metal所采用的方案,在Postgres 17环境下已取得卓越性能成果。许多其他云服务商仅提供网络附加存储方案,而我们同时支持两种存储模式。
每台服务器在基准测试前均经过10分钟查询负载预热。
针对每种配置,我们分别运行sysbench oltp_read_only基准测试5分钟,配置如下:
- 单连接且
--range_size= 100 - 10 个连接且
--range_size= 100 - 50 个连接且
--range_size= 100 - 单连接且
--range_size= 10,000 - 10 个连接且
--range_size= 10,000 - 50 个连接且
--range_size= 10,000
这导致总共产生 24 个独特的 5 分钟基准测试运行。这 24 种配置各运行了四次!一次在 Postgres 17 上,另三次分别在 Postgres 18 的 io_method=worker、io_method=io_uring 和 io_method=sync 模式下。由此形成96种基准组合。尽管如此,请尽管说我疯了!
这是极度依赖I/O的工作负载。数据规模(300 GB)远超内存容量(64 GB),因此执行查询时将产生大量磁盘访问。
单连接模式
尽管单连接模式不符合实际生产环境,但它能为不同I/O设置对直线性能的影响提供基准参考。让我们评估在此模式下可达的QPS值。
下图展示了所有单连接运行中--range_size设为默认值100时的平均QPS。这意味着完整读取负载由点查询与100行序列扫描/聚合查询组合构成。

以下几点值得注意:
- 在网络附加存储(gp3、io2)环境中,Postgres 18的
sync和worker模式表现明显优于17版本及18的io_uring模式。我承认这出乎意料!原本预期io_uring至少能与所有选项持平甚至更优。 - gp3甚至io2的延迟差异是导致结果差异的关键因素。在配备低延迟本地NVME驱动器的实例上,所有配置方案的性能差距显著缩小。
- gp3乃至昂贵的io2驱动器的延迟/IOPS成为性能瓶颈。本地磁盘在所有配置中均表现更优。
- 对于短时查询的线性性能,Postgres 18 明显更快。欢迎这些改进!
以下是相同测试但使用 --range_size=10000 的结果。这意味着工作负载包含更大规模的扫描/聚合操作,导致更多顺序I/O操作和更低的QPS:

本地磁盘性能依然明显领先,但其余三种方案的差距已不那么显著。这主要源于:(a) 更高的顺序I/O操作,但更关键的是(b) 更高的CPU负载(聚合10k行数据比聚合100行更耗CPU)。此外,Postgres 17与18版本间的性能差距已大幅缩小。
下方交互式图表对比了所有实例类型在Postgres 17下的结果与Postgres 18中性能最佳的workers实例。点击缩略图可添加或移除图表线条,比较不同组合。数据基于10秒采样率生成。
高并发场景
实际应用中常存在大量并发连接与同时读取操作。让我们观察各服务器在50个连接的高负载环境下执行相同基准测试的表现。
当然,oltp_read_only 无法完全模拟真实的 OLTP 工作负载(尤其未包含写操作),但我们将其作为高读取需求场景的替代方案。下表展示了所有 50 连接 oltp_read_only 测试(--range_size=100)的平均 QPS 值。

在高并行度和增加的I/O需求下,以下几点变得清晰:
- 对于所有EBS支持的实例,IOPS和吞吐量都是明显的瓶颈。在这种情况下,不同版本/I/O设置的差异并不显著。
- 随着EBS性能提升,QPS呈同步增长趋势,本地NVME实例表现优于所有其他实例。
- 在所有EBS实例中,启用
sync和worker的Postgres 18版本以微弱优势获得最佳性能。
再次进行相同基准测试,但使用--range_size=10000参数。

gp3-10k和io2-16k实例性能已逼近本地磁盘水平。但这源于本次基准测试更侧重CPU而非I/O限制,因此本地磁盘的低延迟优势减弱(尽管仍是最佳选择!)。关键在于,我们终于迎来io_uring胜出的场景!在 NVMe 实例上,其性能略优于其他选项。
下面我们再次比较 Postgres 17 和 Postgres 18 中的这些结果,涉及 worker 数量。点击缩略图可在图表中添加或移除行,比较各种组合。
中等并发
相同基准测试在10个并发连接下运行。结果基本一致故不全部展示,但需特别指出--range_size=100条件下的图表:

请仔细观察首组柱状图(对应gp3-3k)。io_uring设置的性能明显逊于其他配置。但当连接数为50时,该配置在同等条件下的表现仅略逊于其他方案。这表明io_uring在高I/O并发场景下表现优异,而在低并发场景中优势不明显。
成本
比较基础设施配置时,成本始终是关键考量因素。以下是AWS中各服务器配置的按需成本:
r7i搭配 gp3 3k IOPS 及 125 Mbps:$442.32/月r7i搭配 gp3 10k IOPS 及 500 Mbps:$492.32/月r7i搭配 io2 16k IOPS:$1,513.82/月i7i搭配本地 NVMe 磁盘(无 EBS):551.15 美元/月
请注意,前三种配置仅提供 700 GB 存储空间,而 i7i 配备 1.8 TB 卷!采用本地 NVMe 磁盘的服务器无疑是性价比之选。
为何io_uring未能胜出?
鉴于我对Postgres 18新增io_uring功能的期待,本以为它能在更多场景中胜出。实际情况为何如此?
首先,这是非常特定的工作负载类型。它仅限读取操作,且同时包含点查询、范围扫描和范围聚合操作。io_uring在其他工作负载场景中必然能展现优势。此外,通过调整postgresql.conf参数,我们或许能看到io_uring的性能提升。
在撰写本文时,我偶然发现了Tomas Vondra的精彩博文,其中探讨了新的io_method选项、调优方法以及各选项的优缺点。他针对workers为何能超越io_uring给出了若干精辟见解,强烈建议您阅读原文。简而言之:
- 索引扫描(目前)尚未启用AIO。
- 尽管
io_uring将I/O操作移至后台执行,但校验和计算/内存复制仍可能成为瓶颈。 - 从单进程视角看,
workers能实现更高效的I/O并行处理。
因此确实存在io_uring未必更优的合理场景!期待看到更多涵盖不同工作负载类型的配置基准测试。测试使用的多数配置可在附录中查阅。
结论
尽管范围有限,这次对比 Postgres 版本与 I/O 设置性能的实验仍颇具趣味。我的核心发现包括:
- Postgres 18 带来了显著的 I/O 性能提升和配置灵活性。维护团队做得很好!
- 本地磁盘表现明显优于其他方案。当具备低延迟I/O和海量IOPS时,其他因素影响较小。这正是PlanetScale Metal能实现业界顶尖数据库性能的原因。
- 新默认值
io_method=worker是明智选择。它兼具io_uring的诸多“异步”优势,却无需依赖特定内核接口,并可通过设置io_workers=X进行精细调优。 - 不存在万能的最佳I/O配置方案。
- 尽管有所改善,新的
workersI/O配置对网络附加存储场景的助益仍不及预期。
您还希望看到哪些基准测试?欢迎联系我们告知需求。
附录:配置文件
以下是本次基准测试中使用的关键定制化 Postgres 配置选项:
shared_buffers = 16GB # 25% of RAM effective_cache_size = 48GB # 75% of RAM work_mem = 64MB maintenance_work_mem = 2GB wal_level = replica max_wal_size = 16GB min_wal_size = 2GB wal_buffers = 16MB checkpoint_completion_target = 0.9 random_page_cost = 1.1 effective_io_concurrency = 200 default_statistics_target = 100 max_worker_processes = 8 max_parallel_workers_per_gather = 4 max_parallel_workers = 8 max_parallel_maintenance_workers = 4 bgwriter_delay = 200ms bgwriter_lru_maxpages = 100 bgwriter_lru_multiplier = 2.0 autovacuum = on autovacuum_max_workers = 4 autovacuum_naptime = 10s autovacuum_vacuum_scale_factor = 0.05 autovacuum_analyze_scale_factor = 0.025 logging_collector = on ...more log configs... shared_preload_libraries = 'pg_stat_statements' track_activity_query_size = 2048 track_io_timing = on jit = on # io_workers left at default = 3
本文文字及图片出自 Benchmarking Postgres 17 vs 18

据我所知,此基准测试中没有任何内容会在18版实际使用AIO。截至18版,仅序列扫描、位图扫描、vacuum及少数实用命令支持AIO读取。但当前执行的查询通常应规划为索引范围扫描。我们希望在19版中实现索引扫描的AIO支持,但该功能也可能推迟至20版,这并非易事。
另需注意数据校验和的默认设置已变更,由此产生部分开销。
这解释了为何`sync`和`worker`在几乎所有运行中结果如此接近。而Tomas Vondra的基准测试(https://vondra.me/posts/tuning-aio-in-postgresql-18/)显示出显著差异。
若基准测试未使用AIO,为何博客文章中PG 17与18的性能存在差异(sync、worker和io_uring测试)?
是否因为云端远程存储始终引入波动性,而基准测试恰好捕捉到了这种波动?
参考信息:anarazel昨日在pgconf.eu大会上发表了关于AIO的演讲。他提到远程云存储必然引入波动性,导致基准测试结果难以解读。其解决方案是在本地NVMe上引入合成延迟进行测试。
那么io_uring AIO模式的性能不足就更令人费解了。
确实如此。我尝试复现但未成功。
我怀疑这可能只是在性能特征略有差异的不同虚拟机上执行的结果。根据帖子中的描述,我无法判断同一测试的所有运行是否都在同一台虚拟机上执行。
误差条去哪了?我不明白为什么大家跑这么多测试却不提供标准差数据,也不说明差异是否具有统计学意义。
我从中获得的核心教训是:
若注重性能,请勿使用网络存储。
若使用本地 NVMe 硬盘,Postgres 17 或 18 版本差异微乎其微。性能基本持平,且远超网络存储。
但存在临时性和非冗余性问题。
在任何 VPS 上使用本地硬盘是否都存在持久性隐患?
是的,短暂性才是最大问题。企业级SSD相当可靠,通常配备PLP(电源中断保护),即使突然断电,驱动器已接受并确认fsync()的队列写入操作仍会完成。假设您会部署某种冗余方案,可能是RAID或zRAID(此处假设纯本地存储,非Ceph等分布式系统或同步复制)。
但在云环境中,若实例背后的物理服务器故障,甚至有人误发关机命令,新实例启动时您将无法恢复原有磁盘。因此原本可通过本地冗余解决的问题突然变得不可行,你必须选择:要么采用同步或半同步复制(PlanetScale Metal采用后者),承受分布式存储带来的延迟损失;要么选择异步复制并接受一定数据丢失风险——后者通常难以接受。
认同这些权衡。我们根据Postgres或MySQL的不同,同时采用同步和半同步复制。
…对裸机实例而言这似乎是件小事
EC2本地NVMe加密密钥采用临时机制虽能防范泄露,但对其他云平台并非必需(且不利于恢复能力,可能显著降低业务连续性评分)。以他们收取的费用来看,我期待即使在重启后也能保持相对安全性
甚至裸机服务器搭配冗余NVMe SSD运行数据库也行
Postgres这类数据库早有成熟方案处理此类问题。若自行搭建数据库,备份本就是必需操作,还需在不同服务器部署副本。
备份无法解决持久性问题,读副本(异步)同样如此。
我认为唯一可行的方案是实现类似Planetscale的同步复制,但这相当艰巨。
某些服务商(如Hetzner)的专用服务器默认配备双RAID 1磁盘阵列,因此故障概率极低(除非数据中心发生火灾)。
有法国来电,某家OVH公司正在拨打!
你的备份也会灰飞烟灭。
我绝不会把重要数据或服务器托付给OVH,毕竟我们都目睹过他们数据中心的“安全措施”——整栋楼着火时,他们花了3小时才切断电源。
是的,VPS或云服务商中的单个磁盘确实存在耐久性问题。正因如此,EBS这类伪装成单磁盘的产品实际上由多个磁盘组成。不过我们并未依赖多个块设备,而是通过更高层级的冗余机制实现:采用多台MySQL或Postgres服务器保障耐久性,每台服务器都配备本地NVMe驱动器以提升性能。
确实如此。在一定程度上。若运行关键任务型应用,则绝对如此。
但多数应用在本地存储上运行良好,且能承受一定停机时间。性能提升甚至可能带来益处。您也可通过配置RAID/ZFS并保持完善备份来解决耐久性与灾难恢复问题。
没错,PlanetScale总爱炫耀其速度优势,但核心原因在于他们比其他云服务商运行更少的完整抽象层,这确实存在取舍。
减少抽象层有什么问题?我们清楚其弊端。结果摆在眼前,客户显然青睐这种模式。我们在临时计算环境中安全运行海量状态数据——这才是真正的实力展示。Timescale团队除了抱怨毫无建树。要么写代码,要么闭嘴。
我完全不批评你们的工程方案。单节点运行确实有优势,你们的基准测试也证明了这点,但这并非同等条件下的比较——还存在其他权衡因素。我只是赞赏社区能指出这些问题。
另外,这里是HN而非推特,我觉得我们可以更文明些。CEO因无害评论如此动怒,在我看来实在有失体面。
我们运行的是3个节点而非1个。你的评论并非孤例——即便我们根本没考虑你们,Timescale团队也总在暗讽我们。
单盘方案确实存在耐久性隐患。但VPS与独立服务器之争我实在看不出多大意义。
顺便提一句,RAID也不是万能解。在AWS和GCP环境中,即便堆砌再多RAID阵列,一旦CPU或内存故障,本地NVMe驱动器同样会失效。
我们已通过多重方案缓解了耐久性问题。
正确。网络存储能灵活适配多种场景,因此PlanetScale同时支持两种方案。
我的理解是否正确:若运行在NVMe环境下——其速度如此之快,选择何种模式其实无关紧要?
我通过分析图表也得出了相同结论。
我认为更优的IO规划仅对18版本中的“低速”I/O有价值。
相信这将带来大量经验积累。Postgres开发者团队非常出色。
拼写错误?应该是*解释吧?
云服务简直离谱。
仅供参考:用4块消费级NVMe组建RAID10并接PCIe x16接口,单次成本约1000美元就能轻松实现300万IOPS
在当前工作中,我们不得不不断重构数据库查询/设计方案,只因云端IOPS限制,更别提无法掌控RDS页面缓存和Numa架构。
每当深夜被惊醒——某条看似正常的查询突然突破IOPS预算导致WAL日志崩溃时,我总会深刻质疑自己的选择。
整个云计算生态简直荒谬至极。
你购买RDS并非因为在意IOPS,而是为了将备份和复制问题转嫁给他人。更重要的是(这里指的可能是你上级的MBA管理层而非你本人),你们更关注将其列为运营支出而非资本支出,远胜于成本本身。当然,ISO审计的合规要求也是原因之一。
若想将自有硬件转为运营支出,直接租赁即可。所有企业级硬件供应商都会提供此类方案。
> 你为此付费,是因为希望备份和复制成为别人的问题。
或者直接采用CockroachDB、YugabyteDB等自动复制、节点故障自动重平衡的数据库,它们还内置了S3备份功能…
若你更倾向亲力亲为,由MySQL Vitess开发者打造的Multigress项目似乎即将完成(https://github.com/multigres/multigres)。
认为管理软硬件很困难的想法很可笑,但人们(似乎主要是管理者)却认为这是最佳方案。
我不会说它接近完成——根据其代码库显示,项目仍处于非常早期的开发阶段。目前尚未发现任何证据表明他们甚至能通过该工具运行单条查询。
即便完成后,运行起来仍需大量工作。当然,这未必困难,但若非核心业务且能盈利,让他人代劳能让你专注于真正重要的事。
将月度云服务成本与一次性硬件采购成本相比较,完全忽略了后者长期涉及的人力、备件、电力、机房及配件等开销。虽然我承认自建硬件确实能大幅降低成本,但在决策前仍需权衡诸多因素。
但现在你需要有人来维护硬件。
天哪!这已被证明不可能实现,无人能指挥计算机行事
lspci仅记载于古老炼金术典籍,是三圣赫尔墨斯的秘语低语。
附注:我亲手扑灭过数据中心的真实火灾,比起这3000 IOPS的垃圾,我更怀念那份实干。
2000年代末在IT行业工作时,服务器机房仍很常见。即便大型机构分设数百公里外的多个站点,仅需小团队就能管理。据我所知,如今构建高可用应用比当年容易得多。
云成本已高到让我准备抽身而退,长期计划是回归自有服务器,将节省的资金投入人力。我预见云服务只会越来越贵,绝无降价可能。
当前正出现向物理基础设施回流的早期趋势。部分源于成本考量(1),部分出于地缘政治顾虑,部分则因性能需求。然而物理设备的管理确实需要企业应对另一套(虽显陈旧但已逐渐萎缩)的技能体系与成本结构。
(1) 令人震惊的是,当初推动企业迁移云端的主力竟是会计部门——他们追求运营支出而非资本支出,如今却因现金流压力考虑回迁。云服务在提供网页内容和海量数据存储方面表现优异,但一旦涉及数据处理或迁移,成本便会急剧攀升。
某些机构的云迁移由财务部门主导,而我们机构则是法律部门推动。随着《通用数据保护条例》生效在即,加之其他数据隐私法规可能(但未强制)要求数据存储于客户所在司法管辖区,我们必须在更多区域部署服务器。
我们拥有两座大型数据中心,但均位于美国。在欧盟地区仅有一间小型服务器机房作为基础设施。巴西、中国等地完全没有托管能力。多区域可用性迫使我们转向云端——但并非出于“高可用性”的考量。
> 我只看到云服务成本持续攀升,绝无下降可能。
当三大超大规模云服务商激烈竞争时,这种观点基本站不住脚,也不符合市场规律…除非他们开始串通定价。
正因这种竞争态势,三大供应商的网络服务成本已呈现下降趋势。
届时云服务将如此优质廉价,你会惊叹“天啊,我能以远低于AWS的价格出售闲置计算资源”。然后我会买下这些资源,你将成为新的云服务商。随后更多人效仿,最终这片服务器基础设施业务将远超你原有主业规模。十年后又会有人抱怨你的IOPS定价,开始自建服务器机房。
根本无需如此,租用专用服务器即可,成本仍低20-50倍,问题迎刃而解。
我用过的多数云平台都支持创建带本地磁盘的虚拟机,这可能比网络磁盘更划算。
帖子描述的是每月500美元的方案,拥有惊人的30万IOPS;而网络磁盘每月1500美元仅提供1.6万IOPS
更不用说还得自行处理备份、快照、复制等管理难题
本以为v18会为
pg_dumpall添加--format选项[0],但文档显示该功能目前仅在开发分支可用[1]是否有熟悉Postgres开发的同仁能更新该功能的进展?是否计划在未来版本(18或19)中实现?
[0]: https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit…
[1]: https://www.postgresql.org/docs/devel/app-pgdump.html#:~:tex…
18版的文档也显示该功能,你从何得出18版不可用的结论?
啊,是我搞错了,我链接的是
pg_dump的文档(该命令长期支持format选项),而非pg_dumpall(该命令不支持该选项)。在 Postgres 18 发布之前,文档曾将 `format` 列为即将推出的 18 版中 `pg_dumpall` 的选项(例如 2025 年 6 月的互联网档案馆记录 https://web.archive.org/web/20250624230110/https://www.postg…)。相关提交日期为2025年4月(见我原始评论中的链接#0)。但如今所有提及内容均已被清除,甚至开发分支文档中也未保留。
该变更现已被撤销:https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit…
趁此机会想提醒大家,Postgres的Vitess即将发布https://www.neki.dev/
现在是否有方法避免双缓冲并直接使用PostgreSQL的直接I/O?
有人认真测试过性能差异吗?
我认为在该设置下I/O配置不会产生影响,但出于好奇想了解——毕竟这是Oracle和Sybase的默认方案。
直接I/O功能正在开发中,但尚未开放。
详见此处:https://www.cybertec-postgresql.com/en/postgresql-18-and-bey…
我目前使用bitnami/postgresql:17.6.0-debian-12-r4在Docker容器中运行PostgreSQL。据我所知,Bitnami已停止支持和更新其Docker容器。请问升级到Docker版PostgreSQL 18有何推荐方案?
初步观察官方Postgres容器发现:-
POSTGRESQL_DATABASE已重命名为POSTGRESQL_DB– 卷挂载路径当前为/bitnami/postgresql建议采用两种方式:
PGDATA[1] 及pg_upgrade[2] 工具[1] https://hub.docker.com/_/postgres#pgdata
[2] https://www.postgresql.org/docs/current/upgrading.html#UPGRA…
我正在升级生产数据库到pg18版本。该数据库约6TB,每秒处理数千次查询,是否应该考虑使用'worker'模式替代'io_uring'模式?
既然尚未明确所有变更内容及配置参数,为何要迁移生产数据库?
对于本就风险较高的升级操作,我建议尽量减少变量数量。待升级完成并稳定后,可将io_method参数切换至新模式的副本实例进行测试,确认无误再切换主实例。
感谢分享这篇有趣的文章!不知是否也支持timescale扩展?
我们正在开发中。
是指timescaledb吗?还是其他方案…?
是的,就是指 timescaledb。抱歉之前没说明白。
图表效果真棒,想知道用了哪个库实现的。
看起来是 Recharts 库。