PostgreSQL 18 Vacuum 清理核心升级:更快、更智能、更可预测

John Doe 八月 7, 2026

PostgreSQL 18 带来了近年来最重要的一次 Vacuum 和 Analyze 功能升级。

目录

image

核心观点与关键结论

通过引入异步 I/O、动态 Worker 扩展、废弃元组硬性上限控制、主动冻结(Eager Freezing)等核心特性,PG18 彻底解决了过去在高延迟存储、超大表清理以及主从延迟等场景下的历史痛点,使数据库的 Vacuum 机制变得更快速、更智能、更具可预测性。

为什么 Vacuum 如此重要?(前置背景)

在深入了解 PG18 的新特性前,必须明确 Vacuum 在 PostgreSQL 中的核心生命线作用:

  1. 回收存储空间:清理被更新(Update)和读取操作产生的废弃元组(Dead Tuples),防止表膨胀。
  2. 防止事务 ID 回卷(Wraparound):避免数据库因事务 ID 耗尽而强制进入只读状态(紧急故障)。
  3. 保证查询性能:包含的 ANALYZE 操作能更新查询规划器的统计信息,确保查询执行的最优路径。 如果 Autovacuum 调优不当,将导致表膨胀、查询性能下降,甚至引发回卷紧急情况。

旧版本痛点 VS PG18 解决方案(核心对比)

痛点问题(PG18 之前) 解决方案(PG18 及以后)
同步 I/O 阻塞:清理时需同步等待 I/O 完成,影响效率。 全新的异步 I/O 子系统:支持预读取,显著提升清理速度。
扩展需重启:修改 autovacuum worker 数量需整机重启。 动态调节:支持在运行中(On-the-fly)随时增减 worker。
大表隐性膨胀:无硬性清理阈值,大表可能积累上亿废弃元组才触发清理。 引入硬性上限限制(Hard Caps):达到指定数量后立即触发。
I/O 风暴:常规清理跳过全可见页,防回卷(Anti-wraparound)时引发剧烈 I/O 消耗。 主动冻结(Eager Freezing):将冻结操作平摊到常规清理中。
分区表清理繁琐:继承式分区表需手动分别清理子表。 默认递归清理:父表的 Vacuum/Analyze 默认覆盖所有分区子表。
主从读取卡顿:尾部截断(Tail Truncation)隐式发生,会导致只读副本产生排他锁冲突并卡顿。 全局控制尾部收缩:新增全局配置,可主动关闭截断行为以保护读副本。
缺乏可观测性:没有针对单独表的 Vacuum 耗时统计。 全新计数器面板:新增多维度 Vacuum 与 Analyze 的时长统计。

PG18 Vacuum 核心功能升级详解

1. 异步 I/O 支持(Asynchronous I/O for Vacuum)

原理:以往的堆扫描(Heap Scans)是完全同步的(请求磁盘页 -> 等待 -> 处理 -> 请求下一页)。在云磁盘或 NFS 等高延迟存储中,等待时间极长。PG18 引入异步 I/O 后,系统可以在处理当前页面的同时,向磁盘预读取(Prefetch)下一组页面。

配置参数

  • io_method:默认设置为 worker(生成专门的 I/O 工作进程)。

  • io_workers:默认为 3。如果发现扫描耗时过长,可扩展至 6 甚至 12(适用于大型系统)。

结论:开箱即用,无需更改配置即可获得更快的清理速度。

2. Autovacuum 动态弹性扩展(Flexible Scaling)

应用场景:生产高峰期发现某张表急剧膨胀,现有的 Worker 全被大表占用,急需新增 Worker,但系统不允许重启。

新特性:现在可以动态调整 autovacuum_max_workers(默认 3)。

操作要点(关键方法):由于启动时 autovacuum_worker_slots 默认池大小已设为 16,你可以直接上调或下调 Worker 数量。注意: 所有 Worker 共享同一个“成本限制(Cost Limit)”,如果增加 Worker,必须同步调高 Cost Limit,否则每个 Worker 分配到的资源变少,整体清理效率反而会下降。

3. 废弃元组硬性上限设置(Hard Cap on Dead Tuples)

原机制缺陷:自动清理的触发是基于比例(如默认 20%)。如果是 10 亿行的大表,意味着要积累 2 亿个废弃元组才会触发清理,严重拖慢查询。

PG18 机制:引入 autovacuum_vacuum_max_threshold 参数(例如可保守设置为 5000 万)。即使比例未达标,只要废弃元组达到该绝对数值,即可触发清理。支持在实例级别或单表级别进行针对性配置(也可针对特定表禁用)。

4. 主动冻结(Eager Freezing)

原理:打破过去“将繁重冻结任务留给单一防回卷大清理”的模式。现在,常规的 Vacuum 会主动处理元组的冻结工作。

配置参数:由 vacuum_freeze_eager_failure_rate(默认 3%)控制,将 I/O 压力均匀分散到日常常规运行中,有效减少 I/O 风暴。

5. 分区表递归 Vacuum/Analyze

继承式分区表:现在对父表运行 Vacuum 或 Analyze 时,默认递归涵盖所有子表。如需保留旧版本仅针对父表操作的行为,可使用 ONLY 关键字。

声明式分区表(Declarative Partitioning):新增 ANALYZE ONLY 选项。在繁忙的生产环境中,若只需更新父表级别的统计信息而不想引发对所有子表的大规模扫描,可以使用该关键字。

6. 尾部截断控制(Vacuum Truncate)

痛点解决:以往在表尾部清理空页(收缩存储)时,需要获取“访问排他锁(Access Exclusive Lock)”,这会同步到只读副本上,导致读副本的查询请求短暂卡顿(Stall)。

新特性:PG18 提供全局参数开关。针对以读副本为主的工作负载,可以在实例级别或单表级别显式关闭 vacuum_truncate,避免读库卡顿。

7. 可观测性与安全性增强

统计视图升级pg_stat_all_tables 新增 4 个计数器,分别统计:总 Vacuum 时间、总 Autovacuum 时间、总 Analyze 时间、总 Auto analyze 时间。

延迟分析:新增 track_cost_delay_timing(默认禁用)。开启后,可通过 pg_stat_progress_vacuum 观察延迟时间,精准调优成本延迟配置。

更详细的返回信息ANALYZE 现在的详细信息输出包含了 CPU 时间和平均读取速率。

权限下放:引入新的内置角色 pg_signal_autovacuum_worker,允许非超级用户(Non-super users)对工作进程发送信号和进行管理,提升系统安全性。

总结

PostgreSQL 18 让 Vacuum 变得:

  • 更快:得益于 AIO(异步I/O)子系统。
  • 更可控:Autovacuum Worker 可动态扩展,硬性清理阈值可避免大表隐性膨胀,针对尾部收缩的显式控制保护了读库。
  • 更平滑:主动冻结(Eager Freezing)平摊了 I/O 压力,使得防回卷机制更加温和,减少了应用层面的锁冲突。

参考

Vacuuming Enhancements in PostgreSQL 18: Faster, Smarter, More Predictable