执行器 采用计划器/优化器创建的计划,并对其进行递归处理以提取所需的行集。这本质上是一种需求拉动管道机制。每次调用计划节点时,它都必须多传递一行,或报告它已完成传递行。
举例来说,假设顶级节点是 MergeJoin
节点。在执行任何合并之前,必须获取两行(每行来自一个子计划)。因此执行器递归调用自身以处理子计划(它从附加到 lefttree
的子计划开始)。新的顶级节点(左侧子计划的顶级节点)是(举例来说) Sort
节点,再次需要递归来获取输入行。 的子节点 可能是一个 SeqScan
节点,它表示对表的实际读取。执行此节点会导致执行器从表中获取一行并将其返回到调用节点。 、 Sort
节点将重复调用其子节点以获取所有要排序的行。当输入耗尽(子节点返回 NULL 而不是行表示输入耗尽)时, Sort
代码执行排序,最终能够返回其第一个输出行,即按排序顺序排列的第一个行。它将剩余的行存储起来,以便可以按照稍后的需求以排序顺序传递它们。
类似地, MergeJoin
节点从其右侧子计划中要求第一行。然后它比较这两行以查看它们是否可以合并;如果可以,它会返回一行合并到其调用者上。在下一个调用中,或者如果它无法合并当前对输入时,它会前进到一张表或另一张表的下一行(取决于比较结果),并且再次检查匹配项。最终,一个子计划或另一个子计划将耗尽,并且 MergeJoin
节点返回 NULL 以指示无法形成更多合并行。
复杂查询可能涉及许多级别的计划节点,但总体方法是相同的:每次调用时,每个节点都会计算并返回其下一个输出行。每个节点还负责应用计划器分配给它的任何选择或投影表达式。
执行器机制用于计算所有五种基本 SQL 查询类型:SELECT
、INSERT
、UPDATE
、DELETE
和 MERGE
。对于 SELECT
,最上层执行器代码只需要发送查询计划树返回的每一行到客户端即可。INSERT ... SELECT
、UPDATE
、DELETE
和 MERGE
实际上是名为 ModifyTable
的特殊最上层计划节点下的 SELECT
。
INSERT ... SELECT
将行馈送到 ModifyTable
进行插入。对于 UPDATE
,规划器安排每行计算包括所有更新的列值以及原始目标行的 TID(元组 ID 或行 ID);将此数据馈送到 ModifyTable
节点,该节点使用这些信息创建新的更新行并将旧行标记为已删除。对于 DELETE
,计划实际返回的唯一列是 TID,且 ModifyTable
节点仅仅使用 TID 访问每个目标行并将它们标记为已删除。对于 MERGE
,规划器联接源关系和目标关系,并且包括任何 WHEN
子句所需的所有列值,以及目标行的 TID;将此数据馈送到 ModifyTable
节点,该节点使用此信息找出要执行的 WHEN
子句,然后根据需要插入、更新或删除目标行。
一个简单的 INSERT ... VALUES
命令创建由单个 Result
节点构成的简单计划树,该节点仅计算一行结果,将其馈送到 ModifyTable
以执行插入。