Featured image of post DuckDB 源码分析:架构设计与核心模块深度解读

DuckDB 源码分析:架构设计与核心模块深度解读

深入 DuckDB 源码分析,解读数据库架构设计、代码仓库结构、存储引擎、执行引擎、优化器等核心模块工作原理。从源码角度理解 DuckDB 为何如此高效。

DuckDB 源码分析概述

DuckDB 完全用 C++ 实现,代码仓库托管在 GitHub。截至 2026 年,项目拥有超过 30 万行 C++ 代码,代码质量极高,架构清晰,是学习现代列式数据库实现的绝佳素材。

本文从 DuckDB 源码分析的角度,带你深入了解其架构设计、核心模块和工作原理。


代码仓库结构

克隆仓库后,顶级目录组织如下:

duckdb/
├── src/                    # 核心源码
│   ├── include/            # 头文件
│   ├── common/             # 通用工具和类型系统
│   ├── storage/            # 存储引擎
│   ├── execution/          # 执行引擎
│   ├── optimizer/          # 查询优化器
│   ├── parser/             # SQL 解析器
│   ├── planner/            # 查询计划器
│   ├── function/           # 内置函数
│   └── main/               # 入口和数据库管理
├── extension/              # 扩展(JSON, HTTPFS, ICU 等)
├── test/                   # 测试代码
├── tools/                  # 工具(CLI, Python, Node.js 等绑定)
├── benchmark/              # 基准测试
├── Makefile                # 构建文件
└── CMakeLists.txt          # CMake 构建配置

核心目录详解

从 DuckDB 源码分析的角度,以下目录最为关键:

目录职责关键文件
src/storage/数据持久化、缓冲池、表存储table_manager.cpp, buffer_manager.cpp
src/execution/查询执行、向量化处理executor.cpp, operator.cpp
src/optimizer/查询优化、统计信息optimizer.cpp, statistics
src/parser/SQL 解析、语法树构建parser.cpp, transformer.cpp
src/planner/逻辑计划构建planner.cpp, logical_operator.cpp
src/function/聚合、标量、表函数aggregate, scalar, table

构建系统与编译

从源码构建

# 克隆仓库
git clone https://github.com/duckdb/duckdb.git
cd duckdb

# Release 构建(推荐)
make

# Debug 构建(开发调试用)
make debug

# 指定并行度加速编译
make -j$(nproc)

# 编译后的二进制
./build/release/duckdb

CMake 选项

# 启用扩展
cmake -DBUILD_PARQUET=1 -DBUILD_JSON=1 -DBUILD_HTTPFS=1

# 启用测试
cmake -DBUILD_UNITTESTS=1

# 编译优化级别
cmake -DCMAKE_BUILD_TYPE=Release  # 或 Debug, RelWithDebInfo

构建过程分析

DuckDB 的构建系统值得关注的点:

  • 单一组件编译:编译产物是单个 duckdb 可执行文件,链接时通过 unity build 加速
  • 扩展动态加载:扩展可以编译成 .duckdb_extension 文件,运行时加载
  • 测试框架:使用 DuckDB 自研的测试框架 test/unittest

存储引擎架构

DuckDB 的存储引擎是**列式(columnar)**的,这是它比 SQLite 等行式数据库快 10-100 倍的根本原因。

存储层级

Database File (.duckdb)
├── Catalog (元数据)
│   ├── Schemas
│   ├── Tables
│   ├── Columns (列式存储)
│   └── Indexes
├── Data
│   ├── Row Groups (行组,每组约 10 万行)
│   │   ├── Column Segments (列段)
│   │   └── Statistics (统计信息,用于查询过滤)
│   └── Persistent Storage
└── WAL (Write-Ahead Log)

列式压缩

DuckDB 支持多种列式压缩算法,源码在 src/storage/compression/

// 源码中的压缩类型枚举(简化)
enum class CompressionType : uint8_t {
    UNCOMPRESSED,
    CONSTANT,    // 常量压缩
    RLE,         // 行程编码
    DICTIONARY,  // 字典压缩
    BITPACKING,  // 位打包
    FSST,        // 快速静态符号表
    CHIMP,       // 时间序列压缩
    PATAS        // 自适应时间序列压缩
};

缓冲池管理

BufferManager 是存储引擎的核心组件,源码在 src/storage/buffer_manager.cpp

// BufferManager 核心职责(基于源码分析):
// 1. 管理内存中的数据块(Buffer)
// 2. 处理磁盘与内存之间的页面交换
// 3. 实现 LRU 淘汰策略
// 4. 支持直接 IO 和内存映射文件

class BufferManager {
    // 关键方法
    BlockHandle* RegisterBlock(BlockId block_id);
    void UnregisterBlock(BlockId block_id);
    DataPointer Pin(BlockHandle* handle);
    void Unpin(BlockHandle* handle);
};

执行引擎架构

DuckDB 的执行引擎采用**向量化(Vectorized)**模型,这是它高性能的关键。

Volcano 迭代器模型

SQL Query
    ↓
Parser (解析 SQL)
    ↓
Planner (生成逻辑计划)
    ↓
Optimizer (优化逻辑计划)
    ↓
Physical Plan (生成物理计划)
    ↓
Executor (向量化执行)
    ↓
Result

向量化执行

与传统数据库逐行处理不同,DuckDB 每次处理一批数据(Vector),批量大小为 STANDARD_VECTOR_SIZE(默认 2048 行)。

// 源码中的 Vector 结构(简化)
struct Vector {
    VectorType type;     // FLAT, CONSTANT, DICTIONARY, SEQUENCE
    LogicalType logic_type;  // INTEGER, VARCHAR, DOUBLE...
    data_ptr_t data;     // 实际数据指针
    ValidityMask validity;   // NULL 值掩码
    SelectionVector* sel;    // 选择向量(用于过滤)
};

// 操作符处理 Vulkan 的方式
void FilterOperator::Execute(DataChunk &input, DataChunk &result) {
    // 一次处理整个 chunk(2048 行)
    // 通过 SelectionVector 记录符合条件的行
    // 无需逐行判断,CPU 缓存友好
}

执行流水线

// 源码中的执行流水线示例
// Pipeline: Scan → Filter → Aggregate → Output
//          ↓           ↓           ↓
//    读取 2048 行  过滤 2048 行  聚合结果
//          ↓           ↓           ↓
//    向量化读取    SIMD 过滤   并行聚合

查询优化器

DuckDB 的优化器在 src/optimizer/ 中,执行一系列优化规则:

// 优化器规则执行顺序(源码中定义)
void Optimizer::RunOptimizer() {
    // 1. 表达式重写
    expression_rewriter->Rewrite(plan);
    
    // 2. 谓词下推
    filter_pushdown->PushDown(plan);
    
    // 3. 连接顺序优化
    join_order_optimizer->Optimize(plan);
    
    // 4. 列剪枝
    column_binding_manager->Prune(plan);
    
    // 5. 子查询消除
    subquery_flattener->Flatten(plan);
    
    // 6. 统计信息优化
    statistics_propagator->Propagate(plan);
}

统计信息驱动的优化

DuckDB 存储行组的列级别统计信息(min/max/null_count),优化器利用这些信息进行:

  • 分区裁剪:根据 min/max 跳过不相关的行组
  • 基数估计:选择最优的 Join 顺序
  • 查询计划选择:决定是否使用索引或全表扫描

SQL 解析器

DuckDB 的 SQL 解析器位于 src/parser/,使用手写递归下降解析器(而非 Yacc/Bison):

// 解析过程
// SQL: SELECT a, b FROM t WHERE c > 10
// ↓
// Parser::ParseQuery(sql_string)
// ↓
// Transformer (转换 SQL token 为 AST 节点)
// ↓
// SelectStatement (SELECT 语句的 AST 表示)
//   ├── select_list: [ColumnRef(a), ColumnRef(b)]
//   ├── from_table: BaseTableRef(t)
//   └── where_clause: Comparison(c, >, 10)

class SelectStatement : public SQLStatement {
    unique_ptr<SelectNode> node;
    // SelectNode 包含: select_list, from_table, where_clause,
    // group_expressions, having, order_expressions, limit...
};

扩展机制

DuckDB 的扩展架构非常灵活,核心扩展包括:

-- 安装和加载扩展
INSTALL httpfs;
LOAD httpfs;

INSTALL json;
LOAD json;

INSTALL parquet;
LOAD parquet;

INSTALL icu;      -- Unicode 支持
LOAD icu;

INSTALL fts;      -- 全文搜索
LOAD fts;

INSTALL spatial;  -- 空间数据处理
LOAD spatial;

扩展的源码在 extension/ 目录下,每个扩展有自己的目录结构:

extension/
├── parquet/        # Parquet 读写
├── json/           # JSON 支持
├── httpfs/         # S3/HTTP 文件系统
├── icu/            # 国际化
├── fts/            # 全文搜索
└── spatial/        # 空间数据

性能设计原则

从 DuckDB 源码分析中,可以总结出其高性能设计的几个核心原则:

  1. 向量化执行:一次处理 2048 行,最大化 CPU 缓存利用率
  2. 列式存储:只读取查询需要的列,减少 IO
  3. 统计信息过滤:利用列级 min/max 跳过无关数据块
  4. MMAP 优化:大文件使用内存映射,避免显式 IO
  5. 编译优化:使用 C++ 模板元编程和编译时计算
  6. SIMD 加速:关键路径使用 SIMD 指令集(AVX2/NEON)

如何深入源码

# 推荐阅读路径(按从易到难)

# 1. 从 main 入口开始
src/main/database.cpp       # 数据库启动流程
src/main/connection.cpp     # 连接和查询执行

# 2. 理解核心类型系统
src/common/types/           # 类型系统

# 3. 阅读解析和计划
src/parser/                 # SQL 解析
src/planner/                # 查询计划

# 4. 深入存储引擎
src/storage/table/          # 表存储
src/storage/checkpoint/     # 检查点

# 5. 探索执行引擎
src/execution/operator/     # 各种操作符实现

架构图

相关文章


📘 博客: https://duckdblab.org #DuckDB #源码分析 #数据库架构 #C++

📺 Watch video tutorials → DuckDB Lab YouTube

Subscribe for more DuckDB & AI automation tutorials

使用 Hugo 构建
主题 StackJimmy 设计