天天看點

優化PostgreSQL Autovacuum

作者:Laurenz Albe是CYBERTEC的進階顧問和支援工程師。自2006年以來,他一直在PostgreSQL上工作并為PostgreSQL做貢獻。

譯者:類延良,任職于瀚高基礎軟體股份有限公司,PostgreSQL資料庫技術愛好者,10g &11g OCM,OGG認證專家。

在許多PostgreSQL資料庫中,您無需考慮或擔心調整autovacuum。它會在背景自動運作,并在不妨礙您的情況下進行清理。

但是有時預設配置還不夠好,您必須調整autovacuum以使其正常工作。本文介紹了一些典型的問題方案,并介紹了在這些情況下的處理方法。

autovacuum的任務

有許多autovacuum的配置參數,這會使調整變得複雜。主要原因是autovacuum具有許多不同的任務。從某種意義上說,autovacuum必須解決由PostgreSQL的多版本并發控制(MVCC)實作引起的所有問題:

  • 清理UPDATE或DELETE操作後留下的“死元組”
  • 更新可用空間映射(free space map),以跟蹤表塊中的可用空間
  • 更新僅索引掃描所需的可見性圖(visibility map)
  • “當機”(freeze)表行,以便事務ID計數器可以安全地環繞

根據這些功能中的哪個會導緻問題,您需要不同的方法來調整autovacuum。

調整autovacuum以清除死元組

最有名的autovacuum任務是清理UPDATE或DELETE操作中的死元組。如果autovacuum不能跟上清理死元組的速度,則應遵循以下三個調整步驟:

確定沒有任何東西可以阻止autovacuum回收死元組

檢查 防止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_limit預設值200開始增加(這是一種柔和的方法)
  • 從autovacuum_vacuum_cost_delay從預設值2開始減少(在舊版本:20)毫秒(這是有效的方法)

設定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