ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

pgrust 查询执行器剖析:从解析器到执行计划的全链路

pgrust 查询执行器剖析:从解析器到执行计划的全链路 pgrust 查询执行器剖析从解析器到执行计划的全链路【免费下载链接】pgrustPostgres rewritten in Rust, now faster than Postgres and Clickhouse项目地址: https://gitcode.com/GitHub_Trending/pg/pgrustpgrust 是一个用 Rust 重写 PostgreSQL 的开源项目目标是让经典数据库内核焕发新生。它的查询执行器完整复刻了 Postgres 从解析、分析、优化到执行的全链路流程并已通过超过 46000 条回归测试。这篇文章将带你以一条普通 SQL 为例一步步拆解 pgrust 查询执行器内部发生了什么适合想理解数据库内核的初学者和普通开发者阅读。为什么查询执行器是数据库的心脏无论你执行多简单的SELECT数据库都要完成一整套复杂流程。查询执行器负责把人类可读的 SQL 翻译成机器可执行的计划再逐行产出结果。它的效率直接决定了查询快慢而 pgrust 的目标正是让这条链路比原生 Postgres 更快——在分析型负载上甚至宣称比 ClickHouse 还快。pgrust 的特别之处在于它磁盘兼容 Postgres能直接启动一个已有的 Postgres 18.3 数据目录同时用 Rust 的安全性和现代工具链重写内核。这意味着你可以把 pgrust 当作 Postgres 来用却享受到 Rust 带来的内存安全和更好的并发潜力。一条 SQL 的一生pgrust 查询执行全流程概览一条查询在 pgrust 中的旅程大致分为四个阶段阶段对应模块做什么1. 解析crates/backend/parser/把 SQL 文本变成语法树2. 分析crates/backend/parser/parser_analyze/绑定对象、校验语义生成查询树3. 优化crates/backend/optimizer/生成并挑选执行计划4. 执行crates/backend/executor/逐节点运行计划返回结果顶层调度由crates/backend/tcop/Traffic Cop负责它就像交通警察决定一条命令该走查询通道还是工具命令通道。接下来我们逐个阶段深入。第一阶段词法与语法解析——SQL 文本如何变成语法树解析是查询执行器的入口。当 pgrust 收到字符串SELECT * FROM users WHERE age 18时首先要做两件事词法分析把字符串切成一个个 token关键字、标识符、数字、符号。pgrust 的扫描器实现在crates/backend/parser/scan_fgram/。语法分析根据语法规则把这些 token 组装成一棵抽象语法树AST。核心逻辑在crates/backend/parser/gram_core/和crates/backend/parser/driver/。在 pgrust 中语法树的节点类型定义在crates/types/nodes/共 75 个 Rust 源文件对应 Postgres 原生的parsenodes.h结构。解析器只负责读得懂并不关心这张表是否存在、字段类型是否匹配。第二阶段语义分析——让语法树长出肌肉解析出来的 AST 还不能执行必须经过语义分析analyze阶段才能变成可供优化器使用的查询树Query Tree。pgrust 的这一阶段位于crates/backend/parser/parser_analyze/其中select.rs处理 SELECT 语句的展开insert.rs、update_delete.rs、merge.rs处理写操作inline_sql.rs、inline_srf.rs处理函数内联这个阶段会完成几件关键工作对象绑定把表名映射到实际的 Relation 对象把列名映射到具体的属性编号类型推导确认表达式的数据类型必要时插入隐式类型转换权限检查准备记录访问的对象供执行时校验权限子查询提升把可提升的子查询重写为连接Join让优化器有更多发挥空间分析完成后pgrust 就得到了一个结构化的查询树接下来轮到优化器登场。第三阶段优化器——执行计划是怎样炼成的优化器可能是整个查询执行器中最有智慧的部分。pgrust 的优化器在crates/backend/optimizer/下分三个子模块path/负责生成候选访问路径Path比如顺序扫描、索引扫描、各种连接方式plan/把最优路径固化成执行计划Plan入口是crates/backend/optimizer/plan/planner/src/lib.rsprep/执行计划前的预处理如常量折叠、子连接展开优化器的工作逻辑大致如下对每个基表生成访问路径Seq Scan、Index Scan、Bitmap Scan……枚举连接顺序和连接算法Nest Loop、Hash Join、Merge Join用代价模型估算每条路径的成本选出总代价最低的执行计划对聚合、排序、去重等操作选择合适的实现方式比如一条简单的SELECT * FROM users WHERE age 18优化器会权衡全表扫描Seq Scan和索引扫描Index Scan哪个更划算如果age列上有索引且选择性高优化器通常会更倾向于走索引。第四阶段执行器——执行计划如何真正跑起来计划生成后pgrust 查询执行器开始执行。执行器入口在crates/backend/executor/execMain/src/lib.rs它负责初始化执行状态、调度顶层计划节点并最终把结果返回给客户端。pgrust 的执行器采用与 Postgres 相同的迭代器模型volcano 模型每个计划节点都实现取一行的接口父节点向子节点索要元组一层层向下传递直到扫描节点真正从存储层读取数据。这种模型的好处是内存占用小、实现直观。执行器下还有几十个专用节点模块各司其职节点模块路径职责顺序扫描crates/backend/executor/nodeSeqscan/逐块扫描表数据索引扫描crates/backend/executor/nodeIndexscan/利用索引定位元组哈希连接crates/backend/executor/nodeHashjoin/构建哈希表连接两表聚合crates/backend/executor/nodeAgg/分组聚合计算排序crates/backend/executor/nodeSort/内存/外存排序插入/更新/删除crates/backend/executor/nodeModifyTable/执行 DML 操作表达式求值则由crates/backend/executor/execExpr/和execExprInterp/负责把age 18这样的条件编译成高效的字节码式求值循环。用EXPLAIN看懂一条查询的执行计划理解 pgrust 查询执行器最好的方式就是用EXPLAIN查看执行计划。以SELECT * FROM users WHERE age 18为例你可能看到类似这样的输出Seq Scan on users (cost0.00..15.10 rows50 width36) Filter: (age 18)Seq Scan顺序扫描说明优化器选择了全表扫描cost预估的启动代价和总代价rows预估返回行数Filter过滤条件在扫描时逐行判断如果两张表做连接你还可能看到Hash Join、Nested Loop等节点。学会读执行计划就等于掌握了和查询执行器对话的能力。pgrust 查询执行器的下一步pgrust 仍在快速演进中其路线图透露了查询执行器未来的几个方向多线程内核用线程模型替代每连接一进程大幅提升事务型负载性能内置连接池减少连接建立开销更强的分析型负载目标在 clickbench 上全面超越 ClickHouse执行计划护栏为糟糕查询和 AI 生成的 SQL 提供运行时防护减少突然的坏计划切换这些改动都会直接作用在我们剖析的这条全链路上让 pgrust 查询执行器从兼容 Postgres走向超越 Postgres。总结从crates/backend/parser/的语法树到parser_analyze/的查询树再到optimizer/的执行计划最后到executor/的逐节点执行——pgrust 用 Rust 完整重现了 Postgres 查询执行器的全链路。对新手来说pgrust 是一份极好的数据库内核教科书代码是内存安全的 Rust行为却和 Postgres 一致对照着官方 46000 条回归测试你能清晰地看到每个阶段做了什么。如果你想亲手体验可以克隆项目仓库git clone https://gitcode.com/GitHub_Trending/pg/pgrust并按照 README 中的步骤编译运行然后对任意一条查询执行EXPLAIN开始你的数据库内核探索之旅。【免费下载链接】pgrustPostgres rewritten in Rust, now faster than Postgres and Clickhouse项目地址: https://gitcode.com/GitHub_Trending/pg/pgrust创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表