Delta Lake 是什么
Delta Lake 在 Parquet 文件之上增加一个 _delta_log 事务日志:每次提交写入一个 JSON 文件记录新增与移除的文件,并定期生成 checkpoint 加快读取。有了这层日志,对象存储上的数据获得了 ACID 事务、时间旅行、模式强制与 MERGE 更新能力。它与 Spark 生态结合最紧密,MERGE INTO、OPTIMIZE、Z-ORDER、Change Data Feed 都是原生的,适合以 Spark 批处理为主的湖仓链路。
基本信息
| 核心机制 | _delta_log 目录按提交顺序记录 JSON 日志,并周期性生成 checkpoint |
|---|---|
| 主要能力 | ACID 事务、时间旅行、模式强制、MERGE 更新 |
| 时间旅行 | VERSION AS OF 或 TIMESTAMP AS OF,配合 DESCRIBE HISTORY 定位 |
| 模式强制 | 写入类型不匹配直接拒绝,可开启合并模式放宽 |
| 文件优化 | OPTIMIZE 合并小文件,Z-ORDER 按列聚集数据 |
| 空间清理 | VACUUM 删除不再被引用的旧文件,默认保留约 7 天 |
| 变更订阅 | Change Data Feed 可把行级变更暴露给下游 |
| 生态 | 以 Spark 为主,其他引擎通过连接器读取 |
典型使用场景
- 按主键更新明细:MERGE INTO 一条语句完成匹配更新与不匹配插入
- 下游增量消费:开启 Change Data Feed,把变更行直接暴露给流式消费方
- 小文件治理:定期 OPTIMIZE,对高频过滤列再做 Z-ORDER 聚集
- 数据回看与审计:用 DESCRIBE HISTORY 看每次提交,用时间旅行读特定版本
- 脏数据防护:依赖模式强制在写入阶段拦住类型不匹配的数据
Delta 常用操作
Delta 常用操作
CREATE TABLE demo.db.trade_order (
order_id STRING,
pay_amt DECIMAL(18,2),
dt DATE
) USING delta PARTITIONED BY (dt);
-- 按主键更新:匹配则更新,不匹配则插入
MERGE INTO demo.db.trade_order t
USING stg_order s ON t.order_id = s.order_id
WHEN MATCHED THEN UPDATE SET t.pay_amt = s.pay_amt
WHEN NOT MATCHED THEN INSERT *;
-- 合并小文件并按查询列聚集
OPTIMIZE demo.db.trade_order ZORDER BY (order_id);
-- 查看提交历史,定位异常写入
DESCRIBE HISTORY demo.db.trade_order;
-- 清理不再被引用的旧文件,会同时缩短可回看范围
-- VACUUM demo.db.trade_order;关键操作逐项读法
| 操作 | 作用 | 注意 |
|---|---|---|
| DESCRIBE HISTORY | 查看每次提交的操作与时间 | 排查异常写入的第一站 |
| VERSION AS OF | 按版本号读取历史数据 | 依赖旧文件未被清理 |
| OPTIMIZE | 合并小文件 | 大表上开销较大,宜错峰执行 |
| Z-ORDER | 按列聚集数据 | 提升过滤命中,写入成本上升 |
| VACUUM | 删除无引用的旧文件 | 会缩短时间旅行可回看范围 |
模式强制会拒绝类型不匹配的写入。为了导入脏数据而开启合并模式之后,类型约束实际上就失效了,脏数据会长期留在表里,事后清洗成本远高于写入时拦住。
VACUUM 删除的是不再被引用的旧文件。清理之后再想通过时间旅行读取早于保留期的版本就没有可能,清理前要确认审计与回滚窗口都已满足。