PostgreSQL Cost Based Vacuum探秘

jesselyu發表於2015-05-01

    PostgreSQL cost based vacuum的意思就是指每次 vacuum,進行heap scan時,都會基於IO cost進行sleep。如果IO cost越大,總體sleep的時間就會越長。也就是說scan 表,並且清理dead tuple

是斷斷續續的,並不會一次性全vacuum完。這樣子做的原因就是儘量避免對當前DML操作的影響,從而減少因vacuum而對系統IO的壓力。

image

cost based 有幾個非常重要的引數:

  • vacuum_cost_delay : 預設vacuum_cost_delay為20毫秒。 heap scan時,需要sleep的時間。     
  • 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:預設為200,單位時間內多個vacuum worker完成vacuum而不被sleep 懲罰的所允許IO最大消耗值。

 

上面帶有字樣“page”的引數是在readbuffer時,計算的代價。它會及時更新到vacuumCostBalance值中,這個值是每個值的總和。
即:vacuumCostBalance=vacuum_cost_page_hit * x + vacuum_cost_page_miss*Y  + vacuum_cost_page_dirty*Z。其中x,y,z為訪問次數。按預設值轉換後為:vacuumCostBalance=1* x + 10*Y  + 20*Z。

   vacuum_cost_limit有兩個用途:

    其一是用來計算每個vacuum worker毫秒級別所允許消耗的最大IO,vacuum_cost_limit/vacuum_cost_dely。也就是說每個worker會平攤掉這個cost值。一句話概括就是所有vacuum worker在vacuum_cost_delay時間段
內所允許消耗的最大IO。當新的vacuum_worker進來進,都會rebalance一把,得到此worker的VacuumCostLimit值。

    其二是在cost base模式下,用來控制每次delay的時間。每次delay最小值為vacuum_cost_delay值,最大值為4*vacuum_cost_delay值。判斷依據為VacuumCostBalance / VacuumCostLimit的值是否

大於”4“。大於”4“之後就是4*vacuum_cost_delay。PG設定delay最大值為4倍,就是不希望延遲太長。其實4倍的效果已經是非常明顯了。因為在vacuum過程中需要scan heap,index等,而且delay都是

在block級別的。因此,如果某個表IO很高時,就需要透過調高vacuum_cost_limit值來縮短delay時間,從而減少空間爆增量。

    從上面兩點看出,這是一個非常重要的值,如果這個值設定不夠高,也就是說跟當前的系統TPS不匹配的話,那麼導致的結果就是vacuum老是被delay,一個TPS高的表,往往就需要很常的時間來vacuum了。

因此,如果高TPS系統,本人還是建議設定的高些。不然高TPS表,不被及時vacuum完成,而是被delay住,那麼將導致這個表的增長是非常恐怖的,往往會引起效能問題。這個時候變成大表之後,一般vacuum已經不

起作用了,需要vacuum full來處理,而vacuum full是會鎖表的。這會導致對應用嚴重傷害。這個時候有人會跳出來說,vacuum頻率高點可能會影響當前的效能。這個當然會有,在IO上會有爭用。但是這個效能問題,我們
是可能透過其它方式來規避的。比如說應用設計以及資料庫分片技術等。

 

我們先看一個例子,來分析PG是如何基於IO cost,從而來delay vacuum 的:

image

從上面,看Deal Tuples為6116,已經超過threshod值1651,所以後面開始vacuuming “public.sbtest1”。

image

但是總共花了45.64s,才vacuum完成。這個時候的cost_limit值為100。

image

我調整了cost_limit的值到1000,這個時候,可以看到只用了5.85秒。vacuum速度快多了。

這是為什麼呢?原因就是每次scan tuple時,delay的時間少了。PG在索引,表,visibility map等scan進,都嵌入了vacuum_delay_point()方法。

這使得delay的效果是堆積的。當我改成400後,12.84s。

image

 

從上面的例子中,已經完全說明了,為什麼有些高TPS系統,vacuum老是起不了效果。高DML操作表,一直被增大的原因。


另外,autovacuum已經能做到表級並行了。下面三個表位於同一個庫中。

image

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

相關文章