duckdb初探
前言
依旧先创个帖子激励自己……
贴一下用于vscode调试看代码的配置信息:
tasks.json
{ |
launch.json
{ |
然后就可以开始愉快的看代码了=.=

不对,有点神秘,还有goto?
果然是高端代码!

摘一点官方讲解
DuckDB 执行一条 SQL 语句的整体流程
1. 解析阶段 (Parsing)
核心步骤:将 SQL 字符串转换为令牌(如 ParsedExpression、TableRef、QueryNode、SQLStatement),不涉及目录或类型解析,仅语法检查。
源代码文件/目录
src/parser/:解析器核心目录。
src/include/duckdb/parser/expression/comparison_expression.hpp:示例 ParsedExpression 类型。
src/include/duckdb/parser/:包含 ParsedExpression、TableRef、QueryNode、SQLStatement 的头文件。
文件路径 作用描述 src/parser/parser.cpp核心递归下降解析器:处理 SQL 字符串 → Tokens → ParsedExpression/SQLStatement。生成初始 AST。 src/parser/parsed_data/(e.g.,parsed_expression.cpp,sql_statement.cpp)定义 Parsed 结构:存储解析结果,如表达式树和查询节点,用于后续绑定。 src/binder/binder.cpp绑定器:将 Parsed AST 转换为 Bound 形式,进行目录解析和类型绑定,为逻辑算子树铺路。 src/planner/logical_planner.cpp逻辑规划器:从 Bound 结构生成逻辑算子树(LogicalOperator),如将 SELECT 转换为 Scan + Project 树。
2. 绑定阶段 (Binding)
核心步骤:将解析节点转换为绑定形式,使用目录解析表/列,确定类型,提取聚合/窗口函数。
源代码文件/目录:
- src/binder/:绑定器目录(隐含)。
3. 逻辑规划阶段 (Logical Planning)
核心步骤:从绑定语句生成逻辑操作符树(LogicalOperator)。
源代码文件/目录
src/planner/:规划器目录。
src/include/duckdb/planner/logical_operator.hpp:LogicalOperator 定义。
文件路径 作用描述 src/planner/logical_planner.cpp(续)生成初始逻辑算子树,作为优化输入。 src/optimizer/optimizer.cpp优化器入口:运行规则序列(如 FilterPushdown、JoinReorder)重塑逻辑树。 src/optimizer/rule/(e.g.,filter_pushdown.cpp,join_order.cpp)具体优化规则:改造算子树,e.g., 推送 Filter 到 Scan 节点。 src/planner/physical_planner.cpp物理规划器:将优化逻辑树转换为物理计划,选择执行算法(如 HashJoinPhysicalOperator)。
4. 优化阶段 (Optimization)
核心步骤:对逻辑树应用优化器序列,包括表达式重写(Expression Rewriter)、过滤推送(Filter Pushdown)、连接顺序优化(Join Order Optimizer,使用 DPccp 算法)、公共子表达式提取(Common Sub Expressions)和 IN 子句重写(In Clause Rewriter)。
源代码文件/目录
- src/optimizer/:优化器目录(隐含)。
5. 列绑定解析阶段 (Column Binding Resolution)
核心步骤:将 BoundColumnRefExpression(引用表列)转换为 BoundReferenceExpression(引用 DataChunk 中的索引)。
源代码文件/目录
- src/planner/:规划器扩展。
- src/include/duckdb/planner/expression/bound_columnref_expression.hpp:BoundColumnRefExpression。
- src/include/duckdb/planner/expression/bound_reference_expression.hpp:BoundReferenceExpression。
- src/include/duckdb/common/types/data_chunk.hpp:DataChunk 定义。
6. 物理规划阶段 (Physical Planning)
核心步骤:将优化逻辑树转换为物理操作符树(PhysicalOperator)。
源代码文件/目录
- src/execution/:执行规划目录。
- src/include/duckdb/execution/physical_operator.hpp:PhysicalOperator。
7. 执行阶段 (Execution)
核心步骤:使用推送式向量化模型执行物理操作符,通过 DataChunk 推送数据产生结果。支持并行执行和溢出到磁盘。
源代码文件/目录
src/execution/:执行引擎核心。
src/include/duckdb/common/types/data_chunk.hpp:DataChunk 处理。
文件路径 作用描述 src/execution/physical_plan_generator.cpp计划生成器:最终组装物理树,准备执行。 src/execution/physical_operator.cpp核心物理算子基类:定义 Execute 方法,每个算子(如 FilterPhysicalOperator)处理 DataChunk。 src/execution/operator/(e.g.,scan_physical_operator.cpp,join_physical_operator.cpp,aggregate_physical_operator.cpp)具体算子实现:e.g., Scan 从表/文件读取 Chunk,Join 执行哈希匹配。 src/execution/executor.cpp执行器入口:SinkManager 协调 Pipeline,推动执行并收集结果。 src/common/types/data_chunk.cppDataChunk 定义:向量存储,用于批量推送/处理数据。
运行时涉及的文件和目录
DuckDB 在执行语句时会根据连接模式(:memory: 为内存模式,指定文件为磁盘模式)创建/访问文件。这些文件用于持久化、临时存储和配置。以下表格总结关键文件(相对路径基于数据库文件或工作目录):
| 文件/目录名称 | 位置 | 目的 | 模式 | 共享性 |
|---|---|---|---|---|
database_filename (e.g., mydb.duckdb) | 工作目录或指定路径 | 主数据库文件,存储持久数据;在读/写语句中访问。 | 磁盘模式 | - |
database_filename.wal (e.g., mydb.wal) | 相对数据库文件 | 写前日志(WAL),用于事务日志和崩溃恢复;在写操作中创建/访问。 | 磁盘模式 | - |
database_filename.tmp/ (e.g., mydb.tmp/) | 相对数据库文件 | 临时目录,用于查询中间结果、排序/哈希溢出。 | 磁盘模式 | - |
.tmp/ | 工作目录 | 临时目录,用于内存模式下的瞬时操作(如中间结果)。 | 内存模式 | - |
~/.duckdbrc | 用户主目录 (~) | CLI 初始化脚本;在 CLI 执行语句时读取。 | CLI | 仅 CLI |
~/.duckdb_history | 用户主目录 (~) | 命令历史;在 CLI 会话中更新。 | CLI | 仅 CLI |
~/.duckdb/extensions | 用户主目录 (~) | 扩展二进制文件;在加载扩展的语句中访问。 | 所有 | 跨客户端 |
~/.duckdb/stored_secrets | 用户主目录 (~) | 持久化秘密;在涉及认证的语句中访问。 | 所有 | 跨客户端/版本 |






![[论文阅读]GPU-accelerated Database Systems Survey and Open Challenges](http://aplainjane.github.io/article/fbfcc01e/wallhaven-9d3181_1920x1080.png)
