首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >足足等了十年:PG 大表 vacuum 终于能"多线程"了!

足足等了十年:PG 大表 vacuum 终于能"多线程"了!

作者头像
用户4035096
发布2026-07-10 09:28:23
发布2026-07-10 09:28:23
1300
举报

PostgreSQL 这个功能等了十年:大表 vacuum 终于能"多线程"了!

痛点:autovacuum 的单线程瓶颈

Autovacuum 是 PostgreSQL 的"自动保洁阿姨",负责清理死元组、防止表膨胀。

但长期以来有个致命问题:它只能用单线程

想象一下:

  • 订单表 100GB,20 个索引
  • 单线程清理所有索引,需要 1 小时
  • 这 1 小时内,表持续膨胀,查询越来越慢
  • 终于清理完了,下一轮又开始了

革命性突破:autovacuum 并行化

PostgreSQL 最新版本支持 autovacuum 并行 vacuum

代码语言:javascript
复制
之前:只有 1 个 worker,顺序处理所有索引
现在:1 个 leader + 多个 worker,同时处理多个索引(最多 5 个)

:leader 本身也处理 1 个索引,所以如果有 4 个 worker,最多同时处理 5 个索引。每个 worker 处理 1 个或多个索引(不同 worker 处理不同索引)。

效果实测

数据来源参考:12 索引的表,启用 4 个并行 worker

场景

优化前

优化后

索引清理时间(12 索引)

~45 分钟

~12 分钟

总体 vacuum 时间

60+ 分钟

~30 分钟

死元组清理延迟

3-4 天

1 天内

表膨胀程度

2x 正常大小

1.2x 以内

注:具体效果取决于索引数量、大小及 maintenance_work_mem 配置。

如何配置

第一步:全局开启

代码语言:javascript
复制
-- postgresql.conf
autovacuum_max_parallel_workers = 4
max_parallel_workers = 8

第二步:为大表启用

代码语言:javascript
复制
-- 为单个表设置(以分区表为例)
ALTER TABLE orders_history_2025_01 SET (
    autovacuum_parallel_workers = 4
);
ALTER TABLE orders_history_2025_02 SET (
    autovacuum_parallel_workers = 4
);

语义说明

  • -1(默认):让系统自动决定
  • 0:禁用该表的并行 vacuum
  • 正整数:使用指定数量(同时受 GUC 上限约束)

工作原理

代码语言:javascript
复制
Leader Worker
    ├── 负责协调和总体进度
    │
    └── Worker 1 ──► 处理索引 1, 2
    └── Worker 2 ──► 处理索引 3, 4
    └── Worker 3 ──► 处理索引 5, 6
    └── Worker 4 ──► 处理索引 7, 8

所有 worker 共享 cost balance 调度

关键点:cost balance(vacuum 的 I/O 节流)是共享的,不是每个 worker 独立叠加。所以不会因为开并行 worker 就突然疯狂消耗 I/O。

进阶:运行时参数同步

Autovacuum 的 cost 参数可以在运行时修改:

代码语言:javascript
复制
ALTER SYSTEM SET autovacuum_vacuum_cost_delay = 10;
SELECT pg_reload_conf();

修改后,leader 会自动把新参数同步给所有 worker,不需要重启 vacuum。

注意事项

并行有前提条件

  1. 索引大小不能太小(受 min_parallel_index_scan_size 控制)
  2. 表至少有 2 个可并行的索引
  3. 索引的 amparallelvacuumoptions 支持并行

小表不要开并行: 对于小于 100MB 的表,并行的进程启动开销可能反而更大。

代码语言:javascript
复制
-- 小表显式禁用
ALTER TABLE small_config SET (
    autovacuum_parallel_workers = 0
);

一句话总结

以前:autovacuum 单线程,大表 vacuum 要等几小时。

现在:autovacuum 并行化,同样的活几十分钟搞定。


最佳实践

  1. 10GB 以上、多索引的大表:开启并行
  2. 高并发 OLTP 表:配合较高的 autovacuum_vacuum_cost_delay 使用,减少对业务的影响
  3. 核心配置表:保持默认或显式禁用
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-09,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • PostgreSQL 这个功能等了十年:大表 vacuum 终于能"多线程"了!
    • 痛点:autovacuum 的单线程瓶颈
    • 革命性突破:autovacuum 并行化
    • 效果实测
    • 如何配置
      • 第一步:全局开启
      • 第二步:为大表启用
    • 工作原理
    • 进阶:运行时参数同步
    • 注意事项
    • 一句话总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档