PostgreSQL Field Guide

PostgreSQL autovacuum 与表膨胀

监控 dead tuples、冻结风险和 vacuum 进度并安全调整高写入表

标准 VACUUM 的目标不只是“释放空间”:它让 dead row versions 可复用、维护 planner statistics 和 visibility map,并防止 transaction ID/multixact wraparound。多数系统应保持 autovacuum 开启。

日常观测

SELECT
  schemaname, relname,
  n_live_tup, n_dead_tup,
  last_vacuum, last_autovacuum,
  vacuum_count, autovacuum_count,
  last_analyze, last_autoanalyze
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 30;

统计是估算且会重置,不能仅凭一个 n_dead_tup 阈值判断膨胀。结合表大小、更新速率、查询延迟、autovacuum 日志和趋势。

查看正在运行的 vacuum:

SELECT
  pid, datname, relid::regclass AS relation,
  phase, heap_blks_total, heap_blks_scanned, heap_blks_vacuumed,
  index_vacuum_count, dead_tuple_bytes, num_dead_item_ids,
  indexes_total, indexes_processed
FROM pg_stat_progress_vacuum;

这些字段名对应 PostgreSQL 18;较早 major 的 progress view 列可能不同,跨版本监控应先核对目标版本目录。

为什么没有触发或跟不上

  • 表很大,默认 scale factor 对应的变更行数过高;
  • worker、I/O 或维护内存不足;
  • 长事务、prepared transaction、复制槽或 standby snapshot 阻止回收;
  • vacuum 经常被冲突锁取消;
  • 写入峰值持续高于清理能力。

针对已验证的热点表覆盖参数,而不是先全局激进调整:

ALTER TABLE app.events SET (
  autovacuum_vacuum_scale_factor = 0.02,
  autovacuum_vacuum_threshold = 1000,
  autovacuum_analyze_scale_factor = 0.01
);

参数只是示例。根据表大小和每天变更量计算触发频率,并观察 I/O、WAL、延迟与实际完成时间。

手工维护边界

VACUUM (ANALYZE, VERBOSE) app.events;

普通 VACUUM 主要让空间在关系内部复用,通常不会把文件缩回操作系统。VACUUM FULL 会重写整张表、需要额外磁盘并获取 ACCESS EXCLUSIVE 锁,不是日常清理命令。

不要关闭 autovacuum 解决性能问题

先找出具体表、阶段、等待事件和资源瓶颈。关闭 autovacuum 会积累 dead tuples、陈旧统计和冻结风险;反 wraparound vacuum 即使表级设置关闭也可能运行。

完整原理见 PostgreSQL 18 Routine Vacuuming

Last updated on

On this page