当前位置: 首页 > news >正文

理解 DuckDB 的逻辑计划(Logical Plan)、优化器(Optimizer)和物理执行计划模块的工作流程

✅ 一、用于调试的 SQL 语句建议

✅ 1. 创建 orders 表的 SQL

CREATE TABLE orders (
    order_id     INTEGER,
    customer_id  INTEGER,
    order_date   DATE,
    amount       DOUBLE
);

✅ 2. 插入测试数据(模拟多个客户在不同时间下单)

INSERT INTO orders VALUES
-- 客户1:7个订单,部分在2022年之后
(1, 101, '2022-01-02', 120.0),
(2, 101, '2022-02-15', 80.0),
(3, 101, '2022-03-01', 90.0),
(4, 101, '2022-04-10', 60.0),
(5, 101, '2022-06-12', 70.0),
(6, 101, '2022-07-20', 30.0),
(7, 101, '2022-08-05', 40.0),

-- 客户2:4个订单,不满足 HAVING 条件
(8, 102, '2022-02-01', 200.0),
(9, 102, '2022-03-01', 180.0),
(10, 102, '2022-03-15', 150.0),
(11, 102, '2022-03-20', 220.0),

-- 客户3:6个订单,满足 HAVING 条件
(12, 103, '2022-01-05', 95.0),
(13, 103, '2022-01-15', 85.0),
(14, 103, '2022-02-10', 90.0),
(15, 103, '2022-02-20', 88.0),
(16, 103, '2022-03-01', 77.0),
(17, 103, '2022-03-10', 66.0),

-- 客户4:5个订单,刚好不满足 COUNT(*) > 5
(18, 104, '2022-04-01', 50.0),
(19, 104, '2022-04-05', 45.0),
(20, 104, '2022-04-10', 60.0),
(21, 104, '2022-04-15', 70.0),
(22, 104, '2022-04-20', 80.0);

✅ 3. 执行你的分析查询 SQL(统计订单数大于 5 的客户)

我们需要选择一个能覆盖典型逻辑运算的 SQL 语句,例如选择、投影、连接、聚合等。
sql

-- 推荐用于逻辑计划和优化器调试的 SQL

SELECT customer_id, COUNT(*) AS order_count

FROM orders

WHERE order_date >=  DATE  '2022-01-01'

GROUP  BY customer_id

HAVING  COUNT(*) >  5

ORDER  BY order_count DESC

LIMIT 10;

这个 SQL 涵盖以下关键节点:

  • Filter(WHERE)

  • Group By / Aggregation

  • Having

  • Projection

  • Order By + Limit

✅ 二、推荐的 GDB 调试设置流程

(gdb) b Parser::ParseQuery
Breakpoint 1 at 0x589200
(gdb) b Binder::Bind
Breakpoint 2 at 0xa8ff40 (40 locations)
(gdb) b Planner::CreatePlan
Breakpoint 3 at 0xb1da90 (2 locations)
(gdb) b Optimizer::Optimize
Breakpoint 4 at 0xa2ae90

在上面的4处设置断点。

✅ 三、查看逻辑计划过程

主要的过程就是参考https://github.com/duckdb/duckdb/blob/main/src/main/client_context.cpp文件里面的353行的ClientContext::CreatePreparedStatementInternal函数,里面记录了执行的过程,从1️⃣ Create Logical Plan->2️⃣ 优化逻辑计划->3️⃣ 构建物理计划->4️⃣ 初始化执行器->5️⃣ 开始执行。
逻辑计划的执行入口在/src/planner/planner.cpp的32行的Planner::CreatePlan函数内,首先查看duckdb逻辑计划构建阶段的入口。

Planner::CreatePlan函数

首先进入到同名的Planner::CreatePlan上面选择对应的statement->type类型,比如我这里选择的就是select类型。
Planner::CreatePlan函数地址:https://github.com/duckdb/duckdb/tree/main/src/planner 32行
在了解这个函数之前,先去了解逻辑计划的基类一下class LogicalOperator类,简单图示:

class LogicalOperator
    ├── LogicalOperatorType type         ← 节点类型(如 JOIN、GET、FILTER)
    ├── vector<LogicalOperator*> children← 子节点(树结构)
    ├── vector<Expression*> expressions  ← 节点内表达式(如 WHERE 条件、SELECT 列)
    ├── vector<LogicalType> types        ← 返回列类型
    ├── idx_t estimated_cardinality      ← 行数估计
    ├── virtual ResolveTypes() = 0       ← 推断返回类型(由子类实现)
    ├── ToString()/Print()               ← 输出逻辑计划树
    └── Cast<T>()                        ← 类型安全的子类转换
  • LogicalOperatorType type
    枚举类型,表示逻辑节点的类别:这个字段可以让优化器、渲染器、执行器知道当前是哪个操作。
  • ② vector<unique_ptr> children
    当前逻辑节点的子节点,构成逻辑计划树。
    比如:一个 LogicalFilter 会有一个子节点是 LogicalGet。
  • ③ vector<unique_ptr> expressions
    表达式节点,比如:
    WHERE x > 10 → x > 10 是一个表达式
    SELECT x + y → x + y 是一个表达式
    对于某些逻辑节点(如 LogicalProjection),表达式就是它的输出列表达式。
  • ④ vector types
    当前逻辑节点最终会输出哪些列的类型。
    是在 ResolveOperatorTypes() 或 ResolveTypes() 中由具体逻辑算子设置。
  • ⑤ estimated_cardinality 和 has_estimated_cardinality
    用于估算输出行数,供优化器做选择(如连接顺序)
  • ⑥ ResolveOperatorTypes() + ResolveTypes()
    比如:LogicalProjection 会根据表达式类型推导出列类型
    LogicalAggregate 会根据聚合函数决定返回类型
  • ⑦ ToString() 和 Print()
    用于调试或 explain 时打印逻辑计划结构
  • ⑧ Copy(), Serialize(), Cast() 等
    提供计划节点的复制、序列化能力
    Cast() 用于安全地将 LogicalOperator 转为具体类型(如 LogicalJoin)
🧠 总结一句话

LogicalOperatorDuckDB 中逻辑执行计划的树节点基类&#

相关文章:

  • [Godot] C#简单实现人物的控制和动画
  • Spring MVC 逻辑视图(JSP、Thymeleaf、FreeMarker)与非逻辑视图(JSON、Excel、PDF、XML)详解及示例
  • 2025年AI生成引擎搜索发展现状与趋势总结​​
  • 【数学】线性代数(Python)
  • 水果成篮 -- 滑动窗口
  • Franka双臂机器人:多领域革新与核心技术深度解析
  • 数组划分使元素总和最接近
  • 如何迁移 GitHub 仓库到 GitLab?
  • 最新版PhpStorm超详细图文安装教程,带补丁包(2025最新版保姆级教程)
  • 三类人解决困境的方法
  • 【项目管理】第5章 信息系统管理 --知识点整理
  • Oracle 表空间高水位收缩全攻略
  • Ubuntu 22.04 AI大模型环境配置及常用工具安装
  • 消息队列(Message Queue)简介
  • AIGC2——AI生成艺术的边界与伦理:艺术性、版权与美学价值的争议
  • 学习海康VisionMaster之多直线查找
  • 使用python访问mindie部署的vl多模态模型
  • 【数据结构】二叉搜索树
  • Android Input——输入子系统(三)
  • C++ Primer Plus 编程练习题 第六章 分支语句和逻辑运算符
  • 习近平致电祝贺阿尔巴尼斯当选连任澳大利亚总理
  • 扶桑谈|从石破茂“越菲行”看日本周边外交布局战略新动向
  • 习近平结束对俄罗斯国事访问并出席纪念苏联伟大卫国战争胜利80周年庆典回到北京
  • 巴西总统卢拉将访华
  • 上海第四批土拍成交额97亿元:杨浦宅地成交楼板单价半年涨近7000元
  • 习近平会见缅甸领导人敏昂莱