PostgreSQL VACUUM 清理机制详解
2026/6/3 4:14:20 网站建设 项目流程

PostgreSQL VACUUM 清理机制详解

一、为什么需要 VACUUM?

PostgreSQL 使用MVCC(多版本并发控制)实现事务隔离:

  • UPDATE操作:本质是 DELETE + INSERT,旧版本数据并不会立即删除
  • DELETE操作:只是将数据标记为"已删除",物理空间不释放

这导致大量死元组(dead tuples)残留在表中:

┌──────────────────────────────────────────────────────┐ │ 表空间 │ │ [活跃数据] [死元组] [活跃数据] [死元组] [死元组] │ │ │ │ 死元组累积 → 空间浪费 → 查询变慢 → 需要 VACUUM │ └──────────────────────────────────────────────────────┘

VACUUM就是负责回收这些死元组、释放空间、更新统计信息的维护命令。


二、哪些操作会产生空间碎片?

2.1 高频 UPDATE

每次 UPDATE 都会保留旧版本,旧版本变成死元组:

-- 订单状态每次变更,都产生一个旧版本死元组UPDATEordersSETstatus='PAID'WHEREorder_id=12345;UPDATEordersSETstatus='SHIPPED'WHEREorder_id=12345;UPDATEordersSETstatus='DELIVERED'WHEREorder_id=12345;
初始: Page 1: [Row-v1] [空闲] [空闲] [空闲] 3次UPDATE后: Page 1: [Row-v1(死)] [Row-v2(死)] [Row-v3(死)] [Row-v4] ← 60% 空间被死元组占用

2.2 高频 DELETE

大量删除后,空间被死元组占据无法重用:

-- 每天删除过期日志DELETEFROMinterface_execution_logWHEREstart_time<now()-interval'90 days';

⚠️ 即使删除了 500 万行,表文件大小也不会缩小,空间不会归还给操作系统。

2.3 批量数据导入 + 清理

-- Step 1:导入 1000 万行临时数据INSERTINTOodh_sell_in_inboundSELECT*FROMexternal_source;-- Step 2:数据处理完毕,删除临时数据DELETEFROModh_sell_in_inboundWHEREbatch_id='xxx';-- 结果:表大小维持在 1000 万行的体量,内部全是死元组空洞

2.4 长时间未提交的事务

-- 事务 A 开启但长时间未提交BEGIN;SELECT*FROMlorder_master_infoWHEREid=1

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询