DuckDB 2.0 Cyanoptera 来了:脚本里的 OLAP,现在可以开成服务了

引言

我们经常遇到的数据处理工作流大体是这样:写一段 ad-hoc 查询,Jupyter 单元跑出结果,截图扔 Slack。一旦同事问「这查询我能直接调一下吗」,断点就出现了。之前在脚本里、CLI 里、笔记本里直接跑 OLAP 的 DuckDB,必须靠导出 CSV、起一个 ClickHouse 副本、或者专门搭一个只读 Postgres 当 API。

DuckDB v2.0 想动的就是这条断点。8 月 17 日,Mark Raasveldt 和 Hannes Mühleisen 发了一篇 16 分钟的官方博文《A Preview of DuckDB v2.0》,正式代号 Cyanoptera(一种生活在 western Americas 的 cinnamon teal,学名 Anas cyanoptera)。该版本计划在 2026 年秋季正式发布,距离上一版 v1.5(Variegata,2026-03)已积攒超过 10,000 个 commit。GitHub 在 8 月 5 日刚突破 40,000 stars。

博文开篇最该拎出来的一句话:「Where last year was the year of the lakehouse, this release kicks off the year of DuckDB as a server.」这是 DuckDB 团队第一次把 server 模式当作主轴写。从工程师视角看,server 化意味着原本只能在单进程里完成的查询,现在能被远端复用、被并发调度、被嵌入到更大的服务链路里。

位置感:从 SQLite 走向 ClickHouse 的中间地带

DuckDB 一直把自己定位成「SQLite, but for OLAP」。这句话在 v1.0 时代(2024 年)成立:嵌入式 OLAP 引擎,没有 server 概念,所有查询跑在调用它的进程里。

v2.0 是 DuckDB 第一次明确往 server 这边走。表面看是补一个十年来人人都在喊的功能(让独立进程之间能通信)。往深一层看,它是对「嵌入式」定位的松绑:保留 in-process 的轻量,再加一个 client/server 的可选模式。

代价也在那里。v2.0 注定比 v1.4 LTS 更重、更复杂,官方明确声明带有「a small set of carefully chosen breaking changes」。最显眼的两条是新默认存储格式和重写的 C API,下文升级路径会再展开。

落到工程师视角,Cyanoptera 不再只是一个分析用的工具库,它开始接管一些原本属于数据仓库的边界场景。

6 个新特性:哪些真的会改变用法

挑了 6 个对日常开发影响最大的特性,每个都附官方 PR 编号便于查证。剩下的变更(DML-in-CTE / Nested schemas / 变量语法等)这次就不展开了。

1. DuckDB as a Server:quack 扩展 + CONNECT 语句

官方把服务端能力封装成一个叫 quack 的扩展。任何 DuckDB 进程可以 CALL quack_serve(token = '...') 起服务,客户端用 ATTACH 'quack:server.example.com' AS qk (TOKEN '...') 挂上来,再 CONNECT qk 切到远端会话执行查询。

CONNECT 不止支持 quack。新的远程下推优化器(PR #22914)会把 SQL 直接推给 PostgreSQL 和 MySQL 执行,表数据不再拖回本地。

DuckDB 本身是 MVCC、多连接、完整事务隔离的事务型引擎,只是单用户场景下没人需要这些特性。CONNECT 一上来,多租户长跑场景终于有用武之地。

2. Trigger:让 SQL 自己监听表上的变化

v1.x 时代 DuckDB 没有触发器。v2.0 一次性把 BEFORE / AFTERFOR EACH ROW / FOR EACH STATEMENTREFERENCING OLD/NEW TABLEDROP TRIGGER 全补齐。审计表这种典型场景第一次能纯 SQL 写出来。官方也透露 DuckDB 内部要靠 trigger 搭后续功能,比如实时事件流的物化视图。一个最小可用的审计 trigger 长这样:

sql 复制代码
CREATE TABLE audit (id INTEGER, old_val INTEGER, new_val INTEGER);
CREATE TRIGGER trg_audit AFTER UPDATE ON target
REFERENCING OLD TABLE AS o NEW TABLE AS n
FOR EACH STATEMENT
  INSERT INTO audit SELECT n.id, o.val, n.val FROM o JOIN n ON o.id = n.id;

搭配 server 模式,trigger 监听的对象可以来自远端 DuckDB 实例。

3. VARIANT 成为一等公民

VARIANT 在 v1.5 已经引入,思路是「imagine if JSON were fast」。v2.0 把整条流水线打通:shredded 执行直读存储(PR #20912)、提取下推到扫描层(PR #22478)、Parquet 读写都支持,再加一族 variant_* 函数。半结构化数据不再需要先 flatten 成宽表。

后续官方计划把常规 JSON 类型直接落到 VARIANT 之上,老的 JSON 工作流不改一行也能享受这些好处。

4. 异步 I/O:远程存储受益最大

7 月 31 日那篇 21 分钟的《Asynchronous I/O in DuckDB: Work, Thread, Work》详细写了设计思路,v2.0 落地。I/O 层和查询层解耦,远程读可以叠出比同步模型多得多的并行度。Parquet 先走通,CSV、DuckDB 自己的文件格式随后跟上,外加 MMAPDIRECT_IO 两个新模式。本地存储收益有限,远程存储收益巨大。

具体到工程语义:异步 I/O 把「读文件」从阻塞调用变成 prefetch + 后台提交 + 完成的回调链。这意味着 S3 上一个聚合查询可以同时发起多块远端读,CPU 不再被 IO wait 拖住。这套模型对单机本地 NVMe 收益有限(latency 已经够低),但跨区域或冷存储读取能直接换数量级。

5. 全新 SQL parser(PEG)

DuckDB 一直用的是从 PostgreSQL 继承下来的 parser,这次换成自研 PEG parser(PR #22194)。配合扩展体系,扩展可以直接挂到 grammar 上、自带新 SQL 语法,错误信息带精确源码位置。按官方说法,「你应该感觉不到差异」。如果感觉到了,去 issue tracker 报。

6. 存储格式 v2.0

默认存储版本升到 v2.0.0(PR #22875)。列元数据按需懒加载,宽表打开更快;DICT_FSST 字符串压缩默认开启;删除更紧凑;读取时 corruption 校验更严格。下半年 ART 索引还会做 buffer-managed,内存压力下能被驱逐。

存储格式的关键不变量是「向前兼容、不一定向后兼容」:v2.0 仍能读 v1.x 文件,但 v1.x 不一定能读 v2.0 默认写出的文件。对于需要长期归档数据的团队,这意味着要么锁回 v1 默认格式,要么确认全链路下游都升级到 v2.0 reader。官方在 release notes 里给了显式的迁移建议,但强制选项不在:reader 自己决定。

顺带一记性能基准:100 万边的图可达性递归 CTE 查询,v1.5.4 跑 4.90 s,v2.0 preview 跑 0.12 s,快约 40 倍。这背后是聚合下推到 join 之下、递归 CTE 引擎重写、聚合可 spill 到磁盘、min-max 索引(zone map)和 Parquet Bloom filter 现在能跳过 struct / list / decimal / UUID / IN 过滤和函数谓词。

谁会受影响(工程师视角)

  • 独立开发者和小团队:以前要部署 ClickHouse 或专门一个 DuckDB-as-a-service 才能干的活,现在自己跑一个 DuckDB 进程就够了。
  • 数据工程师:ETL 里「读 parquet → 转换 → 写回」的链路可以更短,shredded VARIANT 让 JSON 链路也跟着变轻。
  • ETL / 扩展工具作者:新 C API 把 ABI 稳定化(PR #24702),扩展作者不必每个 DuckDB 版本都重编,还能自建签名扩展仓库(PR #24777)。
  • BI 工具作者:server 模式和 trigger 终于能把 DuckDB 塞进仪表盘的实时刷新链路里。

何时不该用

DuckDB 没变。亿级以上并发查询、典型 OLTP 多写少读、强事务一致性场景,仍然是 ClickHouse / Snowflake / PostgreSQL 的领地。Cyanoptera 的 server 模式更适合多租户长跑场景,跟 ClickHouse 的水平扩展不是同一种生物。

选型时常会混的几条边界值得分清:ClickHouse 擅长固定 schema 下跑超大聚合,Snowflake 擅长云上弹性算力叠加治理,PostgreSQL 擅长事务一致性加单库分析,DuckDB 擅长本地或私有存储的灵活 schema 与 ad-hoc 探索。v2.0 让最后一条边界拓宽到「可服务化部署」,但语义没换。

升级路径

先看清时间表(来自 duckdb.org/release_calendar.html):

版本 关键日期 备注
v1.5.0(Variegata) EOL 2026-09-01 引入 VARIANT
v1.4.0 LTS(Andium) EOL 2026-09-16 社区支持窗口结束
v1.5.6 发布 2026-09-16 1.x 末班车
v2.0.0(Cyanoptera) Fall 2026 秋季正式发布

迁移成本来自三块:新默认存储格式(v1 文件可读,反向不一定)、重写的 C API(v2 扩展在 v1 上跑不动)、少量明确声明的 breaking changes。preview build 现在就能下,官方建议先在测试环境跑通,再切生产。

你接下来可以做的三件事

  1. 拉一份 S3 上的 Parquet 跑聚合查询,对比 v1.5.4 看远程读是否明显加快(异步 I/O 收益最大的场景)。
  2. 在 Jupyter 里用 VARIANT 类型直接 ingest JSON 日志,SELECT variant_keys(payload) FROM events 看 shredding 是否生效。
  3. 起一个 quack server,从另一台机器用 CONNECT 跨实例执行查询,验证 server 模式确实可用。

如果这三步都没炸,主要的 v2.0 收益就基本确认了。剩下的 PR 编号都在官方博文末尾列着,需要时可以查。

迁移前的实操清单:检查现有扩展是否在 v2.0 ABI 列表内、确认下游 reader 是否升级到 v2.0、把存量 v1.x 默认格式的数据决定保留还是迁移、给 quack server 准备 token 轮换机制。这四件事先过一遍,升级当天就不会有意外。


引用列表

  1. A Preview of DuckDB v2.0 - DuckDB 官方 - 2026-08-17
  2. HN Discussion: A Preview of DuckDB v2.0 - Hacker News - 抓取时(2026-08-20)710 points · 131 comments
  3. DuckDB Release Calendar - DuckDB 官方 - 持续更新
  4. Thank You for 40 000 Stars on GitHub - DuckDB 官方 - 2026-08-05
  5. Asynchronous I/O in DuckDB: Work, Thread, Work - DuckDB 官方 - 2026-07-31
  6. Announcing DuckDB 1.5.0 (Variegata) - DuckDB 官方 - 2026-03-09
  7. Reddit r/programming: A Preview of DuckDB v2.0 - Reddit - 8 月 17 日起讨论
相关推荐
lv__pf1 小时前
redis缓存数据库进阶
数据库·redis·缓存
鸽芷咕1 小时前
告别手工分表:金仓时序数据库超表架构落地的一次实战复盘
数据库
草莓熊Lotso1 小时前
【Redis 初阶】Hash 类型深度解析:结构化数据存储的最优解
linux·网络·数据库·redis·tcp/ip·缓存·哈希算法
nvd111 小时前
K3s + ArgoCD 中的密码管理
数据库·oracle·argocd
Wang's Blog2 小时前
PostgreSQL笔记62: 分区表维护最佳实践——默认分区、锁策略与性能调优
数据库·笔记·postgresql
熊出没2 小时前
解密数仓中的ODS、DWD、DWS、ADS
数据库·数据仓库
梦想不只是梦与想2 小时前
MySQL 不同操作系统的安装方式
数据库·mysql·mysql安装
熊文豪2 小时前
向量数据库单独建一套,这笔账划不划算
数据库
一只旭宝2 小时前
预约系统版本2(基于第一版改良)
服务器·数据库·c++