市面上有许多数据库管理系统 (DBMS)。但是,没有放之四海而皆准的数据库系统。所有系统都采取不同的权衡,以更好地适应特定的用例。DuckDB 也不例外。在这里,我们试图解释 DuckDB 的目标,以及我们如何通过技术手段实现这些目标。首先,DuckDB 是一个支持结构化查询语言 (SQL) 的关系型(面向表)DBMS。
DuckDB 的主要特点
简单
SQLite 是全球部署最广泛的 DBMS。其安装简单和嵌入式进程内操作是其成功的关键。DuckDB 采纳了这些简单性和嵌入式操作的理念。
DuckDB 没有外部依赖,无论是编译时还是运行时。对于发布版本,DuckDB 的整个源代码树被编译成两个文件:一个头文件和一个实现文件,即所谓的“大融合文件”(amalgamation)。这极大地简化了部署和集成到其他构建过程中。构建 DuckDB 所需的全部条件是一个可用的 C++11 编译器。
对于 DuckDB,无需安装、更新和维护 DBMS 服务器软件。DuckDB 不作为独立进程运行,而是完全嵌入到宿主进程中。对于 DuckDB 所针对的分析用例,这还带来了高速数据传输的额外优势,无论是向数据库传输还是从数据库传输数据。在某些情况下,DuckDB 可以在不复制的情况下处理外部数据。例如,DuckDB Python 包可以直接在 Pandas 数据上运行查询,而无需导入或复制任何数据。
可移植
由于没有依赖项,DuckDB 具有极高的可移植性。它可以在所有主流操作系统(Linux、macOS、Windows)和 CPU 架构(x86、ARM)上编译。它可以部署在资源受限的小型边缘设备上,也可以部署在拥有 100 多个 CPU 核心的大型多太字节内存服务器上。使用 DuckDB-Wasm,DuckDB 也可以在网络浏览器甚至移动电话上运行。
DuckDB 提供了 Java、C、C++、Go、Node.js 及其他语言的 API。
功能丰富
DuckDB 提供了强大的数据管理功能。它广泛支持 SQL 中的复杂查询,拥有庞大的函数库、窗口函数等。DuckDB 通过我们定制的、为批量处理优化的多版本并发控制 (MVCC) 提供事务保证(ACID 属性)。数据可以存储在持久的单文件数据库中。DuckDB 支持辅助索引,以加快查找单个表条目的查询。
DuckDB 深度集成到 Python 和 R 中,以实现高效的交互式数据分析。
快速
DuckDB 旨在支持分析查询工作负载,也称为在线分析处理 (OLAP)。这些工作负载的特点是查询复杂、运行时间相对较长,并且处理存储数据集的很大一部分,例如对整个表进行聚合或在多个大型表之间进行连接。数据的更改也预计是相当大规模的,例如同时添加多行或更改或添加表的很大一部分。
为了高效支持这种工作负载,关键在于减少每个独立值所消耗的 CPU 周期量。数据管理领域实现这一目标的最新技术是向量化或即时查询执行引擎。DuckDB 使用列式向量化查询执行引擎,其中查询仍被解释,但一次操作处理大量值(一个“向量”)。这大大减少了传统系统(如 PostgreSQL、MySQL 或 SQLite)中存在的开销,这些系统按顺序处理每一行。向量化查询执行在 OLAP 查询中带来了更好的性能。
可扩展
DuckDB 提供了一种灵活的扩展机制,允许定义新的数据类型、函数、文件格式和新的 SQL 语法。实际上,DuckDB 的许多关键功能,例如对 Parquet 文件格式、JSON、时区的支持,以及对 HTTP(S) 和 S3 协议的支持,都是作为扩展实现的。扩展也在 DuckDB Wasm 中工作。用户贡献可在社区扩展中获得。
免费
DuckDB 的开发始于主要开发者在荷兰担任公职期间。我们认为,将我们的工作成果免费提供给荷兰或其他地方的任何人,是我们的责任和对社会的义务。这就是为什么 DuckDB 在非常宽松的 MIT 许可证下发布,并且项目知识产权由 DuckDB 基金会持有。我们欢迎任何人的贡献,前提是他们遵守我们的行为准则。
经过严格测试
虽然 DuckDB 最初是由一个研究小组创建的,但它从未打算成为一个研究原型。相反,它旨在成为一个稳定成熟的数据库系统。为了促进这种稳定性,DuckDB 正在通过持续集成进行密集测试。DuckDB 的测试套件目前包含数百万个查询,并包括从 SQLite、PostgreSQL 和 MonetDB 的测试套件中改编的查询。测试在各种平台和编译器上重复进行。每个拉取请求都会根据完整的测试设置进行检查,并且只有通过后才能合并。
除了这个测试套件,我们还运行各种测试,在重负载下对 DuckDB 进行压力测试。我们运行 TPC-H 和 TPC-DS 基准测试,并运行各种 DuckDB 被许多客户端并行使用的测试。
同行评审论文和学位论文
- 运行时可扩展解析器 (Runtime-Extensible Parsers) (CIDR 2025)
- 固态时代稳健的外部哈希聚合 (Robust External Hash Aggregation in the Solid State Age) (ICDE 2024)
- 这些行天生就用于排序,我们就是这样做的 (These Rows Are Made for Sorting and That's Just What We'll Do) (ICDE 2023)
- 几乎无需统计信息的连接顺序优化 (Join Order Optimization with (Almost) No Statistics) (硕士论文,2022)
- DuckDB-Wasm:Web 上的快速分析处理 (DuckDB-Wasm: Fast Analytical Processing for the Web) (VLDB 2022 演示)
- 数据科学的数据管理——迈向嵌入式分析 (Data Management for Data Science - Towards Embedded Analytics) (CIDR 2020)
- DuckDB:一个可嵌入的分析数据库 (DuckDB: an Embeddable Analytical Database) (SIGMOD 2019 演示)
使用/为 DuckDB 构建的项目
要了解使用 DuckDB 的项目,请访问 Awesome DuckDB 仓库。
站在巨人的肩膀上
DuckDB 使用了各种开源项目的一些组件,并从科学出版物中汲取了灵感。我们对此深表感谢。以下是概述:
- 执行引擎: 向量化执行引擎的灵感来自 Peter Boncz、Marcin Zukowski 和 Niels Nes 的论文《MonetDB/X100:超流水线查询执行 (MonetDB/X100: Hyper-Pipelining Query Execution)》。MonetDB/X100 后来演变为 Vectorwise (Actian Vector) 数据库系统。
- 优化器: DuckDB 的优化器从 Guido Moerkotte 和 Thomas Neumann 的论文《动态规划卷土重来 (Dynamic programming strikes back)》以及 Thomas Neumann 和 Alfons Kemper 的论文《任意查询的非嵌套化 (Unnesting Arbitrary Queries)》中汲取灵感。
- 并发控制: 我们的 MVCC 实现的灵感来自 Thomas Neumann、Tobias Mühlbauer 和 Alfons Kemper 的论文《内存数据库系统中快速可串行化多版本并发控制 (Fast Serializable Multi-Version Concurrency Control for Main-Memory Database Systems)》。
- 辅助索引: DuckDB 支持基于 Viktor Leis、Alfons Kemper 和 Thomas Neumann 论文《自适应基数树:内存数据库的巧妙索引 (The Adaptive Radix Tree: ARTful Indexing for Main-Memory Databases)》的辅助索引。
- SQL 窗口函数: DuckDB 的窗口函数实现使用了 Viktor Leis、Kan Kundhikanjana、Alfons Kemper 和 Thomas Neumann 在论文《分析性 SQL 查询中窗口函数的高效处理 (Efficient Processing of Window Functions in Analytical SQL Queries)》中描述的段树聚合。
- SQL 不等式连接: DuckDB 的不等式连接实现使用了 Zuhair Khayyat、William Lucia、Meghna Singh、Mourad Ouzzani、Paolo Papotti、Jorge-Arnulfo Quiané-Ruiz、Nan Tang 和 Panos Kalnis 在论文《闪电般快速且节省空间的不等式连接 (Lightning Fast and Space Efficient Inequality Joins)》中描述的 IEJoin 算法。
- 浮点值压缩: DuckDB 支持多种浮点值压缩算法:
- Panagiotis Liakos、Katia Papakonstantinopoulou 和 Yannis Kotidi 的 Chimp
- Patas,一项内部开发
- Azim Afroozeh、Leonard Kuffo 和 Peter Boncz 的 ALP(自适应无损浮点压缩),他们也贡献了他们的实现
- SQL 解析器: 我们使用 PostgreSQL 解析器,它被重新打包为独立的库。到我们自己解析树的转换灵感来自 Peloton。
- Shell: 我们使用 SQLite shell 来操作 DuckDB。
- 正则表达式: DuckDB 使用 Google 的 RE2 正则表达式引擎。
- 字符串格式化: DuckDB 使用 fmt 字符串格式化库。
- UTF 处理: DuckDB 使用 utf8proc 库来检查和规范化 UTF8。
- 排序规则和时间: DuckDB 使用 ICU 库进行排序规则、时区和日历支持。
- 测试框架: DuckDB 使用 Catch2 单元测试框架。
- 测试用例: 我们使用 SQLite 的 SQL Logic Tests 来测试 DuckDB。
- 结果验证: Manuel Rigger 使用他出色的 SQLancer 工具来验证 DuckDB 结果的正确性。
- 查询模糊测试: 我们通过
sqlsmith
扩展使用 SQLsmith 生成随机查询进行额外测试。 - JSON 解析器: 我们使用 yyjson,一个用 ANSI C 编写的高性能 JSON 库,用于在 DuckDB 的 JSON 扩展中解析 JSON。