2025年9月25日: PostgreSQL 18 发布!
支持的版本: 当前 (18) / 17 / 16 / 15 / 14 / 13
开发版本: devel
不支持的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

51.6. 执行器 #

执行器 接收由规划器/优化器创建的计划,并递归地处理它以提取所需的行集。这本质上是一个需求拉动的管道机制。每次调用一个计划节点时,它必须再提供一行,或者报告它已完成提供行。

为了提供一个具体的例子,假设顶层节点是一个 MergeJoin 节点。在执行任何合并之前,必须获取两行(每行来自一个子计划)。因此,执行器递归地调用自身来处理子计划(它从附加到 lefttree 的子计划开始)。新的顶层节点(左子计划的顶层节点),比如说,是一个 Sort 节点,并且再次需要递归来获取输入行。 Sort 的子节点可能是一个 SeqScan 节点,代表实际读取一个表。执行此节点会导致执行器从表中获取一行,并将其返回给调用节点。 Sort 节点将反复调用其子节点来获取要排序的所有行。当输入耗尽时(由子节点返回 NULL 而不是行来指示), Sort 代码执行排序,并最终能够返回其第一行输出,即按排序顺序排列的第一行。它会将剩余的行存储起来,以便能够响应后续的需求以排序顺序提供它们。

MergeJoin 节点类似地请求其右子计划的第一行。然后它比较这两行以确定它们是否可以连接;如果可以,它将连接行返回给其调用者。在下一次调用时,或者如果它无法连接当前输入对,它会推进一个表或另一个表的下一行(取决于比较结果),并再次检查匹配。最终,其中一个子计划或另一个子计划耗尽, MergeJoin 节点返回 NULL,表示无法形成更多连接行。

复杂的查询可能涉及多个级别的计划节点,但总体方法是相同的:每个节点在每次被调用时都会计算并返回其下一行输出。每个节点还负责应用规划器分配给它的任何选择或投影表达式。

执行器机制用于评估所有五种基本 SQL 查询类型: SELECTINSERTUPDATEDELETEMERGE。对于 SELECT,顶层执行器代码只需要将查询计划树返回的每一行发送给客户端。 INSERT ... SELECTUPDATEDELETEMERGE 实际上是 SELECT 的变体,它们有一个特殊的顶层计划节点 ModifyTable

INSERT ... SELECT 将行馈送到 ModifyTable 进行插入。对于 UPDATE,规划器安排计算出的每一行都包含所有更新的列值,以及原始目标行的 TID(元组 ID,或行 ID);此数据被馈送到 ModifyTable 节点,该节点使用该信息创建一条新的更新行并将旧行标记为已删除。对于 DELETE,计划中实际返回的唯一列是 TID, ModifyTable 节点仅使用 TID 来访问每一目标行并将其标记为已删除。对于 MERGE,规划器连接源和目标关系,并包含任何 WHEN 子句所需的全部列值,以及目标行的 TID;此数据被馈送到 ModifyTable 节点,该节点使用这些信息来确定执行哪个 WHEN 子句,然后根据需要插入、更新或删除目标行。

一个简单的 INSERT ... VALUES 命令会创建一个简单的计划树,由一个 Result 节点组成,该节点仅计算一行结果,然后将其馈送到 ModifyTable 以执行插入。

提交更正

如果您在本应正确的内容中发现任何不正确之处、与您对特定功能的实际体验不符之处,或需要进一步澄清之处,请使用 此表单 报告文档问题。