51.6. Executor

“执行者”采用计划器/优化器创建的计划,并对其进行递归处理以提取所需的行集。这本质上是一种需求拉管道机制。每次调用计划节点时,它都必须再传送一行,或者报告已完成传送行。

为了提供一个具体的示例,假设顶部节点是MergeJoin节点。在进行任何合并之前,必须获取两行(每个子计划中的每一行)。因此,执行者递归地调用自己来处理子计划(它从附加到lefttree的子计划开始)。假设新的顶部节点(左侧子计划的顶部节点)是Sort节点,并且再次需要递归才能获得 Importing 行。 Sort的子节点可能是SeqScan节点,代表表的实际读取。执行此节点会使执行程序从表中获取一行,并将其返回到调用节点。 Sort节点将反复调用其子节点以获得所有要排序的行。当 Importing 耗尽时(如子节点返回 NULL 而不是一行所指示),Sort代码执行排序,最后能够返回其第一输出行,即排序后的第一行。它会保留剩余的行,以便可以响应以后的需求按排序 Sequences 交付它们。

MergeJoin节点类似地要求其右侧子计划中的第一行。然后比较两行,看是否可以合并。如果是这样,它将向其调用方返回一个联接行。在下一次调用时,或者如果它不能加入当前 Importing 对,则立即前进到一个表或另一个表的下一行(取决于比较的结果),并再次检查是否匹配。最终,一个或另一个子计划用尽,并且MergeJoin节点返回 NULL,以指示无法再形成更多的联接行。

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

执行程序机制用于评估所有四种基本 SQL 查询类型:SELECTINSERTUPDATEDELETE。对于SELECT,顶级执行程序代码仅需要将查询计划树返回的每一行发送给 Client 端。对于INSERT,每个返回的行都插入为INSERT指定的目标表中。这是在称为ModifyTable的特殊顶级计划节点中完成的。 (简单的INSERT ... VALUES命令创建了一个简单的计划树,该计划树由单个Result节点组成,该节点仅计算一个结果行,并在其上方的ModifyTable进行插入.但是INSERT ... SELECT可以要求执行程序机制的全部功能.)对于UPDATE,则计划者安排每个计算的行包括所有更新的列值,以及原始目标行的* TID *(TuplesID 或行 ID);此数据被馈送到ModifyTable节点,该节点使用该信息来创建新的更新行并标记旧行已删除。对于DELETE,计划实际返回的唯一列是 TID,而ModifyTable节点仅使用 TID 访问每个目标行并将其标记为已删除。