当您向 PostgreSQL 发送查询时,查询会依次经历多个处理阶段,并在最后返回结果。这些阶段称为:
-
解析
-
分析
-
重写
-
计划
-
执行
在另一篇文章中,我简要概述了PostgreSQL在每个查询处理阶段的主要责任。你可以在这里找到它。
https://www.highgo.ca/2024/01/26/a-comprehensive-overview-of-postgresql-query-processing-stages/
在这篇文章中。有一个主要聚焦规划器模块的功能,您可以在此处找到。
https://www.highgo.ca/2024/03/22/understand-postgresqls-planner-simple-scan-paths-vs-plans/
在这篇博客中,我们将重点介绍查询处理的执行器部分,作为连接 PostgreSQL 内部模块的关键枢纽,执行器负责协调并收集查询所需的确切数据。
实际上,将执行器用于描述查询处理的这一阶段并不准确。在 PostgreSQL 源代码中,这一角色更多地被整合在名为“portal”的对象框架内。通常,它有 2 条潜在的路径,即“执行器”路径或“指令处理器”路径。
通常情况下,我们只是将此阶段称为“执行器”而不是“门户”,因为执行器处理大多数涉及 SELECT、INSERT、UPDATE、DELETE 的 DML 查询类型......等等,它必须根据“planner”模块创建的查询计划来处理它们。
另一方面,”指令处理器”并不依赖于“计划器”生成的查询计划来执行流程,而是直接处理DDL(数据定义语言)操作以及其他非DML(数据操纵语言)的查询类型,例如 VACUUM、CREATE、PREPARE ...等。
就所涉及的逻辑而言,门户(或执行器)并不像计划器那么复杂,但它同样是PostgreSQL内部架构中不可或缺的一环,因为它需要协调众多其他模块共同协作,确保能够准确地处理并产生查询的正确输出。让我们来看看。
1、一切从这里开始
postgres.c 中的函数 exec_simple_query()函数 是查询处理阶段的关键环节。我们将重点关注 在调用 PortalStart() 函数之后会发生什么。
2、Portal、Executor 和 ProcessUtility 之间的关系
如上所述,portal 是封装“executor”和“process utility”的对象,其中:
l执行器负责执行计划器创建的“计划”——选择、更新、插入......等
l指令处理器负责处理与计划无关的其他非 DML – 创建、显示、游标...等
它们可以可视化为:
执行器在执行过程中,通常会与表和索引的访问方法紧密协作。这些方法通常访问缓冲区管理器,并最终访问磁盘以执行数据操作。有关访问方法的更多信息,请点击此处。
另一方面,指令处理器必须查看“nodeTag”并决定访问哪个模块才能完成请求。例如:
-
nodeTag=TRANS_STMT_BEGIN – 访问事务管理器以启动事务
-
nodeTag=T_CreateTableSpaceStmt – 访问表空间管理器以创建新的表空间
-
nodeTag=T_TruncateStmt – 访问截断表的访问方法
-
nodeTag=T_CreateRoleStmt – 访问用户管理器以创建新角色
-
.. 还有很多其他的。
3、门户 – 执行器路径
我们知道门户的目标,但具体实现细节则通过一系列复杂的函数调用得以展现。下面的调用堆栈图说明了用于处理不同类型扫描 (SELECT) 的重要函数调用。这将触发门户选择“执行器”路径。
在PostgreSQL的执行阶段,两个核心函数——ExecInitNode和ExecProcNode,其通过它们执行器获取计划器模块创建的计划并将其转换为执行器可以理解的数据结构。最终会创建一个树结构,就像它的计划一样,其中包含类型为execProcNodes的一个主节点和若干个子节点例如,对于并行顺序扫描,主节点的类型为“gather”,而子节点 的类型为“seqScan”。
之所以这样布局,是因为 Gather 节点需要从其所有 seqScan 子节点收集元组数据。请注意,将在 PortalRun 期间创建快照,在获取元组时计算元组的可见性时,需要这样做。有关可见性的更多信息,请点击此处。
4、门户 – 指令处理器路径
指令处理器路径不像执行器部分那么复杂。它不需要基于计划创建 execProcNode。它基本上从正确的模块调用正确的函数来处理不同类型的 NodeTag。
5、总结
执行器和指令处理器共同构成了 PostgreSQL 数据库引擎的核心支柱。几乎每个查询类型都由执行器或指令处理器处理。然而,它们并非孤立工作,而是巧妙地扮演着“调度者”的角色,将适当的任务分配给正确的模块来执行。因此,当您在 PostgreSQL 中引入一个新的自定义模块时,您可能还需要修改执行器/指令处理器。希望此文能够帮助您探索 PostgreSQL 内部机制、深入理解其工作原理。
原文链接:
https://www.highgo.ca/2024/05/17/understand-postgersqls-portal-executor-vs-process-utility/
IvorySQL——一款开源的兼容Oracle的PostgreSQL
官方网址:
https://www.ivorysql.org
社区仓库:
https://github.com/IvorySQL/IvorySQL
IvorySQL社区欢迎并赞赏所有类型的贡献,期待您的加入!
记得在GitHub给我们一个 ⭐奥~