欢迎光临
我们一直在努力

Iceberg vs Hudi vs Delta Lake:数据湖三引擎深度压测与选型

一、三巨头概览

1.1 数据湖格式要解决什么

传统数据湖(HDFS + Parquet)的问题是:

问题说明
无 ACID 并发写入数据不一致
无 Schema 演进 加列需要重写整表
无 Time Travel 无法回到历史版本
无 Upsert 不支持行级更新
小文件问题 流式写入产生大量小文件

数据湖格式(Table Format)在 Parquet 之上加了元数据管理层,解决上述问题。

1.2 三引擎对比一览

维度IcebergHudiDelta Lake
起源 Netflix(2018) → Apache Uber(2017) → Apache Databricks(2019)
核心引擎 Spark/Flink/Trino Spark/Flink Spark(深度集成)
表类型 仅 Copy-on-Write CoW + Merge-on-Read CoW + MoR(2023+)
索引 分区 + Manifest Bloom/Record Level/分区 分区 + Data Skipping
社区活跃度 高(多引擎) 中(Databricks 主导)
生态开放 最开放 开放 偏 Databricks

二、架构设计对比

2.1 Iceberg 架构

┌─────────────────────────────────────────┐
│             Iceberg Table               │
│                                         │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Metadata   │ │ Manifest List   │ │
│ │ (.json)     │ │ (Snapshot 层级) │ │
│ └──────┬──────┘ └────────┬────────┘ │
│         │                   │           │
│ ┌──────▼──────────────────▼────────┐   │
│ │       Manifest Files           │   │
│ │ (文件级元数据: 路径/统计/分区)   │   │
│ └──────────────┬──────────────────┘   │
│                 │                       │
│ ┌──────────────▼──────────────────┐   │
│ │     Data Files (Parquet)       │   │
│ │ file_1.parquet file_2.parquet │   │
│ └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

特点:
– 三层元数据: metadata.json → manifest list → manifest
– Manifest 文件记录每个数据文件的分区值和统计信息(min/max)
– 读取时通过 Manifest 过滤无关文件,效率极高
– 不依赖 Hive Metastore(可独立工作)

2.2 Hudi 架构

┌─────────────────────────────────────────┐
│               Hudi Table                 │
│                                         │
│ ┌─────────────────────────────────────┐│
│ │           Timeline                   ││
│ │ (instants: commit/deltacommit/…) ││
│ └──────────────────┬──────────────────┘│
│                     │                   │
│ ┌──────────────────▼──────────────────┐│
│ │         Index (多种类型)             ││
│ │ Bloom / Simple / Bucket / Record   ││
│ │ Level (HBase / RocksDB)             ││
│ └──────────────────┬──────────────────┘│
│                     │                   │
│ ┌──────────────────▼──────────────────┐│
│ │     File Groups                   ││
│ │ ┌──────────┐ ┌──────────────────┐││
│ │ │ Base     │ │ Log Files         │││
│ │ │ (.parquet)│ │(.log, MoR 模式) │││
│ │ └──────────┘ └──────────────────┘││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘

特点:
– Timeline 串起所有操作,天然支持增量查询
– Index 实现 Upsert 的快速定位(O(1) 或 O(log n))
– MoR 模式: 写入先写 Log,读取时合并 Base + Log
– 强项: CDC、Upsert、近实时流式入湖

2.3 Delta Lake 架构

┌─────────────────────────────────────────┐
│             Delta Table                 │
│                                         │
│ ┌─────────────────────────────────────┐│
│ │     _delta_log/ (事务日志)         ││
│ │ 00000000000000000000.json           ││
│ │ 00000000000000000001.json           ││
│ │ …                                 ││
│ │ – 每次 commit 一个 JSON             ││
│ │ – 记录 AddFile/RemoveFile 操作     ││
│ │ – Checkpoint 文件定期生成           ││
│ └──────────────────┬──────────────────┘│
│                     │                   │
│ ┌──────────────────▼──────────────────┐│
│ │     Data Files (Parquet)           ││
│ │ file_1.parquet file_2.parquet     ││
│ │ 每个文件记录 stats (min/max/count)   ││
│ └─────────────────────────────────────┘│
└─────────────────────────────────────────┘

特点:
– 最简单的元数据结构: 事务日志 JSON 序列
– Data Skipping: 基于 Parquet 文件的 min/max 统计
– 与 Spark 深度集成, 性能优化好
– Databricks 商业主导, 开源版部分功能受限


三、特性矩阵对比

特性IcebergHudiDelta Lake
ACID 事务
Schema 演进 ✅ 加列/删列/改类型 ✅ 加列/删列 ✅ 加列/删列
分区演进 ✅ 隐藏分区 ✅ 基本支持 ❌ 固定分区
Time Travel ✅ 增量查询
Upsert/Delete ✅ (CoW) ✅ CoW + MoR ✅ CoW + MoR
并发写入 ✅ 乐观锁 ✅ 乐观锁(Lock) ✅ 乐观锁
小文件合并 ✅ 合并文件 ✅ Compaction ✅ OPTIMIZE
Bloom Filter
增量查询 ✅ (原生强项) ⚠️ 有限支持
引擎兼容 Spark/Flink/Trino/Presto Spark/Flink Spark(最佳)
流批一体

四、压测环境

4.1 硬件与集群

集群: 5 节点 (1 Master + 4 Worker)
CPU: 32C64G per node
磁盘: 4TB NVMe SSD per node
内存: 256GB per node
网络: 10Gbps
Spark: 3.5.0 (YARN 模式)
引擎版本: Iceberg 1.5.2 / Hudi 0.15.0 / Delta 3.2.0

4.2 测试数据

数据集: 模拟电商订单数据
总行数: 1 亿行
数据量: ~500 GB (Parquet 未压缩)
Schema: order_id, user_id, product_id, amount, status, city, ts
分区: 按日期分区 (2026-01-01 ~ 2026-08-31, 共 243 天)


五、写入性能压测

5.1 批量写入(全量初始化)

# Iceberg 批量写入
spark.sql("""
  CREATE TABLE iceberg.orders (
      order_id STRING, user_id STRING, product_id STRING,
      amount DOUBLE, status STRING, city STRING, ts TIMESTAMP
  ) USING iceberg
  PARTITIONED BY (days(ts))
""")

# 写入 1 亿行
spark.sql("INSERT INTO iceberg.orders SELECT * FROM source_orders")

引擎写入时间写入吞吐(rows/s)数据文件数平均文件大小
Iceberg 38 min 43,860 486 1.03 GB
Hudi (CoW) 52 min 32,051 512 0.98 GB
Hudi (MoR) 41 min 40,650 486+243 log 1.0 GB + logs
Delta 35 min 47,619 470 1.06 GB

分析:

  • Delta 写入最快,因为与 Spark 深度集成优化

  • Hudi CoW 最慢,因为 Upsert 需要查 Index 定位

  • Iceberg 表现稳定均衡

5.2 流式写入(增量 Upsert)

模拟 CDC 增量入湖,每分钟 10 万行 Upsert:

# Hudi MoR 流式 Upsert (最强项)
hudi_df.write.format("hudi") \\
  .option("hoodie.table.type", "MERGE_ON_READ") \\
  .option("hoodie.datasource.write.operation", "upsert") \\
  .option("hoodie.index.type", "BUCKET") \\
  .option("hoodie.bucket.index.num.buckets", "64") \\
  .mode("append").save(base_path)

引擎Upsert 吞吐延迟(P99)小文件增长
Iceberg 12,000 rows/s 4.2s 中(需合并)
Hudi (MoR) 28,000 rows/s 1.8s 低(log 模式)
Hudi (CoW) 5,500 rows/s 8.5s
Delta 15,000 rows/s 3.5s 中(需 OPTIMIZE)

分析:Hudi MoR 在 Upsert 场景碾压,因为 Log 文件写入极快,延迟低 3-5 倍。

5.3 Delete 性能

删除 500 万行数据(按 user_id 删除):

引擎Delete 时间方式
Iceberg 3.2 min 写 Delete File(不重写数据)
Hudi 4.8 min 重写受影响的 File Group
Delta 3.5 min 写 Tombstone 标记

六、读取性能压测

6.1 全表扫描

SELECT city, COUNT(*), SUM(amount) FROM orders GROUP BY city

引擎扫描耗时扫描文件数数据跳过效率
Iceberg 4.2 min 486/486 (100%) 基线
Hudi 4.5 min 512/512 (100%) 基线
Delta 4.0 min 470/470 (100%) 基线

全表扫描差异不大,因为都要读全部数据。

6.2 分区裁剪查询

SELECT * FROM orders WHERE ts BETWEEN

引擎扫描耗时扫描文件数跳过比例
Iceberg 8s 14/486 97.1%
Hudi 11s 16/512 96.9%
Delta 9s 14/470 97.0%

Iceberg 的 Manifest 过滤最精准,分区裁剪效率最高。

6.3 Data Skipping / 文件级过滤

— 基于 user_id 的等值查询
SELECT * FROM orders WHERE user_id = 'U12345678'

引擎扫描耗时扫描文件数命中行数
Iceberg 2.1s 3/486 1,245
Hudi (Bloom) 1.8s 2/512 1,245
Delta 2.3s 5/470 1,245

Hudi 的 Bloom Filter 在等值查询上效率最高,Delta 的 Data Skipping 依赖列统计效果一般。

6.4 Time Travel 性能

— Iceberg: 查询 3 天前的快照
SELECT COUNT(*) FROM orders.history
WHERE ts BETWEEN '2026-01-01' AND '2026-01-31'
— 使用 snapshot_id 指定历史版本

— Hudi: 增量查询
SELECT * FROM hudi_orders
WHERE _hoodie_commit_time > '20260801000000'
AND _hoodie_commit_time < '20260802000000'

— Delta: 历史版本
SELECT COUNT(*) FROM delta.orders VERSION AS OF 'v123'

引擎Time Travel 查询延迟实现方式
Iceberg 基线 Snapshot + Manifest 切换
Hudi 增量查询快 3 倍 Timeline 原生增量
Delta 基线 事务日志版本

七、Compaction 性能

7.1 小文件合并

流式写入 24 小时后,每个引擎平均产生约 5000 个小文件(平均 5MB):

引擎Compaction 命令耗时合并后文件数
Iceberg rewrite_data_files 18 min 486
Hudi 自动 Compaction 12 min 512
Delta OPTIMIZE 15 min 470

7.2 Compaction 期间对读写的影响

引擎写入影响读取影响
Iceberg 无影响(写新文件) 无影响(读旧 snapshot)
Hudi 轻微影响 轻微影响(MoR 需合并)
Delta 无影响 无影响

八、综合对比矩阵

评分维度IcebergHudiDelta Lake
批量写入 ★★★★☆ ★★★☆☆ ★★★★★
流式 Upsert ★★★☆☆ ★★★★★ ★★★★☆
读取-全表 ★★★★☆ ★★★☆☆ ★★★★★
读取-分区裁剪 ★★★★★ ★★★★☆ ★★★★☆
读取-等值查询 ★★★★☆ ★★★★★ ★★★☆☆
Time Travel ★★★★☆ ★★★★★ ★★★★☆
Schema 演进 ★★★★★ ★★★★☆ ★★★★☆
Compaction ★★★★☆ ★★★★★ ★★★★☆
引擎兼容性 ★★★★★ ★★★★☆ ★★☆☆☆
社区活跃 ★★★★★ ★★★★☆ ★★★☆☆
综合 4.3 4.1 3.9

九、选型决策树

你的场景是什么?

├─ 批处理为主,多引擎查询 (Trino/Presto/Spark)
│ └─→ Iceberg (引擎兼容性最佳)

├─ 流式 CDC + Upsert + 近实时
│ └─→ Hudi MoR (Upsert 吞吐 3 倍领先)

├─ Databricks 平台用户
│ └─→ Delta Lake (深度集成)

├─ 纯 Spark 批处理
│ └─→ Delta 或 Iceberg 皆可

├─ 需要增量查询 (CDC 同步)
│ └─→ Hudi (Timeline 原生增量)

├─ 分区演进/隐藏分区
│ └─→ Iceberg (唯一支持)

└─ 不确定/想要最均衡
  └─→ Iceberg (综合评分最高,生态最开放)

场景化推荐

场景推荐理由
日志归档 + Trino 即席查询 Iceberg 多引擎兼容 + 分区裁剪强
订单 CDC 实时入湖 Hudi MoR Upsert 吞吐 + 增量查询
Databricks 上的数仓 Delta 深度集成,Z-Order 优化
数据湖 + AI 特征工程 Iceberg 引擎兼容,多框架读
流批一体 Lakehouse Hudi MoR/CoW 双模式灵活

十、部署实战代码

10.1 Iceberg 快速开始

# Spark + Iceberg
spark = SparkSession.builder \\
  .config("spark.sql.extensions", "org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") \\
  .config("spark.sql.catalog.iceberg", "org.apache.iceberg.spark.SparkCatalog") \\
  .config("spark.sql.catalog.iceberg.type", "hadoop") \\
  .config("spark.sql.catalog.iceberg.warehouse", "s3://bucket/warehouse") \\
  .getOrCreate()

# 建表
spark.sql("""
  CREATE TABLE iceberg.orders (
      order_id STRING, user_id STRING, amount DOUBLE,
      status STRING, ts TIMESTAMP
  ) USING iceberg
  PARTITIONED BY (days(ts))
""")

# 写入
spark.sql("INSERT INTO iceberg.orders SELECT * FROM source")

# 查询历史快照
spark.sql("SELECT * FROM iceberg.orders.history").show()
# 输出: snapshot_id, timestamp, operation, …

# 小文件合并
spark.sql("CALL iceberg.system.rewrite_data_files('iceberg.orders')")

10.2 Hudi 快速开始

# Spark + Hudi
hudi_options = {
   "hoodie.table.name": "orders",
   "hoodie.table.type": "MERGE_ON_READ",
   "hoodie.datasource.write.operation": "upsert",
   "hoodie.datasource.write.recordkey.field": "order_id",
   "hoodie.datasource.write.precombine.field": "ts",
   "hoodie.datasource.write.partitionpath.field": "ts",
   "hoodie.index.type": "BUCKET",
   "hoodie.bucket.index.num.buckets": "64",
}

# 写入 (Upsert)
df.write.format("hudi").options(**hudi_options).mode("append").save(base_path)

# 增量查询
spark.read.format("hudi") \\
  .option("hoodie.datasource.query.type", "incremental") \\
  .option("hoodie.datasource.read.begin.instanttime", "20260801000000") \\
  .load(base_path)

10.3 Delta Lake 快速开始

# Spark + Delta
spark = SparkSession.builder \\
  .config("spark.sql.extensions", "io.delta.sql.DeltaSparkSessionExtension") \\
  .config("spark.sql.catalog.spark_catalog", "org.apache.spark.sql.delta.catalog.DeltaCatalog") \\
  .getOrCreate()

# 建表
spark.sql("""
  CREATE TABLE delta.orders (
      order_id STRING, user_id STRING, amount DOUBLE, ts TIMESTAMP
  ) USING DELTA
  PARTITIONED BY (DATE(ts))
""")

# 写入
spark.sql("INSERT INTO delta.orders SELECT * FROM source")

# 优化小文件
spark.sql("OPTIMIZE delta.orders")

# Time Travel
spark.sql("DESCRIBE HISTORY delta.orders").show()
spark.sql("SELECT * FROM delta.orders VERSION AS OF 5").show()


十一、总结

没有最好的数据湖格式,只有最适合的:

引擎一句话定位
Iceberg 最开放、最均衡,多引擎生态首选
Hudi 流式 Upsert + 增量查询最强项
Delta Spark 深度集成,Databricks 用户首选

选型时先确定核心场景,再按决策树走。不确定就选 Iceberg,综合评分最高且生态最开放。


下一篇预告:下一篇我们进入硬件 + Edge AI 领域:从 ESP32 传感器数据采集到 MQTT 上行到云端大模型推理的完整链路搭建。

往期文章:

vLLM Continuous Batching:5800 t/s 吞吐量的核心引擎。

Spark 3.5 AQE 调优:10 个生产环境案例让作业提速 3-10 倍。

RAG 架构设计 7 个关键决策:从 Chunk 策略到 Reranker 的生产级方案。

GPTQ vs AWQ vs GGUF:三大量化方案性能与精度横评。

树莓派 5 + TFLite 边缘部署实战:YOLOv8 目标检测跑出 30fps 的完整方案。

Kafka acks 机制性能实测:acks=all 在百万级吞吐下的延迟代价有多大。

llama.cpp Q4 量化原理拆解:10GB 显存跑 70B 模型的秘密。


觉得有帮助请点赞收藏。关注专栏 「AI大模型+大数据+硬件编程」,每周更新技术选型的深度对比内容。

赞(0)
未经允许不得转载:171主机测评 » Iceberg vs Hudi vs Delta Lake:数据湖三引擎深度压测与选型
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址