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

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

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

一、為什么需要 VACUUM?

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

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

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

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

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

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

2.1 高頻 UPDATE

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

-- 訂單狀態(tài)每次變更,都產(chǎn)生一個(gè)舊版本死元組
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ù)無(wú)法重用:

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

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

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

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

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

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

2.4 長(zhǎng)時(shí)間未提交的事務(wù)

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

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

?? 這是線上最常見(jiàn)的表膨脹根因之一,尤其是跑批任務(wù)或報(bào)表查詢(xún)時(shí)。

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

-- 每秒上萬(wàn)次庫(kù)存扣減
UPDATE inventory SET stock = stock - 1 WHERE product_id = 'HOT001';

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

三、如何診斷表膨脹?

-- 查看死元組比例,找出需要清理的表
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%?? 健康無(wú)需操作
5% ~ 20%?? 關(guān)注執(zhí)行 VACUUM ANALYZE
> 20%?? 膨脹立即執(zhí)行 VACUUM,嚴(yán)重時(shí)用 VACUUM FULL

四、VACUUM 的類(lèi)型與使用

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

-- 清理單表
VACUUM orders;

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

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

特點(diǎn):

  • ? 不鎖表,允許并發(fā)讀寫(xiě),可在線執(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),表文件大幅縮小

特點(diǎn):

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

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

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

統(tǒng)計(jì)信息過(guò)時(shí)會(huì)導(dǎo)致查詢(xún)優(yōu)化器選錯(cuò)執(zhí)行計(jì)劃:

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

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

典型場(chǎng)景:

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

效果對(duì)比:

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

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

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

-- 查看各表的事務(wù)年齡(接近 2 億時(shí)需警惕)
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)以下告警時(shí),立即執(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)記為可重用,表不再無(wú)限膨脹

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

5.2 提升查詢(xún)性能

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

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

5.3 優(yōu)化查詢(xún)執(zhí)行計(jì)劃

統(tǒng)計(jì)信息過(guò)時(shí)是慢查詢(xún)的常見(jiàn)根因:

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

5.4 改善 Shared Buffer 緩存命中率

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

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

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

六、實(shí)戰(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:驗(yàn)證效果
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)磁盤(pá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è)置超時(shí)保護(hù)
SET statement_timeout = '2h';

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

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

針對(duì)項(xiàng)目中的大分區(qū)表,逐個(gè)分區(qū)清理,避免一次性影響范圍過(guò)大:

-- 逐個(gè)分區(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 批量操作前后的最佳實(shí)踐

-- ? 大批量導(dǎo)入后,立即更新統(tǒng)計(jì)信息
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)計(jì)信息
CREATE INDEX CONCURRENTLY idx_xxx ON lorder_master_info (geo_type, fiscal_year);
ANALYZE lorder_master_info;

6.5 在線清理方案(pg_repack)

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

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

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

適用版本:PostgreSQL 12+

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

相關(guān)文章

  • PostgreSql從庫(kù)重新配置的詳情

    PostgreSql從庫(kù)重新配置的詳情

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

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

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

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

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

    基于PostgreSQL和mysql數(shù)據(jù)類(lèi)型對(duì)比兼容

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

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

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

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

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

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

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

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

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

    Postgresql查詢(xún)效率計(jì)算初探

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

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

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

最新評(píng)論

合江县| 自治县| 团风县| 永丰县| 册亨县| 乐安县| 岳西县| 玉门市| 西乌珠穆沁旗| 麟游县| 山西省| 玉山县| 孝感市| 广丰县| 承德市| 翼城县| 台州市| 睢宁县| 康保县| 东乡族自治县| 桐乡市| 正安县| 平度市| 富平县| 峨眉山市| 桂阳县| 济南市| 定结县| 孝昌县| 隆子县| 柳河县| 巴中市| 资溪县| 嘉鱼县| 江川县| 青田县| 涟源市| 黔西县| 白银市| 拜泉县| 烟台市|