autovacuum 默认开启但需验证是否实际运行:执行 SHOW autovacuum 返回 on 且 source 非 override 才有效;死元组未清理主因是阈值过高或成本限制过严,高写入大表须调低表级阈值并提高成本上限。

autovacuum 默认就是开启的,不用“开启”——但你得确认它真在干活,而不是被误关、被压垮、或被表级配置覆盖。
检查 autovacuum 是否实际启用
很多人以为改了 postgresql.conf 就万事大吉,其实 PostgreSQL 会从多个层级加载配置,优先级高的可能悄悄关掉它。
- 连接数据库后执行
SHOW autovacuum;,返回on才算有效启用 - 检查是否被
ALTER SYSTEM或postgresql.auto.conf覆盖:运行SELECT name, setting, source FROM pg_settings WHERE name = 'autovacuum';,看source是不是configuration file或override - 注意:即使全局设为
off,autovacuum 进程仍会启动(只为防事务 ID 回卷),但它不会清理死元组——这种“假启用”最危险
为什么 SHOW autovacuum 返回 on 却没清理 dead tuples?
常见原因是触发条件未满足,或清理被成本机制主动抑制,不是功能失效。
- 默认触发 VACUUM 的阈值是:
n_dead_tup >= autovacuum_vacuum_threshold + autovacuum_vacuum_scale_factor * pg_class.reltuples,即 “50 + 表总行数 × 0.2”。一张 1 亿行的表要积累 2000 万+ 死元组才触发,明显滞后 - 如果
autovacuum_vacuum_cost_delay设得太大(比如 10ms),或autovacuum_vacuum_cost_limit太小(比如 100),autovacuum worker 会频繁休眠,实际扫描页数极少,清理速度远低于生成速度 - 系统视图
pg_stat_progress_vacuum可查当前正在运行的 autovacuum 进程进度;pg_stat_all_tables中的last_autovacuum字段能验证是否真有动作
对高写入大表必须调低触发阈值
默认的 20% 比例只适合小表。生产中千万级以上活跃表,建议按数据变更节奏单独设参,否则死元组堆积到 GB 级才清理,I/O 和查询延迟会突然飙升。
- 在目标表上执行:
ALTER TABLE your_table SET (autovacuum_vacuum_threshold = 1000, autovacuum_vacuum_scale_factor = 0.05); - 这意味着:只要死元组超过 1000 行,或达到总行数 5%,就触发清理——比全局默认激进得多
- 搭配调高成本上限:
ALTER TABLE your_table SET (autovacuum_vacuum_cost_limit = 1000);,避免 worker 因成本限制过早退出 - 切记:这些是表级参数,不会影响其他表;修改后无需重启,下一次 autovacuum 周期即生效
容易被忽略的硬性依赖
autovacuum 不是独立服务,它严重依赖底层资源和基础配置,缺一不可。
-
shared_buffers必须足够大:若太小(如仅 128MB),autovacuum 频繁 page miss,vacuum_cost_page_miss开销暴增,实际效率断崖下跌 -
max_worker_processes和autovacuum_max_workers要匹配:默认autovacuum_max_workers = 3,但若并发大表同时达标,新表只能排队等——可设为 6~10,但需确保系统 CPU 和 I/O 能扛住 - 事务 ID 回卷保护是强制保底逻辑:哪怕所有参数都关了,只要某表的
age(relfrozenxid)接近autovacuum_freeze_max_age(默认 2 亿),autovacuum 会强制介入——这个行为无法禁用,也别想绕过
真正关键的不是“怎么开”,而是“它有没有在你最关键的那几张表上及时动起来”。盯着 n_dead_tup 和 last_autovacuum,比反复检查配置文件有用得多。

















