PostgreSQL码农集散地

DuckDB 的发家史 | 分析的回流

2026 年 10 月 21 日,DuckDB 团队发布了 2.0.0 LTS 版,代号"Cinnamon Teal"(肉桂蓝翅鸭)——一种分布于美洲西部的红褐色鸭子。这是他们迄今为止最大的功能发布:距离上一个次要版本 1.5 不到八个月,却塞进了近两万个 commit。发布清单里有服务器模式、异步 I/O、半结构化数据类型 VARIANT、触发器,以及一个成为默认选项的、可被扩展实时改写的 SQL 解析器。

耐人寻味的是舆论场的反应。人们讨论最多的不是某个新功能,而是一个反复出现的疑问:一个没有服务器的"数据库",为什么越来越像一台服务器?

这个问题问反了。真正发生的事情是另一回事:过去三十年,分析型数据库把"服务器"越做越重——从一体机到集群,从集群到云数仓,从云数仓到湖仓一体;而 DuckDB 代表的潮流,是把这个沉重的东西重新装回进程里。数据在哪儿,计算就在哪儿。本文要讲的,就是这场回流的来龙去脉,以及为什么回流的渡轮上挤满了人。

一、被硬件甩掉的三十年

要理解 DuckDB 为什么长成现在这样,得先回到一个技术史的基本事实:关系数据库的骨架,定型于硬件与今天截然不同的年代。

1970 年 Codd 提出关系模型,1974 年 System R 跑出第一条 SQL。那个年代磁盘慢、内存小、CPU 更慢,数据库设计的全部智慧都花在一件事上:如何尽量减少磁盘读写。行式存储、B 树索引、预写日志,这套组合拳统治了此后半个世纪,而且统治得非常好——好到大多数人忘了它最初是为了解决什么问题。

到了 1990 年代,情况变了。内存容量大约每两年翻一番,CPU 缓存层级越来越复杂,而磁盘虽然也变快,却追不上内存。荷兰国家数学与计算机研究中心(CWI)的研究者们盯上了这个错配:传统数据库把数据整行读进来,只为了算一列的总和;解释执行的算子每个元组一次函数调用,CPU 大量时间花在分支预测和缓存未命中上。他们的实验项目 MonetDB 选择反其道而行:按列存储,把一列数据连续铺在内存里。

1999 年,CWI 团队发表了那篇著名的论文《为新的瓶颈而优化的数据库架构:内存访问》,并在此后拿下 VLDB 十年最佳论文奖。但真正改变行业的是 2005 年的续作:MonetDB/X100 的"超流水线查询执行"。它提出在"一次一个元组"(火山模型)和"一次一整列"(MonetDB 原始模型)之间取一个折中——一次处理一批数据,一批约一千个值,刚好放进 CPU 缓存。解释开销下降两个数量级,循环体内的代码可以被编译器自动向量化,缓存局部性达到最优。

这套思想后来有了正式名字:向量化执行(vectorized execution)。


Image
分析型数据库四十六年:从行式事务到嵌入式回流

2024 年 1 月,CIDR 大会把首届时间考验奖颁给了这篇 2005 年的论文。颁奖词背后是一个更值得注意的事实:向量化执行早已不是某个系统的专利——Snowflake、Databricks、Google BigQuery、Microsoft SQL Server,今天叫得出名字的分析引擎,内核都跑着这套模型。X100 的作者之一 Marcin Żukowski,后来成了云数仓 Snowflake 的联合创始人。学术界的一篇论文,用二十年时间改写了整个行业的执行层。

同一时期,CWI 的 VectorWise 商业化项目在 TPC-H 基准上连续刷新非集群环境的世界纪录;而远在美国的创业者们忙着把"存算分离"写进云数仓的蓝图。2012 年前后,Snowflake 与 Amazon Redshift 相继问世,分析系统的标准形态从"买机器"变成"租算力"。数据开始离开它诞生的地方,向云端的湖里集中。

二、数据越走越远,直到走不动

2013 年,Twitter 与 Cloudera 联合推出 Parquet。这个决定在当时看起来只是又一种列存文件格式,事后看却是数据地理大迁移的起点:数据第一次有了不依赖任何数据库引擎的、自描述的、可被任意工具读取的躯体。此后 Netflix 的 Iceberg、Databricks 的 Delta Lake、Uber 的 Hudi 相继定义了"湖仓一体"——数据以开放格式躺在对象存储里,多个引擎可以同时读它。

2018 到 2022 年,"现代数据栈"(Modern Data Stack)概念爆发:Fivetran 负责搬数、dbt 负责建模、Snowflake 负责存算、Looker 负责看板,每一层都有明星公司,每一层都单独计费。数据团队突然发现,一条数据从业务系统到分析师眼前,要穿过七八个供应商,每穿过一层就付一次钱、等一次批处理窗口。

然后账单来了。按行计费的 ingestion、按秒计费的算力、按席位计费的 BI,七项独立增长的费用加起来,是许多团队没有预料到的运营成本。更重要的是延迟:批处理_stack 意味着小时级的新鲜度,而越来越多的场景——风控、定价、运营监控——需要的是分钟级甚至秒级。

2024 年之后的行业叙事因此明显转向。湖仓一体从"愿景"变成默认架构,Iceberg 成为跨引擎互操作的事实标准,各家云数仓纷纷宣布支持开放格式;现代数据栈从"品牌"退化为"架构本身",工具数量在收缩,平台在变宽。一篇 2026 年的行业综述说得直白:问题不再是"选哪个数仓",而是"我们现在就需要一个数仓吗"。


Image
分析引擎的部署光谱:从进程内到全球集群

这句话背后是一个被长期忽视的常识。我们看看数据实际上住在哪里:

  • 一份 CSV 躺在某台笔记本的下载目录里,730 MB,600 万行业务流水;
  • 一个 Parquet 数据集躺在对象存储里,是某个系统的每日导出;
  • 一个 DuckDB 单文件数据库,280 MB,装着完整的 TPC-H SF1 数据集。

这些数据加在一起,可能都装不满一台云数仓的最小计费单元。而分析它们需要的全部算力,一台笔记本就有。把数据搬到数仓再搬回来,经济上荒谬,延迟上难以忍受,工程上平白多出一整条要维护的链路。

第一性原理在这里只问一个问题:为什么计算不能去数据所在的地方?

三、回流:把数仓装进一个库

DuckDB 就是对这个问题的一个完整回答。它的定位可以用一句话概括:把集群级数仓的核心引擎,做成一个进程内的库——像 SQLite 一样链接进你的程序,但跑的是列存、向量化、基于代价优化的分析负载。

这不是营销话术,是可验证的工程事实。在作者的本机(Apple Silicon,8 核,16 GB 内存)上,用官方 TPC-H 扩展生成 1 GB 数据集(lineitem 表 600 万行),22 条标准查询在单个命令行进程里全部跑完,总耗时 381 毫秒。其中没有网络往返、没有序列化、没有集群协调,启动开销约等于零。作为对照,同一批查询在 100 MB 数据集(lineitem 60 万行)上总耗时 107 毫秒。

这些数字当然不能直接和云数仓比——后者要的是多租户、高并发、PB 级规模,那是对另一个问题的回答。但请注意这个事实的份量:TPC-H 是 1990 年代为衡量"企业级数仓"而设计的基准,如今它跑在了一个库文件里。 当年需要一柜子机器回答的问题,今天一个函数调用就能回答。

为了说清楚 DuckDB 在版图中的位置,值得把"嵌入式"这件事拆开看。嵌入式数据库不是新概念,SQLite 是它的王者——但 SQLite 为 OLTP 而生:B 树、行存、为单表点查和事务吞吐优化。你当然可以用 SQLite 做分析,就像你可以骑自行车送外卖:能到,但别催。DuckDB 补上的是另一块:嵌入式 OLAP。同样是零服务器、单文件、随应用分发,内核却换成了分析引擎的全套——列存与压缩、向量化执行、多态并行、基于代价的优化器。嵌入式不等于低性能,只是过去没有人认真做"嵌入式且高性能"这件事。

和同为列存 OLAP 的 ClickHouse 相比,差异同样不在引擎质量,而在部署形态:ClickHouse 是一台服务器,为多租户、实时摄入、集群扩展而生;DuckDB 是一个库,为单写者、零运维、随应用分发而生。2026 年的多篇行业对比给出同一个结论:在单机本地数据上 DuckDB 常常不慢于 ClickHouse(省掉了网络与序列化开销),在规模与并发上则各守一边。二者是互补,不是替代。

嵌入式 OLAP 这条赛道上,DuckDB 并不是第一个候选者,但它确实赢得了开发者心智。拆开看,赢面来自四个相互放大的因素。

学术血统的完整转化。 DuckDB 不是工程经验的堆叠,而是一篇篇论文的工程落地。执行引擎对应 MonetDB/X100;连接顺序优化对应 Moerkotte 与 Neumann 的动态规划系列工作;并行执行对应" morsel-driven "(薄片驱动)并行模型;MVCC 对应 Neumann 等人的主内存多版本并发控制论文;二级索引对应自适应基数树(ART);窗口函数对应段树聚合;不等式连接对应 IEJoin;浮点压缩对应 Chimp、Patas 与 CWI 自己提出的 ALP。这些组件的论文都能在 DuckDB 官方"站在巨人肩上"页面上找到一一对应。一个团队把三十年学术成果同时工程化到生产质量,这个时间窗口本身就是壁垒——截至 2026 年,这个团队的相关论文从 SIGMOD 2019 演示一路发到 CIDR 2025。

治理结构的刻意选择。 DuckDB 采用 MIT 协议,由独立的 DuckDB 基金会持有知识产权;提供商业支持的 DuckLabs 明确表示不拿风险投资——理由是他们不愿让项目方向被变现压力绑架。与之对照,云上 DuckDB 服务 MotherDuck 拿了 1 亿美元融资,走的是"本地 DuckDB + 云端混合执行"的路线。基金会保核心、商业化公司做云、社区做扩展,这个结构让"开源核心"四个字有了制度保障而非口头承诺。

测试文化的规模。 作者在研究代码库时数了数:仅 SQL 逻辑测试文件就有 6,777 个,测试套件 adapted 自 SQLite、PostgreSQL 和 MonetDB 的测试集,外加随机查询模糊测试(SQLancer、SQLsmith)。官方页面坦言目标是"稳定成熟的数据库系统",而稳定是测出来的,不是声明出来的。

扩展机制卡住了生态位。 DuckDB 没有试图自己实现所有数据源的连接器,而是把"加功能"做成一等公民:核心扩展随发行版分发,社区扩展可运行时安装,2.0 起扩展 ABI 稳定。截至本文写作,已知扩展 31 个,覆盖湖仓格式(Iceberg、Delta、DuckLake、Unity Catalog)、云存储(S3、Azure、GCS)、外部数据库(PostgreSQL、MySQL、SQLite、ODBC、Snowflake、BigQuery)、文件格式(Excel、Avro、Lance、Vortex)、以及全文检索、向量检索、空间数据。一个引擎的竞争力,越来越取决于它接入世界的能力,而不是它自己能做多少事。

最后是时机。2019 年 DuckDB 0.1.0 发布时,pandas 生态正苦于没有顺手的本地分析引擎,Parquet 正要成为数据交换的通用语。DuckDB 几乎是被数据科学工作流"捡"起来的——先是在 Python 笔记本里,然后进入 ETL 管道,最后进入产品。2020 年那篇 CIDR 论文的标题预示了这一切:《面向数据科学的数据管理:走向嵌入式分析》。

五、这一轮回流对国产意味着什么

作为长期关注国产数据库与 AI 工程实践的观察者,我认为 DuckDB 现象有三层本土意义。

第一,它重新标定了"够用"的基准线。 过去国内大量数据团队的默认动作是"建个数仓"——立项、选型、采购、运维,一套流程走下来,实际要分析的数据可能只有几百 GB。DuckDB 证明了这类负载一个库文件加一条 SQL 就能解决。这不是说数仓没有价值,而是说数仓的门槛被显著抬高:上云、上集群之前,先问数据规模、并发模型和团队运维能力是否真的需要。对正在做信创替代的团队,这个问题的答案可能直接改写方案清单。

第二,嵌入式分析是 AI 应用的天然组件。 大模型应用需要可靠的结构化数据访问——RAG 的元数据过滤、Agent 的查询工具、报表的即时生成,背后都是一个"嵌在应用进程里的分析引擎"。DuckDB 2.0 专门为 AI 场景加了 CLI 的 agent 模式:紧凑输出、截断显式标记、错误 JSON 化、可中止失控查询——官方实验显示这能把 Agent 需要消化的输出量减少约 59%。当"消费者"从人变成模型,数据库的人机工程学正在被重新定义,而 DuckDB 是第一个正面回应这件事的主流引擎。

第三,它是学习现代数据库的最佳标本。 对想进入数据库行业的人,DuckDB 有一个难得的属性:它足够小(核心源码约 69 万行,不到主流数仓的零头),可以整册读完;又足够完整,列存、向量化、代价优化、MVCC 一样不缺。读懂一个 DuckDB,等于拿到了读懂所有现代分析引擎的坐标系。

六、本系列怎么读

DuckDB 的故事讲完了背景,接下来要拆细。本系列后续文章的安排如下:

  • 架构总览:一条 SQL 从文本到结果,穿过的每一层,以及各层之间的契约;
  • 解析器:2.0 起成为默认的自研 PEG 解析器,如何被扩展在运行时改写,以及"方言"为何成了可插拔组件;
  • 优化器:逻辑计划被重写的约四十七个步骤,基于代价的部分到底出现在哪;
  • 执行引擎:2048 个值一批的向量化模型,管线并行与任务调度;
  • 存储引擎:行组、压缩家族、内存外执行,以及一次让 5000 万个整数住进 768 KB 的实测;
  • 事务与并发:单写者模型下,MVCC、WAL 与检查点如何配合;
  • 扩展生态:扩展机制的分层设计,DuckLake 与 Quack 协议代表的"Duck Stack"野心;
  • 实证与调优:从零复现本文所有性能数字,以及真正有用的调优旋钮;
  • 边界与展望:DuckDB 不适合什么,2.0 之后往哪走。

每篇文章都遵循同一条纪律:结论可核实,性能数字带条件,代码论断给位置。看不完细节没关系,抓住每篇开头的摘要即可;想深挖的读者,文末的来源清单和源码路径都给你留好了。

回流的逻辑并不新鲜:计算靠近数据,天经地义。新鲜的是,这一轮里"靠近"的极限被推进到了进程内——数据库不再是机房里的庞然大物,而是和你的应用共享同一片内存的伙伴。DuckDB 2.0 一边把服务器模式、异步 I/O 这些"变重"的能力加回来,一边把"变轻"的哲学坚持到底,这个矛盾的统一体,或许就是分析型数据库的下一种形态。

至于那只肉桂色的鸭子,它大概还会继续游下去。