PostgreSQL vacuum原理一功能與引數

jesselyu發表於2015-04-23

從上篇“PostgreSQL MVCC 原始碼實現”中,我們知道,PG並沒有像Oracle那樣的undo來存放舊版本;而是將舊版本直接存放於relation檔案中。那麼帶來的問題就是dead tuple過多,導致relation檔案

不斷增大而帶來空間膨脹問題。為了解決這個問題,PG中引入了vacuum後臺程式,專門來清理這些dead tuple,並回縮空間。當然vacuum的作用不僅在此,它還有以下其它功能:

一、vacuum的功能

1.回收空間

    這個通常是大家最容易想起來的功能。回收空間,將dead tuple清理掉。但是已經分配的空間,一般不會釋放掉。除非做vacuum full,但是需要exclusive lock。一般不太建議,因為如果表最終還是會漲到

這個高水位上,經常做vacuum full意義不是非常大。一般合理設定vacuum引數,進行常規vacuum也就夠了。

2.凍結tuple的xid

   PG會在每條記錄(tuple)的header中,存放xmin,xmax資訊(增刪改事務ID)。transactionID的最大值為2的32次,即無符整形來表示。當transactionID超過此最大值後,會迴圈使用。

這會帶來一個問題:就是最新事務的transactionID會小於老事務的transactionID。如果這種情況發生後,PG就沒有辦法按transactionID來區分事務的先後,也沒有辦法實現MVCC了。因此PG用vacuum後臺程式,

按一定的週期和演算法觸發vacuum動作,將過老的tuple的header中的事務ID進行凍結。凍結事務ID,即將事務ID設定為“2”(“0”表示無效事務ID;“1”表示bootstrap,即初始化;“3”表示最小的事務ID)。PG認為被凍結的事務ID比任何事務都要老。這樣就不會出現上面的這種情況了。

3.更新統計資訊

    vacuum analyze時,會更新統計資訊,讓PG的planner能夠算出更準確的執行計劃。autovacuum_analyze_threshold和autovacuum_analyze_scale_factor引數可以控制analyze的觸發的頻率。

4.更新visibility map

在PG中,有一個visibility map用來標記那些page中是沒有dead tuple的。這有兩個好處,一是當vacuum進行scan時,直接可以跳過這些page。二是進行index-only scan時,可以先檢查下visibility map。這樣減少fetch tuple時的可見性判斷,從而減少IO操作,提高效能。另外visibility map相對整個relation,還是小很多,可以cache到記憶體中。

二、vacuum引數介紹

autovacuum有好多引數,用來控制其行為,大致有以下幾個:

  • autovacuum:預設為on,表示是否開起autovacuum。預設開起。特別的,當需要凍結xid時,儘管此值為off,PG也會進行vacuum。
  • autovacuum_naptime:下一次vacuum的時間,預設1min。 這個naptime會被vacuum launcher分配到每個DB上。autovacuum_naptime/num of db。
  • log_autovacuum_min_duration:記錄autovacuum動作到日誌檔案,當vacuum動作超過此值時。 “-1”表示不記錄。“0”表示每次都記錄。
  • autovacuum_max_workers:最大同時執行的worker數量,不包含launcher本身。
  • autovacuum_vacuum_threshold:預設50。與autovacuum_vacuum_scale_factor配合使用, autovacuum_vacuum_scale_factor預設值為20%。當update,delete的tuples數量超過autovacuum_vacuum_scale_factor*table_size+autovacuum_vacuum_threshold時,進行vacuum。如果要使vacuum工作勤奮點,則將此值改小。
  • autovacuum_analyze_threshold:預設50。與autovacuum_analyze_scale_factor配合使用, autovacuum_analyze_scale_factor預設10%。當update,insert,delete的tuples數量超過autovacuum_analyze_scale_factor*table_size+autovacuum_analyze_threshold時,進行analyze。
  • autovacuum_freeze_max_age和autovacuum_multixact_freeze_max_age:前面一個200 million,後面一個400 million。離下一次進行xid凍結的最大事務數。
  • autovacuum_vacuum_cost_delay:如果為-1,取vacuum_cost_delay值。
  • autovacuum_vacuum_cost_limit:如果為-1,到vacuum_cost_limit的值,這個值是所有worker的累加值。

基於代價的vacuum引數:

  • vacuum_cost_delay :計算每個毫秒級別所允許消耗的最大IO,vacuum_cost_limit/vacuum_cost_dely。 預設vacuum_cost_delay為20毫秒。
  • vacuum_cost_page_hit :vacuum時,page在buffer中命中時,所花的代價。預設值為1。
  • vacuum_cost_page_miss:vacuum時,page不在buffer中,需要從磁碟中讀入時的代價預設為10。 vacuum_cost_page_dirty:當vacuum時,修改了clean的page。這說明需要額外的IO去刷髒塊到磁碟。預設值為20。
  • vacuum_cost_limit:當超過此值時,vacuum會sleep。預設值為200。

把上面每個cost值調整的小點,然後把limit值調的大些,可以延長每次vacuum的時間。這樣做,如果在高負載的系統當中,可能IO會有所影響,因vacuum。但是對於表物理儲存空間的增長會有所減緩。

在下一篇重點將在原始碼實現上。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30088583/viewspace-1592066/,如需轉載,請註明出處,否則將追究法律責任。

相關文章