alitrack

duckdb_orc 0.2.0:DuckDB 能写 ORC 了

DuckDB 至今不支持 ORC。2023 年有人在官方讨论区问过,维护者 hannes 的回答很直接:"No plans, ORC seems far less popular than Parquet"。直到现在,官方扩展列表里也没有 orc。

但 ORC 没死。Hive 的老用户在用,Trino 生态的主力格式也是它。国内很多数仓历史数据就是一堆 .orc 文件,想用 DuckDB 分析,只能先转格式。

我给 DuckDB 写的 ORC 扩展 duckdb_orc,0.1.x 时代只能读。今天 0.2.0 发布,补齐了写:一条 COPY 就能把任意查询结果写成 ORC 文件。

duckdb_orc 读写流程

duckdb_orc 读写流程

● ● ●

0.2.0 新增了什么

核心就一件事:写支持。

-- 读 ORC(0.1.x 就有)
SELECT * FROM read_orc('sales.orc');

-- 写 ORC(0.2.0 新增)
COPY sales TO 'sales_copy.orc' (FORMAT orc);

-- 任意查询结果都可以写
COPY (SELECT region, SUM(amount) AS total FROM sales GROUP BY region)
  TO 'region_total.orc' (FORMAT orc);

写入默认 ZSTD 压缩,2048 行一批流式写,文件多大都不占内存。整个扩展纯 Rust,基于 orc-rust 的 ArrowWriter。

● ● ●

实测验证

发布前我把读写都跑了一遍(DuckDB 1.5.5 + 本地构建的扩展):

读(内置 1 万行测试文件):

指标
结果
行数
10000
avg(score)
7499.25
min / max
0.0 / 14998.5

写 + 回读(100 行混合类型:int、varchar、double、bool、date、timestamp):

检查项
结果
回读行数
100,与源一致
数值完整性
sum 都是 7425.0,逐位一致
日期回读
2024-04-09,与源一致

不支持的类型:LIST 写入时给干净的 Binder Error,不会崩进程:

Binder Error: write_orc: type List(Field { data_type: Int32, nullable: true })
not supported by the ORC writer yet (supported: bool, int8-64, float32/64,
date, timestamp, varchar, blob)

● ● ●

已知边界

  • 写类型白名单
    :bool、int8/16/32/64、float32/64、date、timestamp、varchar、blob。list/struct/map/decimal 会被干净拒绝——上游 orc-rust 的 writer 还没实现这些编码
  • 列名是 column_N
    :DuckDB C API 的 COPY bind 不暴露源列名,所以写出来的 ORC 列名是 column_0、column_1……读回时注意按位置取列
  • 没有 filter pushdown
    :DuckDB C 扩展 API 没暴露这个接口,过滤在扫描后应用(投影下推是有的)
  • 写性能
    :ZSTD 压缩是默认且目前可切换的(改源码里的压缩配置)

● ● ●

怎么装

INSTALL orc FROM community;
LOAD orc;

社区注册表已经合并(duckdb/community-extensions#2589),全平台二进制由 CI 自动构建发布。源码在 github.com/alitrack/duckdb_orc,MIT 协议。

说实话,ORC 在国内数据栈里的存量比 GitHub 讨论区看起来大得多——Hive 时代留下的 .orc 仓库,很多公司到现在还在用 Trino 或 Spark 读。这也是我做这个扩展的原因。DuckDB 官方说 No plans 的格式,我用一个 10.7MB 的扩展补上了读写。ORC 文件在 DuckDB 里,不用先转格式了。

如果你也被 ORC 历史数据卡过:装了扩展后,COPY 一条语句转 Parquet 再分析,还是直接 read_orc 查,哪种更顺手?评论区聊聊。


参考来源

  1. 01
    DuckDB 官方对 ORC 的表态(维护者 hannes:No plans)https://github.com/duckdb/duckdb/discussions/6529
  2. 02
    DuckDB 社区扩展注册表 orc 条目(合并 PR #2589) https://github.com/duckdb/community-extensions/pull/2589
  3. 03
    duckdb_orc 源码仓库 https://github.com/alitrack/duckdb_orc
  4. 04
    上游 orc-rust(Arrow 读写) https://github.com/datafusion-contrib/orc-rust
  5. 05
    实测数据来源:DuckDB 1.5.5 + 本地构建的 v0.2.0 扩展(read/write/roundtrip 验证脚本)