RDS for PostgreSQL表存储空间缩容与膨胀治理指导
PostgreSQL采用多版本并发控制(MVCC)机制。在执行UPDATE或DELETE操作时,旧版本数据(Dead Tuples,死元组)不会立即被物理删除,而是保留在数据页中,以确保事务并发读的一致性。
随着使用时间增加,无效数据持续累积,导致表和索引体积膨胀(Bloat),进而引发以下问题:
- 存储浪费:占用大量云盘空间。
- 性能下降:全表扫描需读取更多数据页,降低缓存命中率。
- 维护成本:备份与恢复时间变长。
本文介绍三种主流的空间回收机制:autovacuum、VACUUM FULL与pg_repack,并提供生产环境下的选型建议。
原理介绍
1 autovacuum:自动空间复用(逻辑回收)
- 工作原理:后台守护进程定期扫描表,识别并标记死元组为“可复用空间”。回收的空间会登记到空闲空间映射(FSM)中,供后续INSERT或UPDATE复用。
- 空间表现:仅逻辑回收,不缩小物理文件大小。操作系统层面看到的表文件大小保持不变,但内部碎片会被复用。
- 锁与性能:不阻塞读写,资源占用低。
- 适用场景:日常自动维护,防止空间无限膨胀的基础防线。
2 VACUUM FULL:物理空间回收(阻塞式)
- 工作原理:重写整张表,逐行将有效数据写入全新的紧凑数据页中,完成后丢弃旧表。
- 空间表现:彻底物理回收,表文件大小缩至仅包含有效数据的最小值,空间返还给操作系统。
- 锁与性能:执行期间申请ACCESS EXCLUSIVE锁,完全阻塞表读写。执行过程需要约2倍表大小的临时磁盘空间。
- 适用场景:业务停机维护窗口期,或必须释放大量磁盘空间且无法接受在线工具的场景。
3 pg_repack:在线无损缩容(生产推荐)
- 工作原理:通过创建新表存储有效数据,利用日志/触发器同步增量变更,最后原子化交换新表与旧表元数据。
- 空间表现:物理回收,有效重组数据页并释放多余空间给操作系统。
- 锁与性能:全程不阻塞读写,仅在最后交换瞬间申请极短暂锁(毫秒级)。执行过程需要约1倍表大小的额外临时空间。
- 适用场景:生产环境高可用表缩容的首选方案。
空间回收机制特性对比
| 特性维度 | autovacuum | VACUUM FULL | pg_repack |
|---|---|---|---|
| 回收类型 | 逻辑复用(不返还给OS) | 物理回收(返还给OS) | 物理回收(返还给OS) |
| 阻塞情况 | 无锁,不阻塞读写 | ACCESS EXCLUSIVE,完全阻塞 | 仅末尾瞬间短暂锁(微秒/毫秒级) |
| 磁盘需求 | 极低 | 高(约2倍表大小) | 中(约1倍表大小) |
| 索引处理 | 仅清理死元组 | 重建索引,消除索引膨胀 | 在线重组索引 |
| 适用时机 | 日常自动运行 | 停机维护窗口/离线库 | 生产环境在线维护 |