最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

PostgreSQL VACUUM 清理機(jī)制詳解

 更新時間:2026年05月12日 08:49:27   作者:倒流時光三十年  
本文主要介紹了PostgreSQL VACUUM 清理機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一、為什么需要 VACUUM?

PostgreSQL 使用 MVCC(多版本并發(fā)控制)實現(xiàn)事務(wù)隔離:

  • UPDATE 操作:本質(zhì)是 DELETE + INSERT,舊版本數(shù)據(jù)并不會立即刪除
  • DELETE 操作:只是將數(shù)據(jù)標(biāo)記為"已刪除",物理空間不釋放

這導(dǎo)致大量死元組(dead tuples) 殘留在表中:

┌──────────────────────────────────────────────────────┐
│  表空間                                              │
│  [活躍數(shù)據(jù)] [死元組] [活躍數(shù)據(jù)] [死元組] [死元組]   │
│                                                      │
│  死元組累積 → 空間浪費(fèi) → 查詢變慢 → 需要 VACUUM    │
└──────────────────────────────────────────────────────┘

VACUUM 就是負(fù)責(zé)回收這些死元組、釋放空間、更新統(tǒng)計信息的維護(hù)命令。

二、哪些操作會產(chǎn)生空間碎片?

2.1 高頻 UPDATE

每次 UPDATE 都會保留舊版本,舊版本變成死元組:

-- 訂單狀態(tài)每次變更,都產(chǎn)生一個舊版本死元組
UPDATE orders SET status = 'PAID'      WHERE order_id = 12345;
UPDATE orders SET status = 'SHIPPED'   WHERE order_id = 12345;
UPDATE orders SET status = 'DELIVERED' WHERE order_id = 12345;

初始:  Page 1: [Row-v1] [空閑] [空閑] [空閑]
3次UPDATE后:
        Page 1: [Row-v1(死)] [Row-v2(死)] [Row-v3(死)] [Row-v4]
                ← 60% 空間被死元組占用

2.2 高頻 DELETE

大量刪除后,空間被死元組占據(jù)無法重用:

-- 每天刪除過期日志
DELETE FROM interface_execution_log WHERE start_time < now() - interval '90 days';

?? 即使刪除了 500 萬行,表文件大小也不會縮小,空間不會歸還給操作系統(tǒng)。

2.3 批量數(shù)據(jù)導(dǎo)入 + 清理

-- Step 1:導(dǎo)入 1000 萬行臨時數(shù)據(jù)
INSERT INTO odh_sell_in_inbound SELECT * FROM external_source;

-- Step 2:數(shù)據(jù)處理完畢,刪除臨時數(shù)據(jù)
DELETE FROM odh_sell_in_inbound WHERE batch_id = 'xxx';

-- 結(jié)果:表大小維持在 1000 萬行的體量,內(nèi)部全是死元組空洞

2.4 長時間未提交的事務(wù)

-- 事務(wù) A 開啟但長時間未提交
BEGIN;
SELECT * FROM lorder_master_info WHERE id = 1;
-- ? 業(yè)務(wù)處理了很久,事務(wù)未提交...

-- 此期間,其他事務(wù)產(chǎn)生的所有死元組都無法被 VACUUM 清理
-- 因為事務(wù) A 可能還需要讀到舊版本數(shù)據(jù)

?? 這是線上最常見的表膨脹根因之一,尤其是跑批任務(wù)或報表查詢時。

2.5 高并發(fā)小事務(wù)

-- 每秒上萬次庫存扣減
UPDATE inventory SET stock = stock - 1 WHERE product_id = 'HOT001';

短時間內(nèi)大量死元組堆積,查詢性能會急劇下降。

三、如何診斷表膨脹?

-- 查看死元組比例,找出需要清理的表
SELECT
    schemaname,
    tablename,
    pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS total_size,
    n_live_tup                                                          AS live_tuples,
    n_dead_tup                                                          AS dead_tuples,
    ROUND(n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS dead_ratio,
    last_autovacuum
FROM pg_stat_user_tables
WHERE n_dead_tup > 10000
ORDER BY n_dead_tup DESC
LIMIT 20;

判斷標(biāo)準(zhǔn):

死元組比例狀態(tài)處理建議
< 5%?? 健康無需操作
5% ~ 20%?? 關(guān)注執(zhí)行 VACUUM ANALYZE
> 20%?? 膨脹立即執(zhí)行 VACUUM,嚴(yán)重時用 VACUUM FULL

四、VACUUM 的類型與使用

4.1 VACUUM —— 日常清理(推薦)

-- 清理單表
VACUUM orders;

-- 清理 + 更新統(tǒng)計信息(最常用)
VACUUM ANALYZE orders;

-- 查看清理詳情
VACUUM VERBOSE ANALYZE orders;

特點:

  • ? 不鎖表,允許并發(fā)讀寫,可在線執(zhí)行
  • ? 將死元組空間標(biāo)記為可重用(供后續(xù) INSERT/UPDATE 使用)
  • ? 不歸還空間給操作系統(tǒng),表文件大小不變

4.2 VACUUM FULL —— 深度清理(維護(hù)窗口)

VACUUM FULL VERBOSE ANALYZE orders;

工作原理:

1. 創(chuàng)建新的表文件
2. 將所有活躍數(shù)據(jù)緊湊復(fù)制到新文件
3. 刪除舊文件,重建所有索引
4. ? 空間歸還給操作系統(tǒng),表文件大幅縮小

特點:

  • ? 徹底回收空間,消除所有碎片
  • ? 需要 ACCESS EXCLUSIVE 鎖,執(zhí)行期間表不可讀寫
  • ? 需要約 2 倍表大小的臨時磁盤空間
  • ? 大表耗時很長(GB 級別可能需要數(shù)十分鐘)

?? 僅在業(yè)務(wù)低峰期(如凌晨維護(hù)窗口)執(zhí)行,生產(chǎn)高峰期禁止使用。

4.3 VACUUM ANALYZE —— 清理 + 更新統(tǒng)計信息

統(tǒng)計信息過時會導(dǎo)致查詢優(yōu)化器選錯執(zhí)行計劃:

-- 數(shù)據(jù)大量變更后,一定要執(zhí)行 ANALYZE
VACUUM ANALYZE lorder_master_info;

-- 或只更新統(tǒng)計信息(不清理)
ANALYZE lorder_master_info;

典型場景:

  • 大批量數(shù)據(jù)導(dǎo)入后
  • 創(chuàng)建新索引后
  • 某張表數(shù)據(jù)量變化超過 20% 后

效果對比:

統(tǒng)計信息過時 → 優(yōu)化器估算:10 行 → 選 Nested Loop → 執(zhí)行 30 秒
執(zhí)行 ANALYZE  → 優(yōu)化器估算:100 萬行 → 選 Hash Join → 執(zhí)行 2 秒

4.4 VACUUM FREEZE —— 防止事務(wù) ID 回繞

PostgreSQL 使用 32 位事務(wù) ID(XID),用完(約 42 億)后會回繞,導(dǎo)致數(shù)據(jù)混亂:

-- 查看各表的事務(wù)年齡(接近 2 億時需警惕)
SELECT
    relname,
    age(relfrozenxid) AS xid_age,
    pg_size_pretty(pg_total_relation_size(oid)) AS size
FROM pg_class
WHERE relkind = 'r'
ORDER BY age(relfrozenxid) DESC
LIMIT 10;

-- 出現(xiàn)以下告警時,立即執(zhí)行:
-- WARNING: database must be vacuumed within 1000000 transactions
VACUUM FREEZE;

五、VACUUM 的核心好處

5.1 回收空間,降低 I/O

清理前:表 100GB,有效數(shù)據(jù) 60GB,死元組 40GB → 全表掃描讀 100GB

VACUUM 后:死元組空間標(biāo)記為可重用,表不再無限膨脹

VACUUM FULL 后:表縮減為 60GB → 全表掃描只需讀 60GB,I/O 節(jié)省 40%

5.2 提升查詢性能

清理前:
  Page 1: [Data][Dead][Dead][Data]   ← 掃描效率 50%
  Page 2: [Dead][Dead][Data][Dead]
  Page 3: [Data][Data][Dead][Dead]
  → 掃描 3 頁,只有 50% 有效數(shù)據(jù)

清理后(VACUUM FULL):
  Page 1: [Data][Data][Data][Data]   ← 掃描效率 100%
  Page 2: [Data][Data][空閑][空閑]
  → 掃描 2 頁,100% 有效數(shù)據(jù),性能提升 ~60%

5.3 優(yōu)化查詢執(zhí)行計劃

統(tǒng)計信息過時是慢查詢的常見根因:

-- 統(tǒng)計信息過時 → 優(yōu)化器估算行數(shù)偏差巨大 → 選錯 Join 方式 → 慢 30 倍
-- VACUUM ANALYZE 后 → 統(tǒng)計準(zhǔn)確 → 選 Hash Join → 正常速度
VACUUM ANALYZE orders;

5.4 改善 Shared Buffer 緩存命中率

清理前:Buffer 中緩存大量死元組頁,熱數(shù)據(jù)被擠出
清理后:Buffer 中全是有效數(shù)據(jù),緩存命中率顯著提升

5.5 防止事務(wù) ID 回繞(數(shù)據(jù)庫崩潰風(fēng)險)

定期 VACUUM 會自動凍結(jié)舊事務(wù) ID,防止 XID 回繞導(dǎo)致數(shù)據(jù)庫不可用。

六、實戰(zhàn)清理操作指南

6.1 標(biāo)準(zhǔn)清理(不鎖表)

-- Step 1:找出需要清理的表
SELECT tablename, n_dead_tup,
       ROUND(n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0), 2) AS dead_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 100000
   OR (n_dead_tup * 100.0 / NULLIF(n_live_tup + n_dead_tup, 0)) > 20
ORDER BY n_dead_tup DESC;

-- Step 2:執(zhí)行清理(不鎖表)
VACUUM VERBOSE ANALYZE lorder_master_info;

-- Step 3:驗證效果
SELECT pg_size_pretty(pg_total_relation_size('lorder_master_info')) AS size,
       n_dead_tup, last_vacuum
FROM pg_stat_user_tables
WHERE tablename = 'lorder_master_info';

6.2 深度清理(維護(hù)窗口執(zhí)行)

-- Step 1:確認(rèn)磁盤空間(需要 2 倍表大?。?
SELECT pg_size_pretty(pg_total_relation_size('orders'))     AS current_size,
       pg_size_pretty(pg_total_relation_size('orders') * 2) AS required_space;

-- Step 2:設(shè)置超時保護(hù)
SET statement_timeout = '2h';

-- Step 3:執(zhí)行深度清理(?? 會鎖表)
VACUUM FULL VERBOSE ANALYZE orders;

6.3 分區(qū)表清理策略

針對項目中的大分區(qū)表,逐個分區(qū)清理,避免一次性影響范圍過大:

-- 逐個分區(qū)清理(推薦)
VACUUM VERBOSE ANALYZE lorder_master_info_ap_st_fy2526_q1;
VACUUM VERBOSE ANALYZE lorder_master_info_ap_st_fy2526_q2;
VACUUM VERBOSE ANALYZE lorder_master_info_ap_st_fy2526_q3;
VACUUM VERBOSE ANALYZE lorder_master_info_ap_st_fy2526_q4;

-- 批量清理所有子分區(qū)
DO $$
DECLARE r RECORD;
BEGIN
    FOR r IN
        SELECT tablename FROM pg_tables
        WHERE schemaname = 'public'
          AND tablename LIKE 'lorder_master_info_%'
    LOOP
        RAISE NOTICE '正在清理: %', r.tablename;
        EXECUTE 'VACUUM VERBOSE ANALYZE ' || quote_ident(r.tablename);
    END LOOP;
END $$;

6.4 批量操作前后的最佳實踐

-- ? 大批量導(dǎo)入后,立即更新統(tǒng)計信息
INSERT INTO odh_sell_in_inbound SELECT * FROM staging_table;
VACUUM ANALYZE odh_sell_in_inbound;

-- ? 大批量刪除后,回收死元組空間
DELETE FROM interface_execution_log WHERE start_time < now() - interval '90 days';
VACUUM interface_execution_log;

-- ? 創(chuàng)建索引后,更新統(tǒng)計信息
CREATE INDEX CONCURRENTLY idx_xxx ON lorder_master_info (geo_type, fiscal_year);
ANALYZE lorder_master_info;

6.5 在線清理方案(pg_repack)

VACUUM FULL 會鎖表,生產(chǎn)環(huán)境推薦用 pg_repack 替代:

# 安裝(Ubuntu)
sudo apt-get install postgresql-16-repack

# 在線整理表,不鎖表,允許讀寫
pg_repack -d mydb -t orders
pg_repack -d mydb -t lorder_master_info_ap_st_fy2526_q4
對比項VACUUM FULLpg_repack
鎖表? 鎖表(不可讀寫)? 不鎖表
空間回收? 完全回收? 完全回收
磁盤需求2 倍表大小2 倍表大小
生產(chǎn)適用? 僅維護(hù)窗口? 隨時可用

適用版本:PostgreSQL 12+

到此這篇關(guān)于PostgreSQL VACUUM 清理機(jī)制詳解的文章就介紹到這了,更多相關(guān)PostgreSQL VACUUM 清理機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • PostgreSql從庫重新配置的詳情

    PostgreSql從庫重新配置的詳情

    這篇文章主要介紹了PostgreSql從庫重新配置的詳情,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 對PostgreSQL中的慢查詢進(jìn)行分析和優(yōu)化的操作指南

    對PostgreSQL中的慢查詢進(jìn)行分析和優(yōu)化的操作指南

    在數(shù)據(jù)庫的世界里,慢查詢就像是路上的絆腳石,讓數(shù)據(jù)處理的道路變得崎嶇不平,想象一下,你正在高速公路上飛馳,突然遇到一堆減速帶,那感覺肯定糟透了,本文介紹了怎樣對?PostgreSQL?中的慢查詢進(jìn)行分析和優(yōu)化,需要的朋友可以參考下
    2024-07-07
  • 解決PostgreSQL服務(wù)啟動后占用100% CPU卡死的問題

    解決PostgreSQL服務(wù)啟動后占用100% CPU卡死的問題

    前文書說到,今天耗費(fèi)了九牛二虎之力,終于馴服了NTFS權(quán)限安裝好了PostgreSQL,卻不曾想,服務(wù)啟動后,新的狀況又出現(xiàn)了。
    2009-08-08
  • 基于PostgreSQL和mysql數(shù)據(jù)類型對比兼容

    基于PostgreSQL和mysql數(shù)據(jù)類型對比兼容

    這篇文章主要介紹了基于PostgreSQL和mysql數(shù)據(jù)類型對比兼容,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • PostgreSQL教程(九):事物隔離介紹

    PostgreSQL教程(九):事物隔離介紹

    這篇文章主要介紹了PostgreSQL教程(九):事物隔離介紹,本文主要針對讀已提交和可串行化事物隔離級別進(jìn)行說明和比較,需要的朋友可以參考下
    2015-05-05
  • 在PostgreSQL中將整數(shù)(int)轉(zhuǎn)換為字符串的方法匯總

    在PostgreSQL中將整數(shù)(int)轉(zhuǎn)換為字符串的方法匯總

    PostgreSQL中將整數(shù)轉(zhuǎn)換為字符串有多種方法,包括使用CAST函數(shù)、::操作符、字符串連接、to_char()函數(shù)等,每種方法都有其適用場景和性能特點,推薦根據(jù)具體需求選擇合適的方法,需要的朋友可以參考下
    2025-12-12
  • 詳解如何在PostgreSQL中使用JSON數(shù)據(jù)類型

    詳解如何在PostgreSQL中使用JSON數(shù)據(jù)類型

    JSON(JavaScript Object Notation)是一種輕量級的數(shù)據(jù)交換格式,它采用鍵值對的形式來表示數(shù)據(jù),支持多種數(shù)據(jù)類型,本文給大家介紹了如何在PostgreSQL中使用JSON數(shù)據(jù)類型,需要的朋友可以參考下
    2024-03-03
  • postgresql中如何執(zhí)行sql文件

    postgresql中如何執(zhí)行sql文件

    這篇文章主要介紹了postgresql中如何執(zhí)行sql文件問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Postgresql查詢效率計算初探

    Postgresql查詢效率計算初探

    這篇文章主要給大家介紹了關(guān)于Postgresql查詢效率計算的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Postgresql具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • PostgreSQL中的外鍵與主鍵操作示例

    PostgreSQL中的外鍵與主鍵操作示例

    在PostgreSQL中,外鍵(Foreign?Key)是一種用于建立表間關(guān)聯(lián)的數(shù)據(jù)庫約束機(jī)制,其核心作用與主鍵(Primary?Key)有顯著區(qū)別,本文給大家介紹PostgreSQL中的外鍵與主鍵操作示例,感興趣的朋友一起看看吧
    2025-10-10

最新評論

海门市| 新郑市| 滦南县| 彰化市| 嫩江县| 桂东县| 长寿区| 谢通门县| 泰宁县| 商水县| 阳东县| 汕尾市| 大足县| 建水县| 乐山市| 上林县| 蕲春县| 鱼台县| 闽清县| 桐庐县| 泰来县| 金秀| 卓尼县| 西昌市| 虞城县| 黄浦区| 逊克县| 井研县| 凤台县| 阿瓦提县| 黄梅县| 肃宁县| 江孜县| 竹溪县| 昔阳县| 荔波县| 杭州市| 河源市| 吐鲁番市| 木兰县| 沙雅县|