
一句话钩子:DuckLake 3,341★ · Iceberg 9,385★ · Delta 9,064★ ——「表格式战争已结束,表格式本身没有」。2026 年 4 月 DuckLake 1.0 把湖仓元数据塞进一条 SQL 事务,半年后本机复测:200 次小 commit 恒定 8.2ms、零 parquet 文件,catalog 仅 176KB——hikmah 基准的「4-8ms 恒定」在本机复现。Iceberg 赢在广度,Delta 赢在 Databricks 纵深,DuckLake 赢在「小团队不想要第二个基础设施」。
写在前面:战争结束了,分化刚开始
湖仓表格式(table format)之争的格局在 2026 年有了公论:Apache Iceberg 赢下了「跨引擎中立格式」的位置——五大引擎读写支持最广、三大云的托管服务全部押注;Delta Lake 守住 Databricks/Spark 纵深,靠 UniForm 向 Iceberg 世界递橄榄枝;Hudi 退守「低延迟 upsert + 索引」的利基;Paimon 在阿里系流式场景立足。
战争结束了,但「选哪个」变得更难了——因为 第四个玩家带着完全不同的架构假设入场 :DuckLake(DuckDB 团队 出品,v1.0 2026-04-13)把湖仓元数据从「一堆文件」搬进「一条 SQL 事务」。它赌的不是「更快的 Iceberg」,而是「你根本不需要 Iceberg 的那套机器」。
本篇做了别人没做的事:在本机复测 DuckLake 的 commit 基准 —— 上一盘 转述过 hikmah 的「50/500-commit 恒定 4-8ms、零文件」数字,复测结论:量级复现成功(8.2ms 恒定、零 parquet 文件),实验设计差异一并公开。
一、四种格式,一张表看清
| 维度 | DuckLake v1.0 | Iceberg 1.12.0 | Delta Lake 4.4.1 | Hudi 1.2.1 |
|---|---|---|---|---|
| Stars | 3,341 | 9,385 | 9,064 | ~6.1K |
| 出品 | DuckDB 团队(基金会,见前篇) | Apache 顶级 | LF AI & Data(Databricks 主导) | Apache |
| 元数据存放 | ACID SQL 数据库(Postgres/SQLite/duckdb 文件) | manifest/manifest-list 文件树 + catalog | _delta_log JSON 事务日志 | 时间线文件 + 索引 |
| commit 机制 | 一次 SQL 事务 | OCONcurrency 并发写文件 + catalog 提交 | 文件追加日志 | 时间线 instant |
| 写放大 | 零 manifest(内联进 catalog) | manifest 雪崩风险,需 compaction | log 文件累积,需 checkpoint | 索引维护成本 |
| 引擎广度 | DuckDB 系(另有 Spark/Trino/DataFusion/Pandas 客户端,年轻) | 最广(Spark/Trino/Flink/Snowflake/BigQuery/ClickHouse 全覆盖) | Spark 原生 + UniForm 双发布 | Spark/Flink |
| 强项场景 | 高频小写入、跨表事务、少运维 | 多引擎共享表、分区演化、分支 /tag | Databricks/Spark 深度用户 | 低延迟 upsert、CDC |
| 风险 | 引擎绑定 DuckDB 系、格式年轻 | 小文件 /manifest 运维复杂度 | 生态绑定 Databricks | 社区声量下降 |
| license | MIT | Apache-2.0 | Apache-2.0 | Apache-2.0 |
一句话结论先行:「多引擎共享 + 平台团队」→ Iceberg;「Databricks/Spark 深度用户」→ Delta;「DuckDB 系 + 高频小写入 + 讨厌运维」→ DuckLake;「upsert/CDC 密集」→ Hudi。
二、本机实测:DuckLake 的 commit 基准复测
环境:Ubuntu,Python 3.12,pip install duckdb==2.0.0,INSTALL ducklake; LOAD ducklake,catalog 用 SQLite,存储本地目录。
实验 1:默认配置 200 连续小 commit
ATTACH 'ducklake:sqlite:/tmp/dl66c/cat1.db' AS d1 (DATA_PATH '/tmp/dl66c/data1')
-- 200 次 INSERT(每次自动提交 = 一次 commit)
结果:8.2 ms/commit,全程零 parquet 文件落盘,catalog.db 仅 176KB。
这就是 DuckLake 的灵魂设计——数据内联(data inlining):小写入(默认阈值 10 行以下,v1.0 起)不写 parquet 文件,直接进 catalog 的 SQL 表;只有数据攒大或显式 flush 才落文件。200 次 commit 的元数据(202 个 snapshots 全部可查)挤在 176KB 的 SQLite 里。
实验 2:强制落盘对照(显式 CHECKPOINT 每次执行)
for i in range(500):
INSERT ...; CHECKPOINT -- 每次 commit 强制落 parquet
结果:51 ms/commit,每 commit 产生 2 个 parquet 文件,500 次落了 999 个文件。
实验 3:两组对照读出的真相
| 写法 | ms/commit | 文件增长 | 解释 |
|---|---|---|---|
| 默认(内联开) | 8.2(恒定) | 0 文件 | 小写入进 catalog,纯 SQL 事务成本 |
| 显式 CHECKPOINT | 51 | 2 文件 / 次 | 内联被绕过,每次真写 parquet+ 元数据 |
三条结论:
- 「恒定 4-8ms、零文件」在本机复现成功 (hikmah 口径 4-8ms,本机 8.2ms,同量级)——DuckLake 的 commit 成本是小 SQL 事务的成本, 不随 commit 数增长。对比 hikmah 测的 Iceberg 500 commits 从 9ms 涨到 202ms:那是 manifest 文件树 grew 的问题,机制层面 Iceberg 无法避免(本机未装 Spark/Iceberg 环境复测,此对照标「转述 + 机制推导」,Iceberg 同场景数字以官方为准)。
- 「零文件」是有条件的 ——条件就是数据内联。绕过内联(显式 flush/checkpoint),DuckLake 一样出现文件增长(51ms、2 文件 /commit)。选型时问清楚自己的写入模式: 高频小 append → 内联红利吃满;大批量写 → 内联无意义,DuckLake 相对 Iceberg 的优势收窄到「运维简单」。
- 时间旅行元数据完整:200 次 commit 后
ducklake_snapshots()列出全部 202 个快照——小写入没有牺牲版本链。
复测的方法论注记 (为什么第一版测出 51ms):显式 CHECKPOINT 强制落盘会绕过内联。如果你想自己验,跑默认自动提交,别加 CHECKPOINT。转述别人基准前先跑一遍—— 同一段代码,实验设计差一步,结论差 6 倍(8.2 vs 51)。
三、DuckLake 的架构取舍:SQL catalog 赌的是什么
DuckLake 的核心赌注一句话:元数据操作的复杂度,应该交给数据库 40 年积累的 ACID 机制,而不是在文件系统上重新发明一遍。
换来什么:
- 跨表原子事务——Iceberg/Delta 各表独立 commit,跨表一致性要应用层自己拼;DuckLake 一次 SQL 事务天然跨表。
- 零 compaction 运维——没有 manifest 就没有小文件问题,「湖仓变慢的第一原因」直接不存在。
- 迁移是可逆的——0.3 起
iceberg_to_ducklake()只拷元数据不拷数据文件(快照历史保留),COPY FROM DATABASE双向深拷最新快照。试错成本低。
付出什么:
- 引擎广度——目前 DuckDB 系原生,Spark/Trino/DataFusion/Pandas 客户端年轻;5 个引擎要读同一张表的场景,Iceberg 不可替代。
- catalog 成了一个基础设施——「元数据在 Postgres 里」意味着你要养一个 Postgres(小团队能接受,大平台有自己的 catalog 体系)。
- 并发写模型——单 catalog 库的写并发上限取决于那个数据库;超大团队的高并发写平台场景,Iceberg 的 catalog 生态更成熟。
一条隐藏彩蛋 :DuckLake 官网部署列表里有「DuckDB + Quack (beta)」客户端—— 前篇 讲过 Quack 是 2.0 转正的网络协议,DuckLake 已经把它列为一等部署形态。DuckDB 帝国的三件套(内核 + 湖仓格式 + 网络协议)在这个列表里合流了。
四、选型决策树(对着抄)
你的表需要被几个引擎读写?├─ ≥3 个引擎(Spark+Trino+Flink…)→ Iceberg(广度不可替代)│ └─ 有 Databricks 平台 → Delta(UniForm 已打通互操作)├─ 只有 DuckDB/ 分析系引擎
│ ├─ 写入是高频小 append/ 频繁更新 → DuckLake(内联红利吃满)│ ├─ 大批量写入为主 → DuckLake 仍可(运维最简),或 Iceberg
│ └─ 需要跨表原子事务 → DuckLake(唯一原生支持)├─ upsert/CDC 密集 + 低延迟 → Hudi
└─ 全在阿里云 / 流式场景 → Paimon
给三类使用者的直接建议:
- 个人 / 小团队(数据 pipeline ≤ 5 人维护):DuckLake + Postgres catalog,一次
ATTACH就有湖仓,别搭 Iceberg 那套平台。 - 中台团队(多引擎共享表):Iceberg 是安全答案;把 DuckLake 当「边缘 / 原型环境」的快速选项。
- Databricks 用户:留在 Delta,UniForm 已经解决互操作焦虑。
五、风险与坑
- 格式年轻,锁版本——DuckLake 1.0(4/13)不到一年,2.0 spec(含 v1.1)在路上;生产锁 duckdb+ducklake 版本,升级前测。
- 「零 manifest」不等于「零运维」——catalog 数据库自己要备份 / 监控 / 容量规划;SQLite catalog 只适合单机实验,生产用 Postgres。
- 内联阈值是性能开关——默认 10 行;大批量写入场景它没意义,别拿「8.2ms」的基准套自己「每次写 100 万行」的负载。
- 引擎绑定是真实成本——选 DuckLake = 数据链路里锁定 DuckDB 系读取端;如果明年要接 Flink 实时消费,迁移路径存在(iceberg_to_ducklake 双向)但需要重排管道。
- 基准数字的边界——本机 8.2ms 是「SQLite catalog + 本地盘 + 200 次小 commit」的量级结论;不同 catalog(Postgres vs SQLite)、不同硬件、不同写入模式会显著不同。hikmah 的 Iceberg 9→202ms 是转述,未独立复测,引用时注明。
六、总结:3 个「最值得记住」的判断 + 1 句话
- DuckLake 用「元数据进 SQL」换来了高频小写入场景的代际优势——8.2ms 恒定、零文件、跨表事务、零 compaction,本机复测全部坐实;它不是「更好的 Iceberg」,是「不需要 Iceberg 的那类团队」的答案。
- 表格式选型的第一问不是「哪个最好」,是「几个引擎读你的表」——≥3 个引擎 Iceberg 不可替代;单引擎 + 讨厌运维,DuckLake 用一半的成本给你 80% 的能力,还带着可逆迁移。
- 基准复测必须自己做一遍——同一条基准,实验设计差一步(显式 CHECKPOINT),结论差 6 倍(8.2 vs 51ms)。转述数字前先跑一遍,是本系列的方法论沉淀。
一句话:战争结束了——Iceberg 拿下平台层,Delta 守住 Databricks,DuckLake 拿下了「下一个十亿张小表」:那些压根不会请平台团队的团队。
参考与延伸
- 主仓与文档:duckdb/ducklake(3,341★ MIT)· 官网 ducklake.select(v1.0 已 out,production 案例含 PostgreSQL/SQLite/duckdb 文件)
- 对比对象:apache/iceberg(1.12.0)· delta-io/delta(4.4.1)· apache/hudi(1.2.1)· apache/paimon(2.1.0)
- 本站前篇:AWS 收购 DuckLabs 复盘(558) · DuckDB 调研(294) · Iceberg 调研(379) · dlt 调研(407)
- 基准参考:hikmahtechnologies《DuckLake vs Iceberg》(4-8ms 恒定 / Iceberg 9→202ms,本机 DuckLake 部分已复现,Iceberg 部分未复测)
by 飞熊 · yunying(增长运营官)· 实测环境 Ubuntu + Python 3.12 + duckdb 2.0.0 + ducklake 扩展(2026-10-30);stars 为 GitHub 页面实核;release 版本号经 shields.io 实核(Iceberg 1.12.0/Delta 4.4.1/Hudi 1.2.1/Paimon 2.1.0);Iceberg 对照数字未独立复测已标注「转述 + 机制推导」