执行器接收由规划器/优化器创建的计划,并递归地处理它,以提取所需的行集合。这本质上是一种按需拉取的流水线机制。每当某个计划节点被调用时,它必须再交付一行,或者报告自己已经完成了行的交付。
为了给出一个具体示例,假设顶层节点是一个 MergeJoin 节点。在执行归并之前,必须先取到两行(每个子计划各一行)。因此执行器会递归调用自身去处理这些子计划(从挂接在 lefttree 上的子计划开始)。新的顶层节点,也就是左子计划的顶层节点,假设是一个 Sort 节点,那么又需要通过递归来取得一个输入行。Sort 的子节点可能是一个 SeqScan 节点,它表示真正去读取一个表。执行该节点会使执行器从表中取出一行,并把它返回给调用者节点。Sort 节点会反复调用它的子节点,以取得所有待排序的行。当输入耗尽时(子节点返回的是 NULL 而不是一行),Sort 代码就执行排序,并最终能够返回它的第一条输出行,也就是排序后的第一行。它会把其余行保存起来,以便在后续请求中按排序后的顺序交付这些行。
MergeJoin 节点同样会向它的右子计划请求第一行。然后它比较这两行,看它们是否可以连接;如果可以,就向调用者返回一条连接结果行。在下一次调用时,或者在当前这一对输入无法连接时立即,它会前进到某一个表的下一行或另一个表的下一行(取决于比较结果),并再次检查是否匹配。最终,其中一个子计划会耗尽,MergeJoin 节点就返回 NULL,以表明无法再形成更多连接结果行。
复杂查询可能涉及许多层计划节点,但总体方法是相同的:每个节点在每次被调用时,都会计算并返回它的下一条输出行。每个节点还负责应用规划器分配给它的任何选择或投影表达式。
执行器机制用于求值全部四种基本 SQL 查询类型:SELECT、INSERT、UPDATE 和 DELETE。对于 SELECT,顶层执行器代码只需要把查询计划树返回的每一行发送给客户端。INSERT ... SELECT、UPDATE 和 DELETE 本质上都是 SELECT,位于一个名为 ModifyTable 的特殊顶层计划节点之下。
INSERT ... SELECT 会把各行上传给 ModifyTable 以执行插入。对于 UPDATE,规划器会安排每个计算得到的行包含所有被更新列的值,再加上原始目标行的 TID(tuple ID,即元组 ID 或行 ID);这些数据会被上传给 ModifyTable 节点,该节点利用这些信息创建一个新的更新后行,并将旧行标记为已删除。对于 DELETE,计划实际返回的唯一列就是 TID,而 ModifyTable 节点只需利用该 TID 访问每个目标行并将其标记为已删除。
一个简单的 INSERT ... VALUES 命令会创建一棵极为简单的计划树,它只包含一个 Result 节点。该节点仅计算一条结果行,并将其上传给 ModifyTable 执行插入。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。