DuckDB 等了三年的 Hudi,一个社区扩展补上了
DuckDB 官方仓库里有一条开了三年多的讨论:能不能读 Hudi 表。
2023 年 9 月有人发帖提问,当时的结论是做不了——Hudi 没有原生 reader,也没有稳定的 API。三年过去,这条帖子在 2026 年 10 月被 Apache Hudi 的 committer 重新翻出来:hudi-rs 已经成熟到可以当 kernel 用了。
现在答案落地:hudi 扩展进了 DuckDB 社区扩展库,INSTALL hudi FROM community 一条命令可用。
● ● ●
先看它做了什么
DuckDB 此前能读湖仓三件套中的两件:Iceberg 有官方 iceberg 扩展,Delta Lake 有官方 delta 扩展。Hudi 一直是缺口,官方没有排期,社区也迟迟没人接。
hudi 扩展补的就是这块。它自己不实现任何 Hudi 逻辑——时间线解析、file slice 发现、schema 推导、COW/MOR 合并,全部交给 Apache 官方维护的 Rust 内核 hudi-rs。扩展只做一件事:把 hudi-rs 的 Arrow 输出通过 Arrow C Data Interface 桥进 DuckDB。
这个架构和官方 delta 扩展用 delta-kernel-rs 的路子完全一致。内核是唯一事实源,扩展层不含时间线或 Parquet 解析逻辑。
● ● ●
实测
以下全部在本机 DuckDB 1.5.6 上跑通,测试数据是 hudi-rs 仓库自带的样例表(v6 版本、非分区)。
读 COW 表:
INSTALL hudi FROM community;
LOAD hudi;
SELECT * FROM read_hudi('/path/to/hudi_table');
读 MOR 表(Merge-on-Read)是 hudi 扩展真正的硬骨头:base file 加 log file 的合并由 hudi-rs 内核完成,实测 4 行全对。
时间旅行,回到某个 commit 之前的快照:
SELECT * FROM read_hudi('/path/to/table',
as_of => '20250117083125837');
增量读取,只取两个 commit 之间的变更:
SELECT * FROM read_hudi('/path/to/table',
start => '20250117083125837', "end" => '20250117083136333');
"end" 要加引号,因为它是 SQL 保留字。as_of 和增量窗口互斥,混用会直接报错。
两个标量函数查表元数据:
SELECT hudi_info('/path/to/table');
-- Hudi table: type=MERGE_ON_READ base_format=parquet
-- latest_commit=20250117083136333 commits=2 files=2
SELECT hudi_files('/path/to/table');
-- 每个 file slice 一行:路径、COW/MOR/LOG 类型、大小、log 文件数
实测的行数对得上样例表的预期:COW 全扫 4 行,MOR 全扫 4 行,时间旅行回到第一个 commit 是 3 行,增量窗口(两个 commit 之间)是 2 行。
● ● ●
为什么是现在
这个时间点不是巧合。hudi-rs 0.5.0 在 2026 年 9 月发布,原生支持 COW 和 MOR 两种表类型,暴露 C ABI。三年前讨论里说的「没有稳定 API」的前提变了,集成才成为可能。
DuckDB 侧的收录流程也走完了:PR 经 DuckDB Labs reviewer 审查通过,期间修掉了 Windows 工具链和 protoc 依赖两块硬骨头。目前覆盖 Linux 和 macOS 三个平台,Windows 暂缺——hudi-rs 还没在 Windows 上验证过,等上游验证后再开。
● ● ●
顺带修了一个文档 bug
收录时的示例代码把函数名写错了:官网示例用的是 hudi_scan(),实际注册的函数是 read_hudi(),示例里还有个源码里根本不存在的 incremental = true 参数。照官网示例跑会直接报 binder 错误。修复 PR 已提交,合并后官网示例与真实 API 对齐。
写文章时我把 pinned ref 的源码逐行核过:表函数的参数就是 as_of / start / end / hudi_option 四个 named parameter,没有藏起来的第五个。
● ● ●
适合谁
手上有 Hudi 表、又想在本地快速查询的人。不用起 Spark 集群,不用配 JVM,DuckDB 直接读。时间旅行和增量读这两个能力让「查某个时间点的表」「只拉新增数据」变成了 SQL 里一个 named parameter 的事。
云上的表也能读:S3 路径直接传,凭证走 hudi_option => 'hoodie.s3.access_key_id=…' 透传给内核。
湖仓三件套在 DuckDB 里到齐了:Iceberg 官方、Delta 官方、Hudi 社区。嵌入式分析库读湖仓格式,这条路走通了。
● ● ●
参考来源
https://github.com/duckdb/duckdb/discussions/8925
https://github.com/duckdb/community-extensions/pull/3043
https://github.com/apache/hudi-rs
https://github.com/alitrack/duckdb-hudi