处理 bloat

本页目录

什么是膨胀?

膨胀是页面内部的空闲空间,在 autovacuum 删除大量元组时产生。

当更新表中的一行时,Postgres 不会覆盖旧数据,而是将旧的行版本 (元组) 标记为"dead",并创建一个新的行版本。随着时间推移,越来越多的行被更新或删除,死元组占据的空间会积累起来。在某个时间点,autovacuum (或手动执行 VACUUM) 会删除死元组,留下页面内的空闲空间供重用。但是,如果死元组累积过多,可能会留下大量空闲空间 — 在最糟糕的情况下,它可能占据表或索引空间的 99% 或更多)

较低的膨胀率 (例如,低于 40%) 不应被视为问题,而较高的膨胀率会有问题,因为它们会导致严重的后果:

  1. 磁盘使用量增加
  2. 读写查询需要更多 IO
  3. 缓存效率下降 (包括缓冲池和操作系统文件缓存)
  4. 结果:查询性能变差

如何检查膨胀

应该定期检查索引和表的膨胀情况。注意,大多数常用的查询都是基于预估,容易出现误报 — 根据表的结构,有时会显示一些并不存在的膨胀 (我见过一些情况,即使是在刚创建的表中,也显示了高达 40% 的"幽灵膨胀")。但这些查询速度快,不需要安装额外的扩展。示例:

监控系统中的建议:

更精确确定膨胀水平的方式:

定期检查膨胀水平是推荐的,以便在需要时及时做出反应。

缓解索引膨胀 (被动)

不幸的是,在经历大量 UPDATE 和 DELETE 的数据库中,索引健康状况会不可避免地会随着时间的推移而恶化。这意味着索引需要定期重建。

建议:

缓解表膨胀 (被动)

某些水平的表膨胀可能不是坏事,因为它增加了优化 UPDATE 的机会 —HOT (Heap-Only Tuples) 更新。

但是,如果膨胀水平令人担忧,考虑使用 pg_repack 在不长时间持有排他锁的情况下重建表。pg_repack 的替代工具:pg_squeeze

通常,这个过程不需要定期调度和完全自动化;通常只需在检测到高表膨胀时有控制地应用即可。

主动缓解膨胀

推荐阅读材料

讨论与补充

在 GitHub 查看讨论

支持作者

感谢支持 PostgreSQL Howto 的长期维护。

微信赞赏码

读者交流群

二维码若已过期,可通过公众号 PostgreSQL 学徒或邮件联系。

PostgreSQL 学徒读者交流群二维码