Postgresql 中文操作指南

41.1. The Query Tree #

要了解规则系统的工作原理,有必要了解何时调用它以及它的输入和结果是什么。

规则系统位于解析器和规划器之间。它获取解析器的一个输出,即一个查询树和用户定义的重写规则,这些重写规则也是带有一些附加信息来查询树,并创建 0 个或多个查询树作为结果。因此,它的输入和输出始终都是解析器本身可以生成的东西,因此它看到的任何东西基本上都可以表示为 SQL 语句。

那么,什么是查询树?它是 SQL 语句的内部表示形式,其中构建它的各个部分都单独存储。如果你设置配置参数 debug_print_parsedebug_print_rewrittendebug_print_plan,则可以在服务器日志中显示这些查询树。规则操作也存储为查询树,位于系统目录 pg_rewrite 中。它们不会格式化为日志输出,但它们包含完全相同的信息。

读取原始查询树需要一些经验。但由于查询树的 SQL 表示足以理解规则系统,因此本章不会教授如何阅读它们。

在本章中读取查询树的 SQL 表示时,必须能够识别在查询树结构中时分割语句的各个部分。查询树的各个部分是

  • the command type

    • 这是一个简单值,指示哪个命令 (SELECTINSERTUPDATEDELETE) 生成了查询树。

  • the range table

    • 范围表是查询中使用的关系列表。在 SELECT 语句中,这些是 FROM 关键字之后给出的关系。

    • 每个范围表条目标识一个表或视图,并通过在查询的其他部分中调用的名称告诉它。在查询树中,范围表条目由数字而不是名称引用,因此这里即使存在与 SQL 语句中相同的名称也没有关系。这可以在合并规则的范围表之后发生。本章中的示例不会出现这种情况。

  • the result relation

    • 这是对范围表的索引,用于标识查询结果转到何处的关系。

    • SELECT 查询没有结果关联。( SELECT INTO 的特殊情况与 CREATE TABLE 后跟 INSERT …​ SELECT 基本相同,这里未单独讨论。)

    • 对于 INSERTUPDATEDELETE 命令,结果关系是更改生效的表(或视图!)。

  • the target list

    • 目标列表是一个定义查询结果的表达式列表。对于 SELECT,这些表达式是构建查询最终输出的表达式。它们对应于关键字 SELECTFROM 之间的表达式。(* 只是关系所有列名称的缩写。它被解析器展开为各个列,因此规则系统永远看不到它。)

    • DELETE 命令不需要正常的目标列表,因为它们不产生任何结果。相反,规划器会将一个特殊的 CTID 条目添加到空目标列表中,以允许执行器找到要删除的行。(当结果关联是一个普通表时,添加 CTID。如果它是一个视图,则由规则系统添加一个整行变量,如 Section 41.2.4 中所述。)

    • 对于 INSERT 命令,目标列表描述了应进入结果关系的新行。它由 VALUES 子句中的表达式或 INSERT …​ SELECTSELECT 子句中的表达式组成。重写过程的第一步为原始命令未分配但具有默认值的任何列添加目标列表条目。规划器将用常数空表达式填充所有剩余的列(既没有给定值也没有默认值)。

    • 对于 UPDATE 命令,目标列表描述应该替换旧行的新行。在规则系统中,它只包含来自命令的 SET column = expression 部分的表达式。规划器将通过插入将值从旧行复制到新行的表达式来处理缺失的列。就像 DELETE 一样,添加了一个 CTID 或整个行变量,以便执行器可以识别要更新的旧行。

    • 目标列表中的每个条目都包含一个表达式,该表达式可以是常量值、指向范围表中某个关系的列的变量、参数或由函数调用、常量、变量、运算符等组成的表达式树。

  • the qualification

    • 查询的限定条件是一个表达式,与目标列表条目中包含的表达式非常相似。该表达式的结果值是一个布尔值,它指示最终结果行的操作 ( INSERTUPDATEDELETESELECT )是否应执行。它对应于 SQL 语句的 WHERE 子句。

  • the join tree

    • 查询的连接树显示 FROM 子句的结构。对于像 SELECT …​ FROM a, b, c 这样的简单查询,连接树只是 FROM 项的列表,因为我们允许按任何顺序连接它们。但是,当使用 JOIN 表达式(特别是外连接)时,我们必须按照连接显示的顺序进行连接。在那种情况下,连接树显示 JOIN 表达式的结构。与特定 JOIN 子句相关联的限制(来自 ONUSING 表达式)被存储为附加到那些连接树节点的限定表达式。事实证明,将顶级 WHERE 表达式存储为附加到顶级连接树项的限定条件也很方便。因此,连接树实际上同时表示 SELECTFROMWHERE 子句。

  • the others

    • 查询树的其他部分,例如 ORDER BY 子句,此处无关紧要。规则系统在应用规则时会用一些条目替换其中的条目,但这与规则系统 的基本原则关系不大。