postgresql dead_tuple和live_tuple
-PG并沒有像Oracle那樣的undo來存放舊版本;而是將舊版本直接存放于relation文件中。那么帶來的問題就是dead tuple過多,導致relation文件不斷增大而帶來空間膨脹問題。
--為了解決這個問題,PG中引入了vacuum后臺進程,專門來清理這些dead tuple,并回縮空間
postgres=# create table t (id int ,name varchar(50));
CREATE TABLE
postgres=# insert into t select id,'rudy'|| id from generate_series(1,100) id;
INSERT 0 100
postgres=# select relname,n_live_tup,n_dead_tup from pg_stat_user_tables where relname='t';
| t | 100 | 0 |
(1 行記錄)
--由以下可知,沒更新一次,n_dead_tup加1
postgres=# update t set name='dead tuple' where id=1;
UPDATE 1
postgres=# select relname,n_live_tup,n_dead_tup from pg_stat_user_tables where relname='t';
| ?t ? ? ? | ? ? ? ?100 | ? ? ? ? ?1 |
postgres=# update t set name='dead tuple 2' where id=1; ? ? ? ? ?
UPDATE 1
postgres=# select relname,n_live_tup,n_dead_tup from pg_stat_user_tables where relname='t';
| ?t ? ? ? | ? ? ? ?100 | ? ? ? ? ?2 |
?
?
--每刪除一次數據 n_live_tup 和 n_dead_tup 均加1?
postgres=# delete from ?t where id<10;
DELETE 9
postgres=# select relname,n_live_tup,n_dead_tup from pg_stat_user_tables where relname='t';
| ?t ? ? ? | ? ? ? ? 91 | ? ? ? ? 11 |
vacuum (verbose ,analyze ) t;
INFO: vacuuming "public.t"
INFO: "t": removed 11 row versions in 1 pages
INFO: "t": found 11 removable, 91 nonremovable row versions in 1 out of 1 pages
描述: 0 dead row versions cannot be removed yet, oldest xmin: 993
There were 2 unused item pointers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.02 s.
INFO: analyzing "public.t"
INFO: "t": scanned 1 of 1 pages, containing 91 live rows and 0 dead rows; 91 rows in sample, 91 estimated total rows
VACUUM
postgres=# select relname,n_live_tup,n_dead_tup,last_vacuum,last_analyze from pg_stat_user_tables where relname='t';
| t | 91 | 0 | 2018-12-19 10:33:13.155231+08 | 2018-12-19 10:33:13.157232+08 |
(1 行記錄)
--不帶表名的vacuum會回收統計系統中的所有的表,此時系統會有大量的io操作,故不要在數據庫繁忙時操作
?vacuum (verbose ,analyze ) ;
?
-- 注意 vacuum full會鎖表和索引,而且是“AccessExclusiveLock”級別的。其實vacuum full會重建整個表,這個的功能實現在cluster.c文件中,因為其行業相當于是一個cluster重建的一個變種
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配置
自動vacuum的執行直接由autovacuum參數值決定,默認值是on。
log_autovacuum_min_duration:默認值為-1,關閉vacuum的日志記錄,配置為0表示記錄autovacuum的所有log。參數設置為正整數表示對于在此時間內完成的vacuum操作不進行log記錄,如果沒能完成,則記錄超出時間內的log。該參數對于了解對象執行vacuum操作的時間非常有用。
autovacuum_max_workers:最大的autovacuum進程的數量,默認值為3。參數大小的配置主要依據系統當前負載和資源。對于系統負載較重的情況,建議開啟少量的進程為好,反之,空閑時間可以采用較大值的方式。
autovacuum_naptime:檢查數據庫的時間間隔。默認為1分鐘。
autovacuum_vacuum_threshold:參數表示執行autovacuum操作之前,對單個表中記錄執行DML操作的最少行數。達到該行數時自動激活autovacuum操作。該參數針對數據庫中的所有表,還可以通過對單個表配置不同的值來改變相應表的autovacuum操作。默認值是50。
autovacuum_analyze_threshold:激活自動analyze操作的最小行數。默認值50。機制與上面相同。
autovacuum_vacuum_scale_factor:該參數采用百分比的方式設定閥值。默認值為20%,當DML涉及的數據量大于某個表的20%時,自動觸發autovacuum操作。同樣可以通過對單個表進行閥值設定。
autovacuum_analyze_scale_factor:機制與上面相同,到達閥值是自動激活analyze操作。同樣可以通過對單個表進行閥值設定。
autovacuum_freeze_max_age:為防止事務ID的重置,在啟用vacuum操作之前,表的pg_class .relfrozenxid字段的最大值,默認為200萬。
autovacuum_vacuum_cost_delay:autovacuum進程的時間延遲限制,默認值是20ms。對于單個表同樣適用。
autovacuum_vacuum_cost_limit:autovacuum進程的開銷延遲限制,默認值是-1,表示不進行開銷限制,系統將會直接依據vacuum_cost_limit參數管理vacuum的開銷。對于單個表同樣適用。
-
總結
以上是生活随笔為你收集整理的postgresql dead_tuple和live_tuple的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 性能优化(概述)
- 下一篇: 关于使用layui中的tree的一个坑