执行器接手优化器/优化器创建的计划,并递归地处理之以抽取所需的行集。这本质上是一种需求拉动的管道机制。每次一个计划节点被调用时,它必须交付一个或多个行,或者报告已经完成了行的交付。
为了提供一个具体例子,假设顶层节点是一个MergeJoin
节点。在归并完成之前,两个行必须先被获取(每一个来自于一个子计划)。因此执行器递归地调用它自己去处理子计划(从附加在lefttree
的子计划开始)。新的顶层节点(左子计划的顶层节点),我们说是一个Sort
节点,并且又要递归来获取一个输入行。Sort
的子节点可以是一个SeqScan
节点,表示真正地读取一个表。该节点的执行将会使执行器从表中获取一行并将它返回给调用节点。Sort
节点将反复调用它的子节点来获得所有需要排序的行。当输入耗尽后(子节点将返回一个NULL来标识),Sort
节点执行排序,并且最后能够返回它的第一个输出行,及排序后的第一个。它会把剩下的行保存下来,这样它可以根据后续的要求按照排好的顺序返回这些行。
MergeJoin
节点也会相似地从其右子计划要求第一个行。然后它会比较两个子节点提供的行看它们是否能被连接,如果可以它会返回一个连接行给调用者。在下一次调用时,或者它无法连接当前的输入对时,它会前进到一个表或另一个表的下一行(取决于比较的结果),并再次检查匹配。最后,某个子计划耗尽,MergeJoin
节点返回NULL表示它没有更多连接行可以提供。
复杂的查询可能涉及多层计划节点,但是一般的方法是相同的:每个节点在被调用时计算并返回它的下一个输出行。每个节点同时也负责应用由优化器分配给它的选择或投影表达式。
执行器机制被用于评估四种基本SQL查询类型:SELECT
, INSERT
,UPDATE
, 和 DELETE
。
对于SELECT
,顶层执行器代码只需要发送查询计划树返回的每个行给客户端。
INSERT ... SELECT
,UPDATE
, 和 DELETE
是在一个被称为ModifyTable
的特殊顶层计划节点下面的有效的SELECT
。
INSERT ... SELECT
把行输送到ModifyTable
来执行插入。
对于UPDATE
,优化器会安排每一个计算行包含所有被更新的列值,加上原始目标行的TID(元组ID或行ID);
这些数据也会被输送到一个ModifyTable
节点,该节点将利用这些信息创建一个新的被更新行并标记旧行为被删除。
对于DELETE
,被计划实际返回的唯一的列是TID,ModifyTable
节点简单地使用TID访问每一个目标行并将其标记为被删除。
一个简单的INSERT ... VALUES
命令会创建一个由一个Result
节点组成的简单计划树,
只计算一个结果行,然后输送到ModifyTable
来执行插入。