PostgreSQL码农集散地

DuckDB 好久没声音了

好久没关注 DuckDB 了, 17号连发了2个版吧, 其中 DuckDB 1.5.4 (Variegata) 发布了, 修了3个大坑, 还有 V2.0 马上要来了!

一、3 个大 bug

先把三个最该拎出来讲的修复摆出来。

Image

#23031 — VARIANT cast 在 filter 下读错行。

VARIANT 是 DuckDB 1.5.0 (2026-03-09 发布) 引入的新类型,本质是"带类型 shredding 的 JSON"。这次的修复是说:WHERE 过滤下,VARIANT 的 cast 可能把行映射到错的结果集。

这种 bug 在 OLAP 里最阴。聚合数字看起来合理,JOIN 看起来对得上,其实行号已经偏了 — 你不会发现,因为没人会去逐行核对几亿行的 cast 输出。

如果你们链路里有"JSON 落 VARIANT → 大宽表聚合",1.5.0 ~ 1.5.3 之间的所有相关 SQL 都要重新对一次账。

#23014 — MERGE INTO 绑定表搞反。

MERGE INTO 是 upsert 的标准 SQL 形式。PR 描述说,修完之后两个分支各自绑到正确的表(WHEN NOT MATCHED 用 target,WHEN NOT MATCHED BY TARGET 用 source);修之前两个分支绑反了。

ETL 链路里这就是脏数据源头。该插的没插,该更的没更,下游对账会发现"为什么两边对不上"。这种 bug 一般要等到月底对账才暴露,回头查已经晚了。

#23137 — ignore_errors 默默接受无效 JSON。

我每次看到这类修复都后脊一凉:COPY ... (ignore_errors) 之前会静默接受无效 JSON。

你以为是"失败的就跳过、成功的就入库"。其实有一类非法 JSON 被悄悄吃掉了。数据进了表,你以为干净,里面夹着坏数据,等真要用的时候就出问题。

这三个雷的共同信号

VARIANT 才发布 3 个月,JSON ingestion 是 DuckDB 的招牌, MERGE INTO 是 ETL 的标准件 — 三条都是用户最容易踩到的主路径。

DuckDB 团队愿意把这三条高调列在 Correctness 节而不是塞进 generic bugfix,说明他们自己也承认这都不是"小修小补"。

二、同日双发:1.4.5 LTS 和 1.5.4 一起出

这次 DuckDB 同一天发两个版本:

  • v1.4.5 LTS (Andium):稳定版,给"我要绑一年不动"的人
  • v1.5.4 (Variegata):主线,给"我要新特性"的人

这种 LTS + 主线 同日发的姿态,在我印象里是 DuckDB 第一次明确摆出来。

它暗示几件事:

  1. 1.4.x 已经被内部视为"够稳,可以扛一年"。LTS 不是营销标签,是项目对自己代码的承诺。
  2. 1.5.x 主线继续推新特性,出问题不用降版本,等下个 patch 就行。
  3. 生态开始需要做"哪个版本适合我"的选型 — 用户、DBA、运维都得有判断,文档、客户端、benchmark 都要分两条线维护。

类比一下:PostgreSQL 走"主线 + LTS"是 9.x 之后的事;ClickHouse 走 LTS 是更晚的事。DuckDB 在 1.x 阶段就摆出"双轨",节奏比前辈们提前了一截。

Image

看时间线能发现:

  • 1.4 LTS 线 9 个月 5 个版本,节奏稳,意图明显是"长期可依赖"。
  • 1.5 主线 3 个月 5 个版本(1.5.0 ~ 1.5.4),近三个 patch(1.5.2/3/4)都是月更 — 快速迭代,但不放飞。
  • 两条线在 6/17 同日发,是项目主动设计的"对外表态"。

7 周 → 30 天一版的节奏意味着:你今天写的一段查询如果撞上当前版的 bug,等不到 v2.0 就能修。

三、v2.0

发布说明的结尾一行:

Stay tuned for future DuckDB releases, including v2.0.0 in the fall!

这一行才是本篇真正的头条。

DuckDB 在 1.x 阶段一直很保守 — 1.0 (2024-06,代号 Snow Duck) → 1.4 → 1.5,主版本号没跳过。从 1.5 跳到 2.0 通常意味着:

  • 有 breaking change 要交代
  • 文件格式 / 序列化格式可能要动
  • 一些 1.x 时代的"兼容性兜底"要卸下

具体变什么,现在没人知道。要等 DuckCon #7(2026-06-24,Amsterdam)的 keynote。

这也是为什么这次"1.4.5 LTS + 1.5.4 同日发"特别值得琢磨:项目在 v2.0 跳代之前,把 LTS 锁住、把主线收尾,姿态上是在给 1.x 画一个干净的句号。