目标
autovacuum 并不神秘:死元组超过“scale×活元组+threshold”就触发,推进速度受 cost limit 与 delay 约束。千万行的表用默认 20% 阈值意味着攒够两百万死元组才开始清理。把真实更新速率代进这套算术,就能准确解释周五为什么慢、以及该改哪两个数字。
步骤要点
- 每小时两次采样 n_dead_tup 与 last_autovacuum 一整天,量化每小时四万死元组的更新速率。
- 手算默认触发点:0.2×1000 万+50≈200 万死元组,按 4 万/小时约 50 小时才触发,与每日churn严重失配。
- ALTER TABLE 设 scale_factor=0.01、threshold=10000、cost_limit=2000、cost_delay=1,约 70 分钟清理一次且每次能跑完。
- 观察 autovacuum_count 稳步上升、n_dead_tup 在低位振荡而非棘轮式攀升。
- 每周跟踪 pg_total_relation_size 趋势:体积稳定在小区间内即成功,周五的减速消失。
排错提示
清理总跑不完就调高该表 cost limit、把 delay 降到 1ms,并用 pg_stat_progress_vacuum 确认运行确实能结束;长事务会冻结清理进度,去 pg_stat_activity 找到并缩短它,或把长读移到副本;激进的按表设置会吃掉全局 worker 预算,应提高 autovacuum_max_workers 或只给极少数表开激进配置。
适用边界
表规模与负载变化后参数需要重估,应以趋势监控代替一次设定;autovacuum 只把空间标记复用、不会缩小文件,成功的判据是体积稳定而非下降。
代码示例
-- The trigger arithmetic
-- vacuum when: dead > scale * live + threshold
-- default: dead > 0.2 * 10,000,000 + 50 = 2,000,050
-- churn 40k/h: fires every ~50 hours
ALTER TABLE events SET (
autovacuum_vacuum_scale_factor = 0.01,
autovacuum_vacuum_threshold = 10000,
autovacuum_vacuum_cost_limit = 2000,
autovacuum_vacuum_cost_delay = 1
);