PostgreSQL Autovacuum和vacuum + 參數優化


1 基礎知識

重點: 如果您的數據庫運行了很久,並且從來沒有打開過autovacuum,那么請在打開autovacuum之前全庫手動運行vacuum analyze(可能要非常久的時間)

完全禁用autovacuum,請不要這樣做,除非你真的知道你在做什么,並且需要定期清理腳本.否則當問題發生時你將不得不處理花費大量的時間處理,甚至可能需要停庫、停機

 

 1.1 dead tuples
tuple:元組,也就是一行數據

首先,簡要解釋什么是"死元組""膨脹".

  當您在PostgreSQL中執行DELETE時,行不會立即從數據文件中刪除.而是僅通過在頁頭中設置xmax字段將其標記為已刪除.同樣對於UPDATE,它可能在PostgreSQL中被視為DELETE+INSERT.

  這是PostgreSQL MVCC背后的基本思想之一,因為它允許更大並發,在不同的進程之間最小的鎖定.這個MVCC實現的缺點是留下了已刪除的元組,即使在所有可能看到這些版本的事務完成之后也是如此.

 

如果沒有清理,那些"死元組"(對於任何事務實際上是不可見的)將永遠留在數據文件中.


對於DELETE和UPDATE比較多的的表,死元組可能占據很多磁盤空間.



同時,死元組也將從索引中引用,進一步增加了浪費的磁盤空間量.


這就是我們在PostgreSQL中稱之為“膨脹”的東西,同時因為查詢也會變慢。

 

1.2 vacuum和autovacuum

收死元組占用空間的最直接方法是手動運行VACUUM命令

注意:VACUUM FULL會回收空間並將其返回給操作系統,但是有許多缺點.首先,它將獲取表上的獨占鎖,阻止所有操作(包括SELECT).其次,它實際上創建了一個表的副本(復制了一個表),使所需的磁盤空間加倍,同時復制表非常慢.

 

[root@iZ2zeijrvu2s38mfzvzrc3Z ~]# cat /home/pg_freeze.sh
#!/bin/bash
#
# cript: pg_freeze.sh
#  Date:2020-04-09
#
#
######################################################################################################################
#                                  init message
######################################################################################################################

# list databases
# 日期
#backup_date=`date  "+%Y-%m-%d"`
# 備份所有業務庫  數據庫用戶根據實際用戶進行替換;
for x in  $(psql -U postgres -h 127.0.0.1  -c "select datname from pg_database where datname not in ('template0','template1'); "  -A -t)
do
##避免錯誤可直接寫死路徑
` psql -U postgres -h 127.0.0.1  -d ${x} -c " VACUUM FREEZE;"`
echo "freeze ${x} success!!"
done
[root@iZ2zeijrvu2s38mfzvzrc3Z ~]#

 

 

 

 根據以下參數我們可以計算autovacuum完成的"工作成本".然后通過autovacuum_vacuum_cost_limit可以一次完成的清理工作,默認情況下設置為200,每次清理完成后它將睡眠20ms:

 

autovacuum_vacuum_cost_delay = 20ms
autovacuum_vacuum_cost_limit = 200


延遲20ms,清理可以每秒進行50輪,每輪200,每秒10000.這意味着:

從shared_buffers讀取80MB/s(假設沒有臟頁,10000/1*8k)
從OS讀取8MB/s(可能來自磁盤,10000/10*8k)
4 MB / s寫入(由autovacuum進程弄臟的頁面,10000/20*8k)

 

3 閾值和比例因子

autovacuum會受到兩個參數的影響
autovacuum_vacuum_threshold = 50 #閾值
autovacuum_vacuum_scale_factor = 0.2 #比例因子

該公式基本上表示在清理之前,高達20%的表可能是死元組(50行的閾值是為了防止非常頻繁地清理微小的表).

默認的比例因子適用於中小型表,但對於非常大的表則沒有那么多(在10GB表上,這大約是2GB的死元組,而在1TB表上則是~200GB).

 

 

 參考:PostgreSQL Autovacuum和vacuum - VicLW - 博客園 (cnblogs.com)

 

 

 

6. pg_repack

[root@iZ2zeijrvu2s38mfzvzrc3Z ~]# cat /home/pg_repack.sh
#!/bin/bash
#
#  Script: pg_repack.sh
#  Date:2020-07-21
#
#
######################################################################################################################
#                                  init message
######################################################################################################################
pg_repack_log=/home/pg_repack_log
# 備份日期
backup_date=`date  "+%Y-%m-%d"`
log_file=pg_repack_${backup_date}.txt
echo  `date` >${pg_repack_log}/${log_file}
# 核心表清單;
for x in  $(psql -U postgres -h 127.0.0.1 -d tenant_1008446 -c "select relname from pg_class where relname in (
'kx_kq_store',
'kx_kq_storeinandout',

'sfa_t_tbascostexec',
'ka_kq_channelcustomers',

'dms_t_contract',
'sfa_t_tbasstorephoto',
'tn_channelscore',
'sfa_t_tbasstoreperformance',
'kx_gzq_content',
'kx_order',

'kx_visit_customerstatus',
'kx_visit_actual'
); "  -A -t)
do
##避免錯誤可直接寫死路徑
##echo  `date` >> ${pg_repack_log}/${log_file}
exec=` /usr/pgsql-10/bin/pg_repack -Upostgres -h127.0.0.1 -d tenant_test -t ${x}`
echo "pg_repack ${x} success!!"  >> ${pg_repack_log}/${log_file}
echo  `date` >> ${pg_repack_log}/${log_file}

done
[root@iZ2zeijrvu2s38mfzvzrc3Z ~]#

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM