pg_squeeze(資料表空間整理)
當表因頻繁的UPDATE和DELETE操作產生大量片段(即表膨脹)時,會導致儲存空間浪費和查詢效能下降。pg_squeeze外掛程式通過線上重組表的方式自動回收這些膨脹空間。它基於邏輯解碼捕獲資料變更,對業務寫入效能影響很小,且完全在服務端自動運行,協助您在不中斷業務的前提下,持續最佳化表結構,提升資料庫效能與空間利用率。
適用範圍
支援的PolarDB PostgreSQL版(相容Oracle)的版本: Oracle文法相容 2.0,且核心小版本需為2.0.14.19.40.0及以上。
與pg_repack對比
pg_squeeze與pg_repack功能相似,都是用於處理表膨脹問題的常用擴充。pg_squeeze作為pg_repack的替代方案,在實現原理和營運方式上存在差異,可根據業務情境選擇。
對比項 | pg_squeeze | pg_repack |
實現原理 | 邏輯解碼(Replication Slot):通過複製槽非同步捕獲WAL中的資料變更。 | 觸發器(Trigger):在源表上建立觸發器,同步捕獲DML操作。 |
對業務寫入影響 | 較小。變更捕獲是非同步過程,對源表寫入效能影響有限。 | 較大。每次DML操作都會額外觸發一次寫入,在高並發下可能成為效能瓶頸。 |
資源消耗 | 消耗一個複製槽。若壓縮任務處理緩慢或失敗,可能導致WAL日誌堆積,佔用儲存空間。 | 觸發器在高並發下會增加CPU開銷。需要額外的日誌表記錄變更。 |
營運複雜度 | 需關注複製槽狀態和WAL儲存空間,防止因任務異常導致磁碟寫滿。 | 需關注觸發器本身的管理,確保其在表結構變更或資料移轉後仍能正常工作。 |
快速入門
本節將引導您完成從安裝配置到成功啟用一個表的自動壓縮任務的全過程。
步驟一:配置叢集參數
登入PolarDB控制台,在集群列表頁面找到目的地組群,單擊叢集ID進入詳情頁。
在左側導覽列選擇。
在参数配置頁面,修改以下參數:
wal_level:設定為logical。這是使用邏輯解碼功能的前提,會適度增加WAL日誌的產生量。max_replication_slots:確保有足夠餘量。pg_squeeze在每個啟用的資料庫中至少需要1 + squeeze.workers_per_database個複製槽。建議設定為比當前值至少大2的值(例如,從10調整到12)。shared_preload_libraries:在現有值的基礎上追加,pg_squeeze。例如,如果原值為pg_stat_statements,則修改為pg_stat_statements,pg_squeeze。
等待叢集重啟後參數配置生效。
步驟二:安裝外掛程式並啟動後台進程
在需要進行資料表空間整理的目標資料庫中啟用pg_squeeze功能。
登入至目標資料庫。
執行以下SQL語句,建立外掛程式並啟動後台調度背景工作處理序(Scheduler Worker)。該進程會根據
squeeze.tables中的配置,定時檢查並建立壓縮任務。-- 在目標資料庫中建立擴充 CREATE EXTENSION pg_squeeze; -- 啟動後台調度進程 -- 此操作只需在每個需要使用pg_squeeze的資料庫中執行一次 SELECT squeeze.start_worker();(可選)執行以下SQL語句,驗證後台進程是否成功啟動。如果看到
application_name為squeeze scheduler的進程,則表示啟動成功。SELECT * FROM pg_stat_activity WHERE application_name LIKE 'squeeze%';
步驟三:配置待處理的表
告知pg_squeeze需要管理哪些表,以及按何種策略進行檢查和壓縮。
確保表具備
REPLICA IDENTITY(副本標識):pg_squeeze需要通過唯一標識來匹配新舊錶中的行變更。通常,主鍵(Primary Key)會自動作為REPLICA IDENTITY。檢查:使用
\d+ your_table_name命令查看錶的Replica identity屬性是否為DEFAULT或FULL。設定:如果表沒有主鍵,但有一個唯一索引(例如
your_table_uidx),可執行以下命令將其設定為REPLICA IDENTITY。ALTER TABLE your_table_name REPLICA IDENTITY USING INDEX your_table_uidx;
將表註冊到
squeeze.tables:將表資訊及調度策略插入squeeze.tables配置表中。schedule欄位用於定義檢查時間,其格式類似於Cron運算式。-- 樣本1:每天淩晨2:30檢查public.foo表 INSERT INTO squeeze.tables (tabschema, tabname, schedule) VALUES ('public', 'foo', ROW(ARRAY[30], ARRAY[2], NULL, NULL, NULL)::squeeze.schedule); -- 樣本2:每周日淩晨4:00檢查public.bar表,並指定壓縮後按主鍵排序 INSERT INTO squeeze.tables (tabschema, tabname, schedule, clustering_index) VALUES ('public', 'bar', ROW(ARRAY[0], ARRAY[4], NULL, NULL, ARRAY[0])::squeeze.schedule, 'bar_pkey');schedule欄位的結構為(分鐘, 小時, 日, 月, 星期)。NULL表示任意時間。更多配置請參見附錄:squeeze.tables配置表詳解。
步驟四:監控與驗證
確認壓縮任務是否按預期執行、成功或失敗。您可以通過查詢pg_squeeze提供的視圖和表來監控任務狀態。
-- 查看當前資料庫中進行中的壓縮任務
SELECT * FROM squeeze.get_active_workers();
-- 查看最近10條成功的壓縮記錄
SELECT * FROM squeeze.log ORDER BY finished DESC LIMIT 10;
-- 查看失敗的壓縮記錄及原因
SELECT * FROM squeeze.errors;步驟五:(可選)取消定製壓縮
如果特定表不再需要定期壓縮,只需從squeeze.tables表中刪除相應的行即可。
DELETE FROM squeeze.tables WHERE tabschema = 'public' AND tabname = 'foo';手動觸發即時壓縮
除了按計劃自動執行,您也可以手動觸發對任意表的即時壓縮,而無需將其註冊到squeeze.tables中。對特定表進行一次性的、立即執行的壓縮操作。
使用squeeze.squeeze_table()函數發起一個手動壓縮任務。
-- 對 public.pgbench_accounts 表發起一次預設的壓縮任務
SELECT squeeze.squeeze_table('public', 'pgbench_accounts');
-- 發起壓縮任務,並指定壓縮後按主鍵(pgbench_accounts_pkey)進行物理排序
SELECT squeeze.squeeze_table('public', 'pgbench_accounts', 'pgbench_accounts_pkey');squeeze.squeeze_table函數不是事務性的。它僅負責啟動一個後台背景工作處理序來執行壓縮,然後立即返回。復原調用該函數的事務,並不會中止已經啟動的後台壓縮任務。
配置進階選項
調整並發與鎖行為
在不影響業務的前提下,更精細地控制壓縮過程。通過設定squeeze.max_xlock_time參數,可以限制壓縮最後階段獨佔鎖定的最長持有時間,避免長時間阻塞業務。
-- 設定獨佔鎖定最長持有時間為100毫秒
SET squeeze.max_xlock_time TO 100;如果鎖持有時間超過此限制,pg_squeeze會釋放鎖,處理在此期間發生的資料變更,然後再次嘗試擷取鎖。若多次嘗試均逾時,任務將報錯中止。如果頻繁發生鎖逾時失敗,應優先考慮將任務調度到業務負載更低的時間視窗,其次再考慮適當增大此參數值。
配置並發背景工作處理序數
當需要同時處理的表較多時,通過增加背景工作處理序數來提高壓縮效率。您可以將squeeze.workers_per_database參數設定為大於1的值,以允許在單個資料庫中平行處理多個表的壓縮任務。
-- 允許每個資料庫最多同時運行2個壓縮背景工作處理序
SET squeeze.workers_per_database = 2;此設定會影響所有正在使用pg_squeeze外掛程式的資料庫。叢集中所有Workers(包括Scheduler Worker)的總數不能超過參數max_worker_processes的數值。
附錄:squeeze.tables配置表詳解
squeeze.tables是pg_squeeze的核心配置表,您通過向此表插入記錄來註冊需要管理的表並定義其處理策略。
欄位 | 類型 | 描述 | 預設值 | 配置建議 |
|
| 表所在的模式名。 | - | - |
|
| 表名。 | - | - |
|
| 任務檢查調度時間,格式為 | - | 根據業務低峰期設定。例如,每天淩晨2:30執行: |
|
| 觸發壓縮所需的額外膨脹空間百分比(超出 | 50 | 對於寫入頻繁的OLTP表,可適當調低此值(如30),以更頻繁、小批量地回收空間。 |
|
| 表佔用的最小儲存空間(MB),小於此值的表不會被處理。 | 8 | 保持預設值即可,避免對小表進行不必要的操作。 |
|
| 自上次 | '1 hour' | 保持預設值。若超過此時間, |
|
| 當首次壓縮失敗時,允許的最大重試次數。 | 0 | 如果表經常因DDL變更等原因導致壓縮失敗,可適當增加此值(如2),以提高任務成功率。 |
|
| 指定一個現有索引,壓縮完成後表內資料將按此索引的索引值進行物理排序,效果類似 |
| 對於範圍查詢頻繁的表,建議將其主鍵或核心查詢索引作為分區鍵,可顯著提升查詢效能。 |
|
| 指定壓縮後表要遷移到的目標資料表空間。 |
| 用於資料表空間遷移情境。若為 |
|
| 二維數組,用於指定索引的資料表空間映射。 |
| 用於索引的資料表空間遷移。 |
|
| 是否在壓縮完成後跳過 |
| 建議保持 |