CodeWalk

Delta Lake Vacuum与Deletion Vector的存储回收机制

作者:屠龙少年 · 2026-05-30 12:55

Delta Lake的VACUUM命令和Deletion Vector(删除向量)如何配合实现高效的存储回收?请解释Deletion Vector的『软删除』机制:标记删除而非立即物理删除,配合VACUUM的物理清理策略(retention duration阈值),以及如何避免误删正在使用的文件。给出一个Delta Lake VACUUM的配置示例和监控方法。

回答

屠龙少年

Delta Lake Vacuum与Deletion Vector存储回收:

1. Deletion Vector(删除向量)

  • Delta 2.3+引入的『软删除』机制
  • 当执行DELETE/UPDATE/MERGE时,不在数据文件中真正删除
  • 而是在_delta_log/中记录Deletion Vector:标记哪些行被删除
  • 读取时自动过滤Deletion Vector标记的行
Parquet File [0,1,2,3,4,5,6,7,8,9]  → 原始文件
Deletion Vector: [2, 5, 7]             → 标记删除行2,5,7
读取结果: [0,1,3,4,6,8,9]              → 自动跳过

2. VACUUM物理清理

-- 物理删除7天前未被引用的文件
VACUUM delta.`/path/table` RETAIN 168 HOURS;
  • 删除未被任何Delta Log引用且超过保留期的文件
  • 默认保留期:7天(168小时)
  • VACUUM前确保所有Reader已切换到新的Snapshot

3. 配置示例

-- 设置默认保留期(SparkSession级别)
SET spark.databricks.delta.retentionDurationCheck.enabled = false;
SET spark.databricks.delta.vacuum.parallelDelete.enabled = true;

-- 执行VACUUM
VACUUM delta.`/path/table` RETAIN 168 HOURS;

-- 仅预览要删除的文件(不实际删除)
VACUUM delta.`/path/table` DRY RUN;

4. Deletion Vector + VACUUM配合流程

时间线:
  t0: INSERT 100行 → Base File A
  t1: DELETE 10行 → Deletion Vector标记删除 (File A的10行标记)
  t2: VACUUM → 文件A仍被t1的Delta Log引用 → 不删除
  t3: OPTIMIZE → 新文件B包含未删除的90行
  t4: 删除t1的Delta Log(触发条件)
  t5: VACUUM → 文件A不再被任何Log引用 → 物理删除

5. 最佳实践: | 操作 | 说明 | |------|------| | VACUUM频率 | 每日或每周运行 | | 保留期 | 7天(默认,足够下游消费) | | DRY RUN先行 | 先预览要删除的文件再实际执行 | | 监控 delta.log.fsMetrics.numDeletedFiles | 确认删除文件数 |

6. 监控方法

-- 查看表文件清单
DESCRIBE DETAIL delta.`/path/table`;
-- 查看.numFiles和.totalSize

-- 查看已标记删除的行
SELECT COUNT(*) FROM delta.`/path/table` VERSION AS OF 1
EXCEPT
SELECT COUNT(*) FROM delta.`/path/table`;