postgres 表膨脹處理2(轉)
阿新 • • 發佈:2022-05-06
一,關於vacuum
進行delete操作之後,表和索引的大小沒有發生變化
vacuum 表名字 不能回收空間,執行時可以正常訪問資料表(共享鎖)。執行效率高 作用是把表中的dead tuples進行刪除標記變成可以使用的狀態,並沒有真正的物理刪除,並且會更新統計資訊和相關係統表
vacuum full 表名字 可以回收空間,執行時不允許訪問資料表(排他鎖)。執行效率低 作用是物理刪除dead tuples,並且把釋放的空間重新交給作業系統。
本質時生成一個新的資料檔案,然後把原來的表的live tuples 存放到新的資料檔案中
autovacuum程序 只是個監控作用是用來啟動自動清理程序的,autovacuum然後autovacuum worker然後vacuum+analyze,可以同時啟動多個
表中不能被回收的dead tuple在索引頁裡是作為正常tuple而不是dead tuple記錄的。考慮到這一點,索引的實際膨脹要乘以對應表的膨脹率
二,表膨脹的原因
1 autovacuum清理速度趕不上dead元組產生速度
2 由於以下因素導致dead元組無法被回收
◦ 主庫或備庫存在長事務(長時間的更新操作或者只讀操作都會造成表膨脹)
◦ 主庫或備庫存在未處理的未決事務
◦ 主庫或備庫存在斷開的複製槽
3 表膨脹和索引膨脹的對比
三,表膨脹的預防
1適當調整autovacuum引數,使得事務或者表,索引等能得到相對及時的清理
select * from pg_settings ps where 1=1 and lower(ps.name) like '%autovacuum%' order by ps.name;
比如:autovacuum_vacuum_cost_limit引數
2關注長時間執行的事務
select extract(epoch FROM (clock_timestamp() - xact_start )) as longtrans, ----xact_start 這個程序的當前事務被啟動的時間 extract(epoch FROM (clock_timestamp() - query_start )) as longquery ----query_start當前活動查詢被開始的時間 from pg_stat_activity -----pg_stat_activity檢視將為每一個伺服器程序有一行,顯示與該程序的當前活動相關的資訊 where 1=1 and state <> 'idle';
或者
select * from pg_stat_activity where state<>'idle' and pg_backend_pid() != pid and (backend_xid is not null or backend_xmin is not null ) and extract(epoch from (now() - xact_start)) > <時間閾值,單位秒> ;
3,關注表的膨脹率
select schemaname||'.'||relname,
n_dead_tup, ----n_dead_tup的資料量是未回收的空間
n_live_tup,------n_live_tup的數量是當前表的資料量
coalesce(round(n_dead_tup * 100 / (case when n_live_tup + n_dead_tup = 0 then null else n_live_tup + n_dead_tup end ),2),0.00) as dead_tup_ratio ----dead_tup佔所有有資料的行的百分比
from pg_stat_all_tables
where 1=1
and n_dead_tup >= 10000
order by dead_tup_ratio desc
limit 10;
4這些表要警惕,進行清理
SELECT relname, age(relfrozenxid) as xid_age, pg_size_pretty(pg_table_size(oid)) as table_size
FROM pg_class WHERE relkind = 'r' and pg_table_size(oid) > 1073741824 ORDER BY age(relfrozenxid) DESC LIMIT 20;
四,檢視清理後的效果
語句一:表及的大小
select pt.schemaname||'.'||pt.tablename as table_name, ----表名字
pg_relation_filepath(pt.schemaname||'.'||pt.tablename) as table_path, ----指定表的檔案路徑名
pg_table_size(pt.schemaname||'.'||pt.tablename) as table_size, -----指定表的大小(不包括索引)
pg_relation_size(pt.schemaname||'.'||pt.tablename) as relation_size, ----指定表使用的磁碟空間(包括索引) pg_relation_size不加引數,預設就是查的表的資料檔案大小,單位位元組
pg_total_relation_size(pt.schemaname||'.'||pt.tablename) as totalrelation_size, ---指定表所用的總磁碟空間,包括所有的索引和TOAST資料
pi.schemaname||'.'||pi.indexname as index_name, ---指定索引的名稱
pg_relation_filepath(pi.schemaname||'.'||pi.indexname) as index_path, ----指定索引的檔案路徑名
pg_relation_size(pi.schemaname||'.'||pi.indexname) as index_size,--指定的單個索引
pg_indexes_size(pi.schemaname||'.'||pi.tablename) as index_total_size,--表上的所有索引
pi.indexdef ---索引的定義
from pg_tables pt
left outer join pg_indexes pi
on pt.schemaname||'.'||pt.tablename = pi.schemaname||'.'||pi.tablename
where 1=1
and pt.schemaname='public'
and pt.tablename='tmp_t0';
語句二:看錶的統計資訊
select * from pg_stat_all_tables where relname='tmp_t0';
五,一些額外的瞭解
psql的\watch 1 作用反覆檢視語句執行結果(每一秒鐘一次);
fsm結尾的檔案是主檔案的空閒空間對映檔案---只跟蹤可用空間的頁面
vm結尾的檔案是主檔案的可見性對映檔案---只跟蹤包含凍結元組(死元組)的頁面