如果清除作業無法跟上資料操縱語言 (DML) 對資料表執行的速率,就會發生資料表和索引膨脹的情況。部分表格和索引膨脹是無可避免的,一般來說可以接受,因為交易可以重複使用該空間。嚴重膨脹會導致效能問題,例如查詢時間變慢、I/O 增加、共用緩衝區和快取使用效率降低,以及儲存空間成本增加。
如要估算膨脹程度,最好的方法是使用 pgstattuple 模組。不過,如果擴充功能必須讀取關係的所有頁面,使用 pgstattuple 的效率就會較低。如果無法使用 pgstattuple,可以改用其他指令碼估算膨脹,但這種做法的準確度較低。
讀取 pgstattuple 輸出內容
使用 pgstattuple 回報表格或索引的實體儲存特性時,輸出內容的格式如下:
> SELECT * FROM pgstattuple('large_table');
-[ RECORD 1 ]------+-----------
table_len | 7431888896
tuple_count | 66666666
tuple_len | 2796296271
tuple_percent | 37.63
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
free_space | 3873153652
free_percent | 52.12
輸出內容說明如下:
table_len(7431888896)- 資料表總大小 (以位元組為單位)。包括所有有效元組、無效元組和可用空間。在本例中,
large_table約佔 7,088 GB。 tuple_count(66666666)- 代表資料表中的有效元組數量,也就是可見且有效的資料列。這個資料表包含約 6,600 萬個有效列。
tuple_len(2796296271)- 所有即時元組的總長度 (以位元組為單位),約為 2.6 GB。
tuple_percent(37.63)有效元組占用的
table_len百分比。計算方式如下:(
tuple_len/table_len) ∗ 100 = (2796296271/7431888896) ∗ 100 ≈37.63百分比這項輸出內容表示有效資料使用的磁碟空間不到資料表的 40%。
dead_tuple_count(0)無效元組的數量,也就是更新或刪除後,真空作業尚未移除的資料列。
0值表示資料表已清除,沒有待回收的無效元組。這通常表示VACUUM或 autovacuum 在資料表上有效率地執行。dead_tuple_len(0)所有無效元組的總長度 (以位元組為單位)。與
dead_tuple_count一致,0值表示無效資料列不會耗用任何空間。dead_tuple_percent(0)無效元組占用的
table_len百分比。計算方式如下:(
dead_tuple_len/table_len) ∗ 100 = (0/7431888896) ∗ 100 =0%free_space(3873153652)這個值代表資料表資料頁面中的可用空間量。您可以重複使用這個空間來插入或更新資料,不必擴充表格。這表示有大量可用空間,約為 3.7 GB。
free_percent(52.12)這個值代表
table_len的可用空間百分比。 計算方式如下:(
free_space/table_len) ∗ 100 = (3873153652/7431888896) ∗ 100 ≈52.12%
使用查詢估算膨脹
您可以對系統目錄表執行查詢來估算膨脹,但這種方法的準確度不如使用 pgstattuple 等擴充功能。如果您使用 PostgreSQL 資料表膨脹檢查等指令碼,資料表統計資料必須為最新狀態,否則估算結果會不準確。
將查詢的輸出內容與 pgstattuple 模組進行比較時,估計值具有可比性,但並非膨脹的確切測量結果。不過,由於 SQL 查詢依賴 PostgreSQL 的累計統計資料引擎,而模組會讀取實際資料頁面,因此模組仍是更準確的膨脹指標。
以下範例比較兩種不同方法的輸出內容,這兩種方法用於分析 PostgreSQL 中名為 large_table 的資料表膨脹。
> SELECT * FROM pgstattuple('large_table');
-[ RECORD 1 ]------+-----------
table_len | 2475892736
tuple_count | 22000000
tuple_len | 922925931
tuple_percent | 37.28
dead_tuple_count | 0
dead_tuple_len | 0
dead_tuple_percent | 0
free_space | 1293696900
free_percent | 52.25
Vs.
-[ RECORD 1 ]+------------
databasename | postgres
schemaname | public
tablename | large_table
can_estimate | t
est_rows | 21965400
pct_bloat | 54
mb_bloat | 1269.24
table_mb | 2361.195
地址膨脹
您可以透過下列方式管理膨脹,每種方式都有優缺點,因此需要仔細規劃:
- 徹底吸塵。這項作業需要完整鎖定資料表,時間長度為清除作業的持續時間,且需要停機。
- 將資料移至新資料表。如要使用這個方法,您必須暫停表格變更,確保變更不會轉移至新關係。
- 請使用
pg_squeeze。這項擴充功能可減少線上膨脹。擴充功能會建立影子資料表、插入所有資料,然後使用複製位置維護資料表變更,直到最後一個步驟為止,也就是將膨脹的資料表換成新建立的非膨脹資料表。然後要求短暫鎖定資料表,將非膨脹資料表移至膨脹資料表的位置,取代膨脹資料表。這個方法在作業期間需要兩倍的物件空間,但對正常作業的干擾最少。