等了三年,DuckDB 终于从"嵌入式分析数据库"进化成了真正的"客户端-服务器架构"。
2026 年 10 月 21 日,DuckDB 2.0.0 LTS(代号 Cinnamon Teal,桂红茶色鸭)正式发布。这不是一次小版本迭代,而是一次架构层面的蜕变。Quack 协议让任何 DuckDB 进程都能变成服务器,异步 I/O 在不改一行代码的情况下把 S3 查询速度提升了 3 倍,VARIANT 类型让半结构化数据的查询性能暴涨 78 倍。
这篇文章会带你过一遍 2.0 的 6 大核心特性,看看哪些值得立刻上手,哪些迁移时要小心踩坑。
Quack 协议:DuckDB 变身为服务器
这是 2.0 最具颠覆性的特性。
过去 DuckDB 的定位是"嵌入式 SQLite 替代品",进程内运行,数据文件本地存储。Quack 协议打破了这个限制——任何 DuckDB 进程都可以作为客户端或服务器,基于 HTTP 协议通信,防火墙友好,支持认证和连接缓存。
三种连接方式
方式一:ATTACH + CONNECT(推荐)
这种方式会把整个会话路由到远程服务器,适合需要执行多条查询的场景。
方式二:ATTACH 作为完整 catalog
这种方式把远程服务器作为一个完整的 catalog,可以混合查询本地和远程数据。
方式三:quack_query() 函数
| |
无状态单次查询,适合偶尔需要远程执行的场景。
实际应用场景
Quack 协议打开了很多新的可能性:
- 数据湖查询:本地 DuckDB 连接远程 DuckDB 服务器,查询 S3 上的 Parquet 文件
- 分布式分析:多个 DuckDB 节点组成集群,各自处理分片数据
- 开发测试分离:开发环境用本地 DuckDB,生产环境连接远程服务器
不过要注意,Quack 目前还是早期阶段,生产环境部署前需要充分测试。
异步 I/O:零代码改动的 3 倍性能提升
这是最让我兴奋的特性。
DuckDB 2.0 重写了 I/O 层,将 I/O 与查询处理完全解耦。工作线程处理已到达的数据时,I/O 线程在后台继续预取。这意味着你的查询代码不需要任何修改,性能就会自动提升。
官方基准测试数据
| 场景 | v1.5.5(同步) | v2.0.0(异步) | 提升 |
|---|---|---|---|
| 单文件 S3 Parquet(2.2GB) | 9.344s | 2.945s | 3.2x |
| 多文件并行读取 | 基准 | - | ~3x |
| SSD 本地冷读 | 基准 | - | 1.5x |
| SSD 本地热读 | 基准 | - | 无差异(已缓存) |
S3 场景提升最明显,因为网络延迟是主要瓶颈。本地 SSD 热读已经很快了,异步 I/O 帮不上忙。
配置参数
异步 I/O 默认开启,通过 read_ahead_depth 控制预取深度:
支持格式
- ✅ Parquet
- ✅ CSV(未压缩、可寻址、UTF-8)
- ✅ DuckDB 原生存储格式
- ❌ JSON(仍使用同步 I/O)
JSON 还没支持异步 I/O,这是个遗憾。如果你的数据管道大量使用 JSON,可能需要等后续版本。
VARIANT 类型:半结构化数据的杀手锏
这是 Snowflake 早就有的特性,DuckDB 终于跟上了。
VARIANT 类型用于存储半结构化、无 schema 的数据(比如 JSON),但保持列式执行的性能。核心机制是"shredding"(分解)——自动检测常见结构,将 JSON 字段转为真实类型列存储。
性能对比(500 万事件测试)
| 指标 | JSON 字符串 | VARIANT(shredded) | 提升 |
|---|---|---|---|
| 磁盘占用 | 224 MB | 85 MB | 62% 压缩 |
| 查询性能 | 基准 | 60ms | 78x 更快 |
| 与类型化列对比 | - | 60ms | 仅慢 20% |
78 倍的性能提升,这个数字相当惊人。而且 shredded VARIANT 与真实的类型化列相比,只慢 20%,几乎可以忽略。
使用示例
| |
每行可以存储不同形状的 JSON,自动分解为类型化列。支持 Parquet 读写,提供 variant_* 函数族。
对于日志分析、事件追踪这类场景,VARIANT 类型会大幅提升开发效率和查询性能。
触发器:自动响应表变化
DuckDB 2.0 终于支持触发器了。
支持的类型很全面:
BEFORE/AFTERFOR EACH ROW/FOR EACH STATEMENTREFERENCING OLD TABLE/NEW TABLE(转换表)- 每个事件多个触发器
RETURNING子句DROP TRIGGER
经典用例:审计表
| |
性能对比(50 万行插入测试)
| 触发器类型 | 相对开销 |
|---|---|
| 无触发器 | 基准 |
| FOR EACH STATEMENT | 1x |
| FOR EACH ROW | 3x |
最佳实践很明确:优先使用 FOR EACH STATEMENT(批量处理),避免 FOR EACH ROW(逐行处理)。3 倍的性能差距,在大数据量场景下会很明显。
其他亮点
Agent 模式
CLI 内置 AI 代理模式,可以用自然语言描述需求,自动生成 SQL。需要配置 LLM API(如 OpenAI)。
这个功能还在早期阶段,但对于快速原型开发很有帮助。
新 SQL 解析器
扩展可以添加新的 SQL 语句、子句、关键字,不再局限于核心 SQL 语法。这为第三方扩展提供了更强大的能力,比如定义专属的 COPY TO 格式或特定领域的查询语言。
递归 CTE 性能提升
重写递归查询引擎,深层递归查询(如 20,000 次提交的祖先遍历)从 16 秒降到 0.4 秒,40 倍提升。
LTS 长期支持
DuckDB 2.0.0 是 LTS 版本,社区支持期限到 2027 年 10 月 22 日(1 年)。适合生产环境部署。
迁移指南:破坏性变更
升级 2.0 之前,这些破坏性变更必须了解。
1. 新存储格式(最重要)
DuckDB 2.0 使用新的默认存储格式。旧版本(< 2.0)无法读取 2.0 创建的数据库文件,但 2.0 可以读取旧格式(自动迁移)。
如果有多个 DuckDB 进程访问同一数据库,必须全部升级到 2.0。
2. Lambda 语法变更
这个改动会影响所有使用 lambda 表达式的查询。
3. 除零错误
如果你的查询依赖除零返回 NULL 的行为,需要加上 NULLIF 处理。
4. ICU 扩展移除
时区、日历、排序规则现在由 icu 扩展处理,核心构建不再包含。自定义构建需要显式加载 icu 扩展。
5. 标识符大小写
identifier_case 设置行为变更,建议显式使用引号处理大小写敏感标识符。
总结
DuckDB 2.0 不是一次简单的版本升级,而是一次架构层面的蜕变。
Quack 协议让 DuckDB 从嵌入式工具变成了客户端-服务器架构,异步 I/O 在不改代码的情况下把性能提升了 3 倍,VARIANT 类型让半结构化数据的查询性能暴涨 78 倍,触发器补全了数据管道的最后一块拼图。
作为 LTS 版本,2.0 适合生产环境部署。但升级前一定要注意新存储格式和 Lambda 语法变更这些破坏性改动。
DuckDB 正在从"SQLite 的分析替代品"进化成"轻量级的分析型数据仓库"。这个定位变化,会让它在数据湖、实时分析、嵌入式 BI 这些场景下越来越有竞争力。
