本文借鉴了官方 PostgreSQL 项目文档以及每个主要版本之后发布的两个技术分析:Microsoft 技术社区(Azure Database for PostgreSQL 团队)和 Crunchy Data。下图不是我们复制的基准:当数据来自第三方时,我们会注明其来源和日期。有关我们应用于自己测量的方法,请参阅我们的 基准测试方法支柱。
- Postgres 17 的主要优点是 VACUUM(TidStore 结构)的内存大改,它取消了 1 GB 左右的旧上限。官方发行说明表明在某些情况下使用的内存最多可减少 20 倍。
- Postgres 17 还减少了计算事务快照的争用,这尤其有利于多核硬件上的高并发实例。
- Postgres 18(2025 年 9 月下旬)引入了异步 I/O (AIO),这是几个主要版本中最具结构性的架构变化,特别是对于高延迟存储。
- Postgres 18 还添加了对多列 B 树索引的跳过扫描、默认虚拟生成的列以及对身份验证的 OAuth 2.0 支持。
- Aurabase 今天在生产中运行 Postgres 16.15,已在代码中验证:不是延迟,是与 CloudNativePG 下主要版本升级的不可逆转性相关的记录选择。
Postgres 16、17 和 18 之间真正的变化是什么
这三个版本没有单一的整体性能数据来区分。每个都修正了架构的特定点,每次都有不同的受众:Postgres 17 的大表,Postgres 18 的高延迟存储。下表总结了可验证的事实,所有这些事实都已过时,然后再详细介绍每个项目。
| 版本 | PostgreSQL 16 | PostgreSQL 17 | PostgreSQL 18 |
|---|---|---|---|
| 发售日期 | 2023 年 9 月 14 日 | 2024 年 9 月 26 日 | 2025 年 9 月底 |
| 大桌子上的真空吸尘器 | 数组中的死元组,内存上限 ≈ 1 GB | TidStore 结构(基数树),吊顶 | 继承17中引入的结构 |
| 输入输出 | 同步,逐块 | 用于分析和顺序扫描的流式 I/O | 通用异步 I/O (AIO),可配置 io_method |
| 并发连接数 | 快照计算的已知争用 | 减少争用(GetSnapshotData 已优化) | 继承17中引入的收益 |
| 多列B树索引 | 如果过滤器中缺少头柱,请完成扫描 | 与 Postgres 16 相同 | 跳过扫描:可以进行部分扫描 |
| 生成的列 | 仅存储 | 与 Postgres 16 相同 | 添加了 VIRTUAL,成为默认行为 |
| 认证 | SCRAM、LDAP、证书 | 与 Postgres 16 相同 | + OAuth 2.0(RFC 8628,设备流程) |
来源:PostgreSQL 项目的官方发行说明 (postgresql.org),与 Microsoft 技术社区和每次主要版本发布后的 Crunchy Data 发布的分析进行交叉引用。访问日期:2026 年 8 月 24 日。
VACUUM 的内存改革改变了大表的游戏规则
在 Postgres 17 之前,VACUUM 将要清理的死元组列表存储在一个简单的数组中,大小为 maintenance_work_mem。问题不在于计算速度,而在于结构本身:该表稳定在 1 GB 左右,无论配置超出该值多少。在具有超过 1.78 亿个死行的表上,VACUUM 必须多次循环,每次都重新读取整个索引。
Postgres 17 用名为 TidStore 的结构替换了这个数组,TidStore 是一种自适应基数树,它极大地压缩了存储元组标识符所需的空间。该项目的官方发行说明表明,在某些情况下,VACUUM 使用的内存最多可减少 20 倍,而无需与旧结构相关的人造天花板。资料来源:PostgreSQL 17 官方发行说明,postgresql.org,2024 年 9 月 26 日。Microsoft 技术社区和 Crunchy Data 在发布后不久各自发布了对此更改的技术分析。两者都证实了对具有高删除或更新率的数亿行表的具体兴趣。
该项目主要受益于一个特定的场景:删除或更新率较高的大表。由于缺乏可用内存,VACUUM 之前运行了几次。在小桌子上,或者在主要阅读负载上,增益仍然很小,甚至是看不见的。
高并发连接上的争用更少
第二个 Postgres 17 项目触及了一个更谨慎的点:事务快照的计算。每个查询都需要知道正在进行的其他事务,以强制执行 Postgres 的 MVCC 可见性规则。在具有大量内核和活动连接的计算机上,此计算会产生对共享内部结构的争用。这是项目贡献者长期以来记录的一个瓶颈。
Postgres 17 减少了这种争用。效果主要是在高并发实例上测量的,多核硬件上有许多同时活动的连接。在低并发负载下,与 Postgres 16 的差异仍然很小:它是一个可扩展性项目,而不是减少每个隔离请求的延迟。
这种增益并不会取代连接池,它只是降低了其内部成本。如果活动连接的数量已经成为您的瓶颈,那么主要版本就会退居二线。我们的 max_connections 调整指南 和我们的 PgBouncer 事务模式比较 更详细地探讨了这个主题。
异步 I/O:多年来最深刻的架构变化
Postgres 18 于 2025 年 9 月底发布,解决了一个更具结构性的问题。在此之前,每次 Postgres 磁盘读取都会阻塞请求它的进程。新的异步输入输出 (AIO) 子系统允许进程并行启动多个读取,并在读取完成时继续工作,而不是按顺序等待每个读取。
io_method 参数控制此行为:worker (专用于 I/O 的进程,默认)或 Linux 上的 io_uring(当使用此支持编译 Postgres 时)。顺序扫描、位图堆扫描和 VACUUM 是第一个受益者,特别是在高延迟存储上:网络磁盘、云卷,而不是本地 NVMe。
PlanetScale 提供托管 Postgres 产品,并发布了自己的 Postgres 17 与 18 比较,重点关注此 I/O 更改。这些是他们对自己的基础设施的测量,而不是我们在这里独立复制的数字。将其视为一个信号,表明该主题值得在您的实际负载上进行测试,而不是作为通用百分比。
Postgres 18 的通用 AIO 延续了 Postgres 17 中启动的项目,而不是一个孤立的更改。版本 17 已经引入了流 I/O 接口,但仅限于 ANALYZE 和顺序扫描。 Postgres 18 将相同的逻辑扩展到更广泛的操作范围,包括 VACUUM 和位图堆扫描。因此,这两个版本被视为一个进展,而不是 I/O 上的两个单独的赌注。
其他重要的变化
其他三个 Postgres 18 更改也值得监控,即使它们不直接解决原始性能问题。
多列 B 树索引上的 跳过扫描 允许 Postgres 使用复合索引,即使查询未在其头列上进行筛选也是如此。在 Postgres 18 之前,这种情况通常需要对表进行完整扫描,或者创建额外的专用索引。
当未指定 STORED 时,生成的虚拟列 (GENERATED ALWAYS AS (...) VIRTUAL) 将成为默认行为。虚拟列是在读取时计算的,而不是写入磁盘,这减少了每次插入或更新源行时的写入量。
Postgres 18 最终在身份验证方面(RFC 8628、设备流)添加了对 OAuth 2.0 的支持,以及 SCRAM、证书或 LDAP 等现有机制。对于任何已经通过外部 OAuth/OIDC 提供商集中其身份的组织来说,这是一个相关点。
为什么 Aurabase 仍然在 Postgres 16 上运行,以及什么会改变这个选择
在 Aurabase,租户数据库当前在 Postgres 16.15 中运行,而不是 17。这可以直接在存储库中进行验证:参考 CNPG 映像 (docker/Postgres.CNPG.Dockerfile) 从 ghcr.io/cloudnative-pg/postgresql:16-standard-bookworm开始,由摘要固定,与共享层 (docker/Postgres.Dockerfile) 具有相同的主要版本。验证日期:2026 年 8 月 24 日。
代码还记录了原因。 k8s_tenant.rs 中的更正注释解释了早期的回退错误地指向 postgresql:17.2。当时给出的理由是标准镜像不会包含pgvector,经核实是假的。两个图像的 pgvector:在 17.2 上为 0.8.0,在 16-standard-bookworm 上测量为 0.8.5。
评论本身记录的真正风险在其他地方:一旦创建集群,CloudNativePG 就会禁止任何主要版本降级。在 Postgres 17 中错误配置的机群将是不可逆转的,而在 Aurabase 端到端验证的所有内容都在 Postgres 16 中。
这并不是对 Postgres 17 本身的判断。这是一项谨慎操作的政策:在进行端到端验证之前,不要将生产队列切换到主要版本。同样的推理适用于任何通过 CloudNativePG 或等效 Kubernetes 操作员管理 Postgres 的团队。问题不仅在于预期的性能提升,还在于出现问题时的返回路径。
PostgreSQL 不提供主要版本降级。 pg_upgrade 仅在一个方向上迁移,CloudNativePG 在其运算符级别应用相同的约束。唯一的恢复方法是恢复更新之前的备份,或者从旧版本的新实例开始。
您现在应该迁移到 Postgres 17 还是 18?
三个标准使得无需等待通用数字即可做出决定。首先,最大表的大小和突变率:如果 VACUUM 已经在多次运行中运行,则 Postgres 17 内存工作站点直接适用于您的情况。然后,您的存储:在低延迟本地 SSD 上,Postgres 18 提供的异步 I/O 少于网络卷上的异步 I/O。最后,返回:对于禁止重大降级的操作员,首先在一次性环境中进行测试并不是一种可选的预防措施。
具体来说,同样的规则适用于 Kubernetes 运营商管理的任何队列。首先在目标版本中配置一个测试集群,然后在其上重放代表您的生产的负载。仅在该测试经过端到端验证后才接触实际集群,而不仅仅是阅读发行说明。如果您的决定还涉及在专用基础和共享基础之间进行选择以吸收此类更改,我们的文章 专用与共享基础 探讨了这个角度。
我们最常被问到的问题
性能比可逆性更重要
Postgres 16、17 和 18 之间的选择不仅仅是哪个版本“最快”。 Postgres 17 修复了大型表上真正的结构性 VACUUM 问题,并减少了高并发时的争用。 Postgres 18 在异步 I/O 方面更进一步,这是一种架构更改,需要在推广之前对实际负载和存储进行测试。
最常被遗忘的标准不是性能,而是可逆性。在像 CloudNativePG 这样的运营商上,主要版本升级在事后不会撤消。在切换生产车队之前,真正的问题不仅是预期收益,而且是测试失败后的返回路径。如果您正在准备此版本升级,我们的 Postgres 生产中的调整清单 详细介绍了主要版本更改后重新验证的设置。