PostgreSQL 教程: 优化 autovacuum 以清理死元组

五月 27, 2024

摘要:在本教程中,您将学习如何在 PostgreSQL 中优化 autovacuum,以高效清理死元组。

目录

autovacuum 最典型的任务是清理由UPDATEDELETE操作产生的死元组。如果autovacuum无法清理死元组,您可以按照以下三个步骤进行调优:

确保没有任何事情阻止 autovacuum 回收死元组

有时,autovacuum 不会删除死元组。大多数情况下,问题原因在那些长时间运行的事务。除非您能消除这些障碍,否则调整 autovacuum 将毫无用处。

如果您无法从根本上解决问题,则可以使用配置参数 idle_in_transaction_session_timeout,让 PostgreSQL 终止那些停留在 “idle in transaction” 时间过长的会话。这会导致客户端出现错误,但如果没有其他方法来保持数据库正常运行,那可能也是合理的。同样,要消除长时间运行的查询,您可以使用参数 statement_timeout

优化 autovacuum 以加速运行

如果 autovacuum 无法跟上清理死元组的步伐,解决方案是让它工作得更快。这样看来是显而易见的,但许多人会陷入这样的陷阱,即认为,让 autovacuum 更早启动或更频繁地运行可以解决问题。

VACUUM是一种资源密集型操作,因此默认情况下 autovacuum 故意运行缓慢。目的是让它在后台工作,而不妨碍正常的数据库操作。但是,如果你的工作负载创建了大量的死元组,你将不得不使它更积极地工作:

autovacuum_vacuum_cost_delay设置为 0,将使 autovacuum 与手动VACUUM一样快,也就是尽可能的快。

由于不是所有表都以相同的速度增加死元组,因此通常最好不要更改postgresql.conf中的全局设置,而是单独更改那些繁忙的表的设置:

ALTER TABLE busy_table SET (autovacuum_vacuum_cost_delay = 1);

对表进行分区也有助于更快地完成清理工作。这样做的好处是,您可以让多个 autovacuum 工作进程并行处理多个分区,这样清理这些分区表的完成速度就比单个 autovacuum 工作进程要更快。

优化业务负载,以产生更少的死元组

如果其他方法都不起作用,则必须看下能否产生更少的死元组。也许一行的多次UPDATE可以合并成一次UPDATE

通常,您可以使用 “HOT 更新” 来显著减少死元组的数量:

  • 设置表的 fillfactor 为一个小于 100 的值,以便INSERT时在每个块中留下一些空闲空间。
  • 请确保您在UPDATE中修改的列,是没有索引的列。

然后,任何SELECT或 DML 语句都可以清理死元组,这样就不太需要VACUUM了。

了解更多

PostgreSQL 优化