优化PostgreSQL Autovacuum

做者:Laurenz Albe是CYBERTEC的高级顾问和支持工程师。自2006年以来,他一直在PostgreSQL上工做并为PostgreSQL作贡献。
sql

译者:类延良,任职于瀚高基础软件股份有限公司,PostgreSQL数据库技术爱好者,10g &11g OCM,OGG认证专家。数据库

 

在许多PostgreSQL数据库中,您无需考虑或担忧调整autovacuum。它会在后台自动运行,并在不妨碍您的状况下进行清理。安全

可是有时默认配置还不够好,您必须调整autovacuum以使其正常工做。本文介绍了一些典型的问题方案,并介绍了在这些状况下的处理方法。session

 

autovacuum的任务并发

有许多autovacuum的配置参数,这会使调整变得复杂。主要缘由是autovacuum具备许多不一样的任务。从某种意义上说,autovacuum必须解决由PostgreSQL的多版本并发控制(MVCC)实现引发的全部问题:ide

  • 清理UPDATE或DELETE操做后留下的“死元组”
  • 更新可用空间映射(free space map),以跟踪表块中的可用空间
  • 更新仅索引扫描所需的可见性图(visibility map)
  • “冻结”(freeze)表行,以便事务ID计数器能够安全地环绕

根据这些功能中的哪一个会致使问题,您须要不一样的方法来调整autovacuum。函数

 

调整autovacuum以清除死元组post

最有名的autovacuum任务是清理UPDATE或DELETE操做中的死元组。若是autovacuum不能跟上清理死元组的速度,则应遵循如下三个调整步骤:网站

 

确保没有任何东西能够阻止autovacuum回收死元组spa

检查 防止vacuum清除死元组的已知缘由 

https://www.cybertec-postgresql.com/en/reasons-why-vacuum-wont-remove-dead-rows/罪魁祸首一般是长期事务。除非您能够消除这些障碍,不然调整autovacuum将无用。

 

若是您不能从根本上解决问题,则可使用配置参数

idle_in_transaction_session_timeout使PostgreSQL终止会话,这些会话在事务中处于“idle in transaction”的时间过长。这会在客户端致使错误,可是若是您没有其余方法能够保持数据库正常运行,这多是有道理的。一样,要解决长期运行的query,可使用statement_timeout配置参数。

 

调整autovacuum以使其运行更快

若是autovacuum没法跟上清理死元组的速度,那么解决方案就是使其工做更快。这看起来彷佛很明显,可是许多人陷入了使autovacuum更早开始或更频繁运行将解决问题的陷阱。

VACUUM是一项耗费资源的操做,所以默认状况下,autovacuum操做的速度故意下降。目的是使其在后台运行而不妨碍正常的数据库操做。可是,若是您的工做负载建立了不少死元组,那么您将不得不使其更具侵略性:

设置autovacuum_vacuum_cost_delay为零将使autovacuum与手动VACUUM速度同样快,即尽量快。

 

因为并不是全部表都以相同的速度增加死元组,所以一般最好不要更改中的全局设置postgresql.conf,而要单独更改繁忙表的设置:

ALTER TABLE busy_table SET (autovacuum_vacuum_cost_delay = 1);

对表进行分区还能够帮助更快地完成工做。请参阅本文partition部分了解更多信息。

 

更改工做负载,以便生成更少的死元组

若是没有其余效果,则必须看到生成的死元组更少。也许将几个UPDATE合并为一行UPDATE一般,您可使用“ HOT更新”来显着减小死元组的数量:

  • 将表的fillfactor参数设置为小于100的值,以使INSERTs在每一个块中保留一些可用空间
  • 确保你在update语句中修改的列不是索引列

而后,任何SELECT或DML语句均可以清除死元组,而对VACUUM的需求则更少。

 

调整仅索引扫描的autovacuum

索引扫描的昂贵部分是查找实际的表行。若是您想要的全部列都在索引中,则彻底不须要访问该表。可是在PostgreSQL中,您还必须检查一个元组是否可见,而且该信息仅存储在表中。

为了解决这个问题,PostgreSQL对每一个表都有一个“可见性图”(visibility map)。若是一个表块在可见性图(visibility map)中被标记为“全部可见”,则没必要访问该表以获取可见性信息。

所以,要得到真正的仅索引扫描,autovacuum必须处理表并常常更新可见性图(visibility map)。为此,如何配置autovacuum取决于查询收到的数据修改类型:

 

为接收UPDATEs或DELETEs的表的仅索引扫描调整autovacuum

为此,您能够减小表的存储参数autovacuum_vacuum_scale_factor,例如

ALTER TABLE mytable SET (autovacuum_vacuum_scale_factor = 0.01);

按照如上所述加快autovacuum是一个好主意。

 

调整仅接收INSERTs的表的仅索引扫描的autovacuum

从v13开始这很简单:对配置参数autovacuum_vacuum_insert_scale_factor进行调整,调整方法是如上所示对autovacuum_vacuum_scale_factor的调整。

对于较旧的PostgreSQL版本,您能够作的最好方法就是下降autovacuum_freeze_max_age,最佳值取决于您使用事务id的速率,若是您天天消耗100000个事务id,而且但愿天天自动清理table,则能够进行以下设置:

ALTER TABLE insert_only SET (autovacuum_freeze_max_age = 100000);

要测量事务ID消耗的速率,请在一个长的时间间隔内使用两次txid_current()函数(或者从V13开始的pg_current_xact_id()函数),而后取其差值。

 

调整autovacuum以免事务回绕问题

正常时,autovacuum关心并启动一个特殊的“anti-warparound” autovacuum worker,不论一个表中最老的transaction id比autovacuum_freeze_max_age参数值更老或者一个表中的最老的multiact比autovacuum_multixact_freeze_max_age 参数值更老

 

确保anti-wraparound vacuum能够freeze掉全部表中的行

再次强调,你不得不确保:没有阻塞autovacuum进行freeze老元组和改进pg_database.datfrozenxid 以及pg_database.datminmxid。这些阻塞者包括:

  • 运行时间很长的session,这些session保持一个事务处于open状态或者有临时表(autovacuum不能处理临时表)
  • 数据损坏,这会致使全部的autovacuum worker运行失败。

为了防止数据损坏,请使用更好的硬件,并老是运行最新的PostgrSQL的次要版本。

 

为接收updates或者Deletes的tables调优anti-wraparound vacuum

在接收updates或者deletes的table上,你不得不作的一切是看autovacuum正在运行,而且足够快以便及时完成(参见上文)

 

为接收inserts的tables调优anti-wraparound vacuum

从PostgreSQL v13开始,在这种状况下没有特殊考虑,由于您也能够在此类表上按期运行autovacuum。

在此以前,仅插入表是有问题的:因为没有死元组,所以永远不会触发正常的autovacuum运行。

 

而后,一旦autovacuum_freeze_max_age或autovacuum_multixact_freeze_max_age超过该值,您可能会忽然得到大量的autovacuum运行,从而冻结整个大表,花费很长时间并致使大量的I / O。

为避免这种状况,请减小autovacuum_freeze_max_age该表:

ALTER TABLE insert_only SET (autovacuum_freeze_max_age = 10000000);

 

分区

对于很大的表,建议使用分区。这样作的好处是您可让多个autovacuum workers 并行处理多个分区,所以整个分区表的完成速度比单个autovacuum worker快。

若是您有多个分区,则应增长autovacuum_max_workers,该参数是指autovacuum workers的最大数量。

只要更新影响全部分区,分区还能够帮助清理接收大量更新的表。

 

调优autoanalyze

更新表统计信息是自动清理的“辅助工做”。

您知道,若是您的查询计划在手工对表执行ANALYZE后变得更好,那么自动统计信息收集将不会常常发生。

在这种状况下,您能够下降autovacuum_analyze_scale_factor以使autoanalyze更频繁地处理表:

ALTER TABLE mytable SET (autovacuum_analyze_scale_factor = 0.02);

另外一种选择是不使用scale factor,而是使用set autovacuum_analyze_threshold,以便每当固定数量的行发生更改时,就计算表统计信息。

 

例如,要配置每当超过一百万行更改时要分析的表:

ALTER TABLE mytable SET (

   autovacuum_analyze_scale_factor = 0,

   autovacuum_analyze_threshold = 1000000

);

 

结论

根据您的特定问题和PostgreSQL版本,有不一样的调整开关可使autovacuum正确执行其工做。autovacuum的许多任务和许多配置参数并无使它变得更容易。

 

若是本文中的提示还不够,请考虑寻求专业咨询

(https://www.cybertec-postgresql.com/en/services/postgresql-consulting/)

 

原文连接:

https://www.cybertec-postgresql.com/en/tuning-autovacuum-postgresql/

 

更多精彩内容,请关注如下平台、网站:

 

中国Postgre SQL分会官方公众号(技术文章、技术活动):

开源软件联盟PostgreSQL分会

 

中国Postgre SQL分会技术问答社区:

www.pgfans.cn

 

中国Postgre SQL分会官方网站:

www.postgresqlchina.com