首页/数据/数据工程与 ETL 速查/Apache Hudi 基础概念
管道基础52 条

Apache Hudi 基础概念

Hudi 面向湖上增量更新:记录级 upsert、两种表类型(COW 重写文件、MOR 写日志文件)、基于主键与预合并字段决定同键保留哪条。

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 降低写入开销,读时再合并

两种表类型对比

维度COWMOR
写入方式直接重写数据文件写日志文件
读取方式直接读数据文件读取时合并日志与数据
写放大较高较低
读延迟稳定受日志大小影响
需要维护compaction 影响较小需安排日志合并
同主键多版本记录以 precombine 字段较大者为准,字段选错会导致旧数据覆盖新数据。
MOR 表长期不合并日志,读取时要在查询阶段完成大量合并,延迟会持续上升;表服务需要纳入调度而不是手动临时执行。

易错点

  • MOR 表不压缩日志会累积读取开销,需要安排 compaction
  • recordkey 组合字段的拼接顺序与分隔符要固定,变更会破坏历史数据识别
  • precombine 字段选了不随更新变化的列,同主键记录无法正确取最新
  • 分区字段配置与查询条件不一致,写入时产生大量小分区
  • 把 Hudi 表当普通 Parquet 目录直接改写文件,时间线与数据集合失配

数据来源与参考

  • Apache Hudi 官方文档:Table Types 与 Write Operations
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌