选择 打开 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0
历史版本PostgreSQL 9.2 已于 2017 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本

44.6. 执行器 #

执行器接收由规划器/优化器创建的计划,并递归地处理它,以提取所需的行集合。这本质上是一种按需拉取的流水线机制。每当某个计划节点被调用时,它必须再交付一行,或者报告自己已经完成了行的交付。

为了给出一个具体示例,假设顶层节点是一个 MergeJoin 节点。在执行归并之前,必须先取到两行(每个子计划各一行)。因此执行器会递归调用自身去处理这些子计划(从挂接在 lefttree 上的子计划开始)。新的顶层节点,也就是左子计划的顶层节点,假设是一个 Sort 节点,那么又需要通过递归来取得一个输入行。Sort 的子节点可能是一个 SeqScan 节点,它表示真正去读取一个表。执行该节点会使执行器从表中取出一行,并把它返回给调用者节点。Sort 节点会反复调用它的子节点,以取得所有待排序的行。当输入耗尽时(子节点返回的是 NULL 而不是一行),Sort 代码就执行排序,并最终能够返回它的第一条输出行,也就是排序后的第一行。它会把其余行保存起来,以便在后续请求中按排序后的顺序交付这些行。

MergeJoin 节点同样会向它的右子计划请求第一行。然后它比较这两行,看它们是否可以连接;如果可以,就向调用者返回一条连接结果行。在下一次调用时,或者在当前这一对输入无法连接时立即,它会前进到某一个表的下一行或另一个表的下一行(取决于比较结果),并再次检查是否匹配。最终,其中一个子计划会耗尽,MergeJoin 节点就返回 NULL,以表明无法再形成更多连接结果行。

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

执行器机制用于求值全部四种基本 SQL 查询类型:SELECTINSERTUPDATEDELETE。对于 SELECT,顶层执行器代码只需要把查询计划树返回的每一行发送给客户端。对于 INSERT,每个返回的行会被插入到为该 INSERT 指定的目标表中。这项工作是在一个名为 ModifyTable 的特殊顶层计划节点中完成的。(一个简单的 INSERT ... VALUES 命令会创建一棵极为简单的计划树,它只包含一个计算单条结果行的 Result 节点,以及位于其上执行插入的 ModifyTable。但 INSERT ... SELECT 可能需要执行器机制的全部能力。)对于 UPDATE,规划器会安排每个计算得到的行包含所有被更新列的值,再加上原始目标行的 TID(tuple ID,即元组 ID 或行 ID);这些数据会被送入 ModifyTable 节点,该节点利用这些信息创建一个新的更新后行,并将旧行标记为已删除。对于 DELETE,计划实际返回的唯一列就是 TID,而 ModifyTable 节点只需利用该 TID 访问每个目标行并将其标记为已删除。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。