postgresql 在 autovacuum 启用时,当死元组数 ≥ threshold + scale_factor × 总行数,或变更行数达 analyze 阈值,或事务 id 接近 autovacuum_freeze_max_age 限制时,自动触发 vacuum 或 analyze;但 unlogged 表、临时表及系统表(未显式启用)除外。
什么时候 PostgreSQL 会自动触发 VACUUM 和 ANALYZE
PostgreSQL 默认开启 autovacuum,只要表有足够多的死元组(dead tuples)或统计信息过期,就会自动调度 VACUUM 和 ANALYZE。但“足够多”不是固定行数,而是基于几个动态阈值计算出来的:
-
autovacuum_vacuum_threshold(默认 50)+autovacuum_vacuum_scale_factor(默认 0.2)→ 触发VACUUM的死元组下限 =threshold+scale_factor × 表总行数 -
autovacuum_analyze_threshold(默认 50)+autovacuum_analyze_scale_factor(默认 0.1)→ 触发ANALYZE的变更行数下限同理 - 实际是否运行还受
autovacuum_freeze_max_age(默认 2 亿事务)约束:哪怕没改数据,只要事务 ID 快耗尽,也会强制VACUUM
注意:autovacuum 不会为 UNLOGGED 表或临时表运行,也不处理系统表(除非显式配置 autovacuum_enabled = on)。
哪些场景必须手动执行 VACUUM / ANALYZE
自动机制有延迟、有保守性,以下情况无法等待:
- 刚批量
DELETE或UPDATE掉表 80% 以上数据,但表仍很大 → 死元组堆积严重,查询可能变慢,空间不释放 - 执行完大批次
INSERT后立刻做复杂查询 → 优化器还没拿到新数据分布统计,容易选错执行计划 -
pg_stat_all_tables.n_dead_tup持续高于pg_class.reltuples × 0.2,且last_autovacuum时间很久 → 自动进程被阻塞或配置过松 - 升级 PostgreSQL 小版本后首次启库 → 建议对所有用户表跑一次
VACUUM ANALYZE,避免旧统计残留影响
手动命令最常用组合是 VACUUM (VERBOSE, ANALYZE) table_name,加 VERBOSE 能看到实际清理了多少行、是否触发了冻结(freeze)。