Hudi 是什么
Hudi 是面向数据湖的增量更新表格式,核心能力是在对象存储上做记录级 upsert 与删除,让湖上的表能被持续更新而不必整分区重写。它用两种表类型满足不同的读写偏好:COW 写时复制,更新时直接重写数据文件,读路径最简单;MOR 合并读,更新先写日志文件、读取时合并,写入代价小但读取要多一层合并。哪一条记录算最新,由主键与预合并字段共同决定。
基本信息
| COW | 写时复制,更新即重写文件,读路径简单 |
|---|---|
| MOR | 写日志文件,读取时合并,延迟低写放大小 |
| 关键字段 | recordkey 主键 + precombine 排序字段 |
| 表服务 | compaction 合并日志、clean 清理旧文件、归档时间线 |
| 写入模式 | insert、upsert、bulk_insert 等 |
| 典型引擎 | Spark、Flink 均可写入与读取 |
PySpark 写入 Hudi 表
PySpark 写入 Hudi 表
hudi_options = {
'hoodie.table.name': 'orders',
'hoodie.datasource.write.recordkey.field': 'order_id',
'hoodie.datasource.write.precombine.field': 'updated_at',
'hoodie.datasource.write.table.type': 'COPY_ON_WRITE',
}
df.write.format('hudi').options(**hudi_options) \
.mode('append').save('/warehouse/orders_hudi')
# 读取时可指定快照或增量视图
spark.read.format('hudi').load('/warehouse/orders_hudi')典型使用场景
- 近实时入湖:CDC 数据持续 upsert,下游按快照读取最新状态
- 按主键去重:源端重复投递时用主键与预合并字段保留最新记录
- 增量消费:下游只读某一时间点之后的变更,而不全量扫描
- 历史回溯:需要查询某个时间点的表状态时使用时间旅行
- 写多读少:写入压力大时用 MOR 降低写入开销,读时再合并
两种表类型对比
| 维度 | COW | MOR |
|---|---|---|
| 写入方式 | 直接重写数据文件 | 写日志文件 |
| 读取方式 | 直接读数据文件 | 读取时合并日志与数据 |
| 写放大 | 较高 | 较低 |
| 读延迟 | 稳定 | 受日志大小影响 |
| 需要维护 | compaction 影响较小 | 需安排日志合并 |
同主键多版本记录以 precombine 字段较大者为准,字段选错会导致旧数据覆盖新数据。
MOR 表长期不合并日志,读取时要在查询阶段完成大量合并,延迟会持续上升;表服务需要纳入调度而不是手动临时执行。