首页 › programming › 解剖DuckDB:秒查十亿行的引擎秘密

解剖DuckDB:为什么你的笔记本能秒查十亿行?

导语

如果你做过数据分析,一定经历过这种崩溃:一个 500MB 的 CSV 喂进 pandas,先撑爆内存,再被 GIL(全局解释器锁)锁死,一个本该 10 秒的聚合跑了 40 分钟。你也大概率听过一个像段子的口号——"DuckDB is eating the data world(DuckDB 正在吞掉整个数据世界)",然后默默 pip install duckdb,发现真的能在笔记本上秒级聚合上亿行。

但"为什么它能这么快"这个问题,绝大多数人答不上来。这正是 YouTube 上这期 "Dissecting the Duck: Master Database Internals with DuckDB"(解剖那只鸭子) 价值所在。它不教你写 SQL,而是把你拽进数据库引擎的"引擎舱",拆解一个现代 OLAP(联机分析处理)数据库到底由哪些齿轮咬合而成。它的知识底座,是德国图宾根大学 Torsten Grust 教授在 2026 年推出的 15 周课程 DiDi(Design and Implementation of DuckDB Internals)——这被官方生态通讯 DuckDB Monthly #41(2026 年 5 月)选为当月"深度之选"。

这篇文章我就把这个视频(及其背后的 DiDi 课程)彻底拆给你看:从"查询性能谱系"到"向量化执行",从 ART 索引到查询改写优化器,看一只"鸭子"如何在你笔记本上跑出 ClickHouse 级别的分析性能。


视频背景卡片

项目 内容
视频标题 Dissecting the Duck: Master Database Internals with DuckDB
频道 Github Signals
视频链接 youtube.com/watch?v=3g1009aqWtQ(已通过 oembed 双重验证真实存在)
内容底座 图宾根大学 DiDi 课程(Prof. Torsten Grust,2026 年 3 月定稿,15 周)
GitHub 仓库 DBatUTuebingen/DiDi(8 章 PPT + 约 50 个 SQL/C/Python/awk 辅助文件)
核心主题 DuckDB 内部原理:存储、向量化执行、流水线、索引、查询优化
配套数据 TPC-H 基准测试,scale factor 1 / 10 / 100
同期热度 DuckDB Monthly #41(2026-05)官方推荐;DuckDB 本体 v1.5.3(2026-05-20 发布)、GitHub 38,758 stars

说明:因 YouTube 对服务器 IP 封锁字幕接口,本期字幕未能直接抓取,下文内容基于 DiDi 课程官方仓库、DuckDB 文档与多篇内部原理深度文章交叉还原,并明确标注"课程内容"与"我的延伸分析"。


核心内容拆解

一、DuckDB 到底是个什么东西:被低估的"分析版 SQLite"

要理解这期视频,先得理解主角。DuckDB 是一个进程内(in-process)的分析型 SQL 数据库——注意这两个关键词。

"进程内"意味着它不像 PostgreSQL、MySQL 那样需要你启动一个独立的服务进程、走网络协议连接;它是一个库,直接嵌进你的 Python/Node/R 程序里,跟 SQLite 一模一样的部署哲学。但 SQLite 是为 OLTP(事务型、行存、点查快)设计的,DuckDB 则是为 OLAP(分析型、列存、扫描聚合快) 设计的。所以社区给它起了个外号:"the SQLite of analytics"(分析界的 SQLite)。

它诞生于荷兰阿姆斯特丹的 CWI(国家数学与计算机科学研究所)——没错,就是孕育了 MonetDB 的那个实验室。作者 Hannes Mühleisen 和 Mark Raasveldt 在 2019 年的 CIDR 会议上发表了奠基论文 "DuckDB: an embeddable SQL OLAP database system",核心论点是:过去 20 年数据库界把全部注意力都放在"分布式/云端大仓库"上,却没人认真做一个"在单机上、和 SQLite 一样好用的分析数据库"。DuckDB 填的就是这个空。

我的延伸分析:这个定位在 2026 年看尤其精准。AI 时代,数据工作者越来越希望"在我本机就把活干完",而不是把数据搬上云。DuckDB + Parquet 几乎成了新时代数据科学家的默认工作流,直接威胁 pandas 的地盘。视频反复强调的"commodity laptop 上 crunch billions of rows(普通笔记本处理数十亿行)",正是这套叙事的核心钩子。

二、查询性能谱系(DiDi 第 2 章):用 6 种语言做同一件事,看清"慢"的本质

这是整个课程最妙的开场,也是视频最容易"勾住人"的部分。Grust 教授给学生的第一道题极其朴素:对一张 lineitem(订单明细)表的 quantity(数量)列求和。然后他用 6 种方式实现同一个求和:

  1. awk(脚本逐行处理)—— 慢得离谱
  2. Python(纯解释执行)—— 仍慢
  3. C(逐行 fscanf 读、累加)—— 快了一些
  4. C + mmap(把文件映射进内存,避免 read 系统调用)—— 显著变快
  5. C + mmap + 多线程(切开文件并行求和)—— 再快一个量级
  6. DuckDB 一条 SQL(SELECT SUM(quantity) FROM lineitem)—— 几乎总是最快

课程核心洞察:这条"性能谱系"揭示了 OLAP 速度的三层来源——减少解释开销(解释执行 vs 编译执行)、减少内存拷贝(mmap 直接映射)、榨干硬件并行(多核 + SIMD)。DuckDB 之所以能在第 6 步"通杀",是因为它把前三层的优化全部内化成了引擎默认行为。

Grust 在课程里特别说明,这一章改编自慕尼黑工业大学 Thomas Neumann(Hyper/ Umbra 数据库之父)的《Foundations in Data Engineering》讲义。换句话说,这不是 DuckDB 的独家秘方,而是现代分析数据库的通用底层逻辑——这一章本身价值就值回票价。

三、向量化执行(DiDi 第 7 章):为什么是 2048,而不是 2 或 200 万?

这是 DuckDB(乃至整个 MonetDB/X100 血脉)真正的性能护城河。传统的查询执行采用 1970 年代 Goetz Graefe 提出的 Volcano 模型:一次处理一行,每个算子(过滤、投影、聚合)之间通过 next() 一行一行拉数据。问题是每一行都要付出一次函数调用 + 一次分支判断的解释开销,现代 CPU 的流水线和缓存根本喂不饱。

DuckDB 采用的是 Vectorized Execution(向量化执行),源自 Boncz 等人 2005 年的经典论文 "MonetDB/X100: Hyper-Pipelining Query Execution"。核心做法:一次处理一个"向量"(chunk),而不是一行。 DuckDB 默认的 STANDARD_VECTOR_SIZE = 2048 行。

我的延伸分析(这部分是视频之外的硬核补充):为什么偏偏是 2048?这是一个精心计算的工程折中。向量太小(如 2、4),解释开销摊不薄,等于退化回 Volcano;向量太大(如几百万行),又会让中间结果撑爆 CPU 的 L1/L2 缓存,反而触发 cache miss 风暴。2048 行 × 8 字节(一个 int64 列)≈ 16KB,刚好能舒舒服服地躺进 L1 缓存(通常 32–48KB)。配合按列存储,同类型数据连续排布,CPU 的硬件预取器和 SIMD 指令(一条指令同时处理多个数据)就能火力全开。

DiDi 第 7 章的辅助文件堪称"CPU 微优化圣经",里面有 027-duffs-device.c(Duff's Device,一种古老的循环展开技巧)、028-prefetch.c(软件预取)、029-branch-prediction.c(分支预测)、026-unroll.c(循环展开)。Grust 用这些 C 小程序让学生亲手测量:循环展开、消除分支、预取数据,到底各能换来多少毫秒。这种"用 C 代码直接和 CPU 硬件对话"的教学方式,在中文技术社区里几乎见不到。

四、ART 索引与数据跳过(DiDi 第 5 章):分析库也需要索引吗?

一个常见误解是"列式分析数据库不需要索引"。DuckDB 的答案是:需要,但用的是另一种索引,而且和行存数据库的 B+ 树完全不同。

DiDi 第 5 章 "The ART of Indexing" 讲两样东西:

1. Zone Maps(区图)与 Row Group Pruner(行组裁剪)。DuckDB 的列式存储把数据切成一个个 row group(行组,默认约 122,880 行),每个行组的每一列都记录了 min/max。查询时如果某个过滤条件(比如 WHERE date > '2026-01-01')发现某行组的 max 都不满足,整组直接跳过,根本不读磁盘。这就是"数据跳过",是 Parquet 列存分析库的看家本领。

2. ART(Adaptive Radix Tree,自适应基数树)。这是 DuckDB 用来保证主键唯一性、加速点查询的索引。它源自 Leis 等人 2013 年 ICDE 论文 "The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases"。和 B+ 树比,ART 针对内存数据库做了极致优化:路径更短、节点大小自适应。它的精髓在于——根据子节点数量动态切换节点类型:子节点 ≤4 用 Node4,≤16 用 Node16,≤48 用 Node48,否则用 Node256。这样在小分支时省内存、在大分支时保性能。

课程细节:DiDi 配套的 017-encode-float.c、018-simd-compare.c 揭示了一个反直觉的点——为了让 ART 能用统一的字节比较处理整数、浮点、字符串,DuckDB 会把各种类型编码成可比较的字节串(比如把浮点数的符号位翻转,让 IEEE754 浮点的字节序直接对应数值大小)。这种"键规范化(key normalization)"在 DiDi 第 4 章排序里也会再次出现。

五、执行计划与流水线(DiDi 第 6 章):让数据像水流一样不停顿

如果说向量化解决"单算子内怎么算得快",那 Pipeline(流水线) 解决的是"多个算子之间怎么串起来不浪费"。

传统 Volcano 模型是 pull(拉)模式:上游算子向下游要一行,下游再向下下游要一行,层层嵌套函数调用。DuckDB 借鉴了 morsel-driven parallelism(morsel 驱动并行) 思想:把数据切成一个个 morsel(小块,正好就是一个向量),一条 pipeline(流水线) 就是"一串不需要物化中间结果的算子链"——比如 scan → filter → project → aggregate,数据块从最前端一路流到最末端,中间结果不落盘、不进内存,像工厂流水线一样连续流转。

DiDi 第 6 章的 021-pipelines.sql、022-parallelism.sql 让学生看到:DuckDB 的并行度是按 morsel 分配的——每个工作线程抢一个 morsel 处理,天然负载均衡,不需要复杂的中央调度。这比传统"按表分片"的并行方式灵活得多。

六、查询改写与优化器(DiDi 第 8 章):最"魔幻"的一章

第 8 章是整个课程的智力巅峰,辅助文件多达 20+ 个。Grust 把 DuckDB 优化器拆成了一长串改写规则(rewriting rules),每条都对应一个文件:

我的延伸分析:第 8 章最该被中文开发者记住的概念是 Late Materialization(迟物化),这是列存分析库区别于行存库的决定性设计之一。在行存里,读一行就读出所有列;在列存 + 迟物化里,你 SELECT name FROM users WHERE age > 30,引擎先只扫 age 列定位到满足条件的行号,最后才去读 name 列。这能把分析查询的 I/O 量降一个数量级。理解了它,你才算真正理解了"为什么列式分析库快"。

七、内存管理与大表排序(DiDi 第 3、4 章):撑不住内存怎么办?

这两章解决"数据大于内存"的真实场景。

第 3 章 分组聚合:当你 GROUP BY 的分组数量巨大、哈希表塞不进内存时,DuckDB 会溢写(spilling)到磁盘,再分批合并。DiDi 用 009-buffering.sql、010-streaming.sql、011-spilling.sql、012-adaptive.sql 对比了缓冲式、流式、溢写式、自适应式四种聚合策略。

第 4 章 大表排序:核心是外部归并排序(external merge sort)——把数据分块排序、各自落盘,再合并。配合前面提到的键规范化,让任意类型都能用同一套字节比较逻辑排序,从而吃满 SIMD。


知识结构图

graph TD
    DUCK["🦆 DuckDB<br/>嵌入式 OLAP 分析数据库<br/>SQLite for Analytics"]

    DUCK --> STO["列式存储<br/>Parquet 原生"]
    DUCK --> VEC["向量化执行<br/>2048 行/向量"]
    DUCK --> PAR["流水线并行<br/>Morsel-driven"]
    DUCK --> IDX["索引体系"]

    STO --> ZM["Zone Maps<br/>min/max 数据跳过"]
    VEC --> SIMD["L1 缓存 + SIMD<br/>+ 分支预测优化"]
    PAR --> PIPE["Pipeline 不物化中间结果<br/>按 morsel 分配线程"]
    IDX --> ART["ART 自适应基数树<br/>Node4/16/48/256"]

    DIDI["📚 DiDi 课程 8 章<br/>图宾根大学 Torsten Grust"]
    DIDI --> C2["2 查询性能谱系<br/>awk→Python→C→mmap→多线程→SQL"]
    DIDI --> C3["3 内存管理 + 分组聚合<br/>缓冲/流式/溢写/自适应"]
    DIDI --> C4["4 大表排序<br/>外部归并 + 键规范化"]
    DIDI --> C5["5 ART 索引<br/>+ 数据跳过 + SIMD 比较"]
    DIDI --> C6["6 执行计划 + 流水线"]
    DIDI --> C7["7 向量化微优化<br/>Duff's Device/预取/展开"]
    DIDI --> C8["8 查询改写与优化<br/>行组裁剪/迟物化/谓词下推/Join 顺序"]

    C5 -.-> ART
    C6 -.-> PIPE
    C7 -.-> SIMD
    C2 -.-> VEC
    C8 -.-> ZM

    classDef store fill:#e8f4f8,stroke:#2b6cb0
    classDef course fill:#f0fff4,stroke:#276749
    class STO,ZM,VEC,SIMD,PAR,PIPE,IDX,ART store
    class DIDI,C2,C3,C4,C5,C6,C7,C8 course

实战启示:看完这期,你能用它做什么?

1. 数据工作者:把 pandas 的"重量级活"交给 DuckDB。 凡是要 groupby + merge 几百万到几亿行的场景,别再硬扛 pandas 了。import duckdb; duckdb.query("SELECT ... FROM 'data.parquet'")——它能直接读 Parquet/CSV,秒级返回,内存占用还更小。理解了第 8 章的迟物化和行组裁剪,你就知道为什么只查两列比查二十列快得多,从而写出真正高效的查询。

2. 后端/平台工程师:重新评估"要不要上云仓库"。 DiDi 反复强调"commodity laptop 处理数十亿行",背后的工程哲学是:很多所谓的"大数据",其实单机就能搞定。在 2026 年,DuckDB + 对象存储 + Parquet 的组合,正在替代一批中等规模、本该上 Snowflake/BigQuery 的场景。你可以用 MotherDuck(DuckDB 的云端商业化版本)做"本地 + 云"混合,热数据本地查、冷数据下沉云。

3. 想深入系统软件的开发者:这是最好的"数据库内核"入门材料。 DiDi 课程最大的价值是把晦涩的数据库内核论文,翻译成了可运行的 SQL/C 代码。你不需要啃 800 页的教材,跟着 50 个辅助文件,就能亲手测量"循环展开能快多少""分支预测失败多耗多少周期"。如果你想进数据库内核方向(PostgreSQL、ClickHouse、TiDB),或想写高性能系统软件,这套材料是练基本功的黄金路径。第 7 章的微优化(预取、展开、消除分支)甚至对所有写 C/C++/Rust 高性能代码的人都有用。

4. 技术面试/体系认知:建立"分析库 vs 事务库"的完整心智模型。 当你能清晰地讲出 Volcano 模型 vs 向量化、行存 vs 列存、B+ 树 vs ART、build side vs probe side,你在系统设计面试里关于"数据库选型"的回答,就能碾压 90% 只会说"用 MySQL"的候选人。


延伸学习路径

  1. DiDi 课程官方仓库(强烈推荐) — github.com/DBatUTuebingen/DiDi,8 章 PDF + 50 个可运行辅助文件,本文知识底座。
  2. DuckDB 官方文档 "Why DuckDB" — duckdb.org/why_duckdb,作者亲自讲设计哲学与组件来源。
  3. 奠基论文:DuckDB (CIDR 2019) — Raasveldt & Mühleisen,"DuckDB: an embeddable SQL OLAP database system",理解它的定位初心。
  4. 向量化源头论文:MonetDB/X100 — Boncz et al., "Hyper-Pipelining Query Execution",第 7 章的理论祖宗。
  5. ART 索引论文:Leis et al. (ICDE 2013) — "The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases",第 5 章的核心,PDF 在 db.in.tum.de/~leis/papers/ART.pdf。
  6. 同伴课程 TaDa — github.com/DBatUTuebingen/TaDa,Grust 教授的 SQL 入门伴侣课,同样基于 DuckDB。

一句话总结

这期视频(及其背后的 DiDi 课程)最大的价值,是把"为什么 DuckDB 能在笔记本上秒查十亿行"这个黑盒,拆成了一整套可运行、可测量、可迁移的现代数据库内核工程知识——从向量化的 2048 行折中,到 ART 索引的 Node4/16/48/256,再到优化器的迟物化与连接重排,让你第一次真正"看懂"一个分析数据库。


参考来源

  1. Dissecting the Duck: Master Database Internals with DuckDB(视频) — 本文分析的核心视频(频道:Github Signals,oembed 验证)
  2. DiDi 课程仓库 — Dissecting the Duck's Innards — 8 章课程 PPT 与 50 个辅助文件,本文知识底座
  3. Design and Implementation of DuckDB Internals(DuckDB 官方课程页) — Torsten Grust, University of Tübingen, 2026-03-19
  4. DuckDB Monthly #41(2026 年 5 月生态通讯) — 官方将 DiDi 选为当月深度之选
  5. How DuckDB Works Internally: Vectorized Execution, Columnar Storage... — 向量化执行与列存原理延伸
  6. DuckDB Architecture — Why It's So Fast(zatoima 译) — 2048 行向量化与列式存储解释
  7. DuckDB GitHub 仓库(38,758 stars,v1.5.3,2026-05-20) — 实时数据,C++ 实现
  8. The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases (Leis et al., ICDE 2013) — ART 索引原始论文

本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。

[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。

51学通信知识星球海报-扫码加入