alitrack

duckOrch:Dagster 的核心能力,装进一个 DuckDB 扩展

飞机上没网,数据管道照样自动跑——听起来像广告词,装完这个扩展它就是字面事实:

INSTALL duckorch FROM community;
LOAD duckorch;

两句 SQL 之后,你的 DuckDB 里多了一整套资产编排:任务依赖图、分区重跑、调度传感器、增量物化、血缘图谱。这套东西在别的生态里叫 Dagster,叫 Airflow,需要单独部署一个调度服务。duckOrch 把它压进了一个 47MB 的扩展文件。

● ● ●

它解决什么问题

用 DuckDB 做分析的人迟早撞上一堵墙:SQL 写得再顺,多个 SQL 之间的依赖、重跑、定时刷新,DuckDB 自己不管。老办法是外挂一个调度器——Airflow 起个服务,dbt 拉一套项目结构,或者干脆 cron + shell 脚本。对单机本地分析来说,这些都太重了。

duckOrch 的答案是:任务就是一个 .sql 文件,元数据写在头注释里——

-- @asset analytics.clean_users
-- @inputs raw.users
-- @test "SELECT COUNT(*) FROM analytics.clean_users WHERE user_id IS NULL" expect 0
CREATE TABLE analytics.clean_users AS
SELECT * FROM raw.users WHERE user_id IS NOT NULL;

@inputs 甚至可以不写:扩展内置 sqlparser,直接从 SQL 语句里推断出 raw.users → analytics.clean_users 的依赖关系,自动建 DAG。这是 SQLMesh 一脉的思路,git 友好,零额外文件格式。

注册和执行各一句:

PRAGMA orch_register('sql/');
PRAGMA orch_run('analytics.clean_users');

● ● ●

宣称的能力,逐条真跑核验

这个项目的 README 写得相当满,我把官方 DuckDB v1.5.5 CLI 和 community-extensions 的 v0.3.0 二进制拉下来逐条验证过:

能力
宣称
实测
DAG 拓扑执行
按依赖序跑任务
✅ 两任务 DAG 依序执行,runs 表记录 success
依赖自动推断
从 SQL 抽取 inputs
✅ 无需声明,推断正确
资产一阶化
__orch__.assets
 表
✅ 注册后资产入表
分区重跑
@partitions_by
 + $partition_key
✅ parser 正确绑定日期分区参数
自动化条件 DSL
eager/on_cron/on_missing 等 + AND/OR/NOT
✅ 复合条件解析正确
target_lag 增量
Snowflake Dynamic Tables 语义
✅ @target_lag 5min 解析为 300 秒
动态资产
合成资产 + 自动依赖
✅ 创建成功,依赖自动推断
Mermaid 血缘
一句出图
✅ 输出 graph LR 格式
JSON ingestion
父子表 + merge
✅ 嵌套 JSON 拆成两张表,merge 删旧行插新行,语义正确

全部通过。核心账本 __orch__ schema 下有 19 张状态表:资产、分区、物化记录、自动化评估留痕、血缘、schema 版本台账。这套状态模型是整个扩展最见功力的部分——分区级的状态追踪和条件评估留痕,很多成熟调度工具都没做到这个 granularity。

函数面一共 40 个:33 个 PRAGMA 加 7 个标量函数,同一套能力开放三条通道——SQL 内嵌、独立 CLI、MCP server(9 个工具,供 AI agent 调用,写操作默认 dry_run)。

● ● ●

架构:为什么 C++ 和 Rust 各一半

扩展本体是个三明治:约 5,100 行 C shim 加 9 个 Rust crate 共约 11,400 行。这个分工有真实的技术理由——DuckDB 的稳定 C 扩展 API 不暴露 optimizer 和 parser hook,纯 Rust 写不了列级血缘捕获,所以必须有一层 C;而解析、DAG、血缘这些复杂逻辑用 Rust 写,通过 FFI 边界交给 C++ 层执行。

依赖面克制得不像单人项目:核心 crate 只用 serde/chrono/cron,血缘只用 sqlparser,没有把 tokio 泄漏进核心。测试函数 258 个,还带 DuckDB 原生 e2e 测试套件。能进 community-extensions 注册表本身就是硬门槛——Linux/macOS/Windows 三平台加多版本 DuckDB 的 CI 矩阵全绿才收,作者为 MSVC 兼容性专门修过三个 commit。

● ● ●

一个人的项目,AI 的产能

看到这你可能以为背后是个团队。实际数据:3 个 star,0 fork,贡献者 1 人——日本独立数据工程师 nk,GitHub 上还有 duckSMILES、duckMuPDF、duckdb-midi 一串 DuckDB 扩展作品。

时间线更夸张:2026 年 5 月 1 日建仓,五天内完成了 parser、DAG、执行、重试、并行、CLI、增量、调度、OpenLineage 九个阶段;四个月后的 v0.3.0 已在官方注册表发布。54 个 commit 里 48 个带着 Claude Opus 的 co-author 署名,占 89%——单人加 AI 深度协作,把这个体量的工程从零做到官方收录。

这是「AI 时代一个人能交付什么」的一个实测锚点。同类证据正在多起来,这一个的特别之处在于:它是过的了官方 CI 的基础设施代码,不是 demo。

● ● ●

该知道的另一面

诚实框,以下同样是一手核验:

  • 社区验证为零
    。3 star、0 fork,HN 上搜不到任何真实讨论,唯一的外部 issue 是一位开发者提的函数文档改进请求(统计出 40 个函数 0 描述、0 示例)。bus factor = 1,作者弃坑就是终点。
  • 两处文档漂移
    。README 里 @test 示例用单引号,parser 实际只认双引号;更麻烦的是带单引号的任务文件会被 orch_register 静默跳过——不报错、不注册。编排工具静默失败是大忌。
  • 47MB 的扩展体积
    ,静态链 Rust workspace 的代价。CLI 和 MCP server 没有发布二进制,要用得自己 cargo build。
  • CLI 有个小怪癖:duckdb -c "PRAGMA orch_init" 在 v1.5.5 报 pragma 不存在,同样内容走 stdin 却正常。版本特异问题,根因未明,如实记录。

● ● ●

值不值得用

分场景看。单机本地分析、SQL 文件本来就在 git 里管理、想要分区级 backfill 和自动化传感器——duckOrch 是目前 DuckDB 生态里唯一的严肃选项,gh search repos "duckdb orchestration" 找不出第二个同类。生产环境的关键链路,单人项目加零社区的现状要掂量着来。

编排这个层到底该不该长在数据库里,业界吵了很多年。duckOrch 给出了一个极端样本:能长,而且长得完整。至于这个品类是真需求还是伪需求——3 个 star 和一个注册表收录,现在还回答不了这个问题。

● ● ●

参考来源

  • https://github.com/nkwork9999/duck-orch
  • https://github.com/duckdb/community-extensions/tree/main/extensions/duckorch
  • https://community-extensions.duckdb.org