↑↓ 选择↵ 打开⌫ 切换范围完整搜索

PG.CENTER 连接 PostgreSQL 文档、百科与生态知识。由 Pigsty 维护。

支持中的版本: 当前版本 (18) / 17 / 16
开发中的版本: 19 / 20devel
已结束支持的版本: 7.3 / 7.2
历史版本。 PostgreSQL 7.3 已结束支持。 请参阅 当前版本手册.

13.2. 什么是查询树? #

要理解规则系统如何工作,必须先知道它在何时被调用,以及它的输入和输出是什么。

规则系统位于查询解析器和规划器之间。它接收解析器的输出,即一棵查询树,以及来自 pg_rewrite 目录的重写规则;这些规则本身也是带有一些附加信息的查询树。它会生成零棵或多棵查询树作为结果。因此,它的输入和输出始终都是解析器本身也可能产生的东西,所以它看到的任何内容基本上都可以表示为一个SQL语句。

那么什么是查询树?它是SQL语句的一种内部表示,其中构成语句的各个部分被分别存储。如果以调试级别 4 启动 PostgreSQL 后端,并在交互式后端界面中输入查询,就可以看到这些查询树。pg_rewrite 系统目录中的规则动作同样以查询树的形式存储。它们的格式与调试输出不同,但包含的却是完全相同的信息。

阅读查询树需要一些经验,我刚开始在规则系统上工作时也经历了一段艰难的时光。我记得我曾站在咖啡机前,看到目标列表里有一个杯子,范围表里有水和咖啡粉,而所有的按钮出现在一个条件表达式中。由于查询树的SQL表示已足以理解规则系统,本文不会讲解如何阅读它们。学习阅读查询树也许会有帮助,而且在后续的描述中需要用到这些命名约定。

13.2.1. 查询树的组成部分

在阅读本文中查询树的 SQL 表示时,需要能够辨认语句在查询树结构中被拆分成了哪些部分。查询树的组成部分是

命令类型

这是一个简单的值,说明了是哪一种命令(SELECT、INSERT、UPDATE、DELETE)产生了解析树。

范围表

范围表是查询中使用的关系列表。在 SELECT 语句中,它们就是 FROM 关键字后面给出的关系。

每个范围表项标识一个表或视图,并说明在查询的其他部分以哪个名称来称呼它。在查询树中,范围表项是按编号而不是按名称引用的,因此即使像 SQL 语句中那样出现重名,这里也无关紧要。这种情况可能出现在规则的范围表被合并之后。本文中的示例不会涉及这种情形。

结果关系

这是范围表中的一个索引,用来标识查询结果应写入哪个关系。

SELECT 查询通常没有结果关系。SELECT INTO 这一特殊情况与 CREATE TABLE、INSERT ... SELECT 序列几乎相同,这里不再单独讨论。

在 INSERT、UPDATE 和 DELETE 查询中,结果关系就是要让修改生效的表(或视图!)。

目标列表

目标列表是定义查询结果的表达式列表。对于 SELECT,这些表达式构成查询的最终输出。它们对应于关键字 SELECT 和 FROM 之间的表达式。(* 只是某个关系全部属性名的缩写。解析器会把它展开为各个独立属性,因此规则系统永远不会看到它。)

DELETE 查询不需要目标列表,因为它们不产生任何结果。实际上,规划器会向空目标列表加入一个特殊的 CTID 项,但这发生在规则系统之后,将在后面讨论;对规则系统而言,目标列表是空的。

在 INSERT 查询中,目标列表描述的是将要进入结果关系的新行。它由 VALUES 子句中的表达式,或 INSERT ... SELECT 里 SELECT 子句中的表达式组成。重写过程的第一步会为原始查询未赋值但带有默认值的列补上目标列表项。其余列(既没有给定值也没有默认值)将由规划器填入常量空值表达式。

在 UPDATE 查询中,目标列表描述要替换旧行的新行。在规则系统中,它只包含查询中 SET attribute = expression 部分的表达式。规划器会通过插入把旧行值复制到新行的表达式来处理缺失列。与 DELETE 一样,它也会加入一个特殊的 CTID 项。

目标列表中的每一项都包含一个表达式,它可以是常量值、指向范围表中某个关系属性的变量、一个参数,或者由函数调用、常量、变量、操作符等构成的表达式树。

条件

查询的条件是一个表达式,与目标列表项中的表达式很相似。该表达式的结果值是布尔值,用来说明是否应对最终结果行执行相应操作(INSERT、UPDATE、DELETE 或 SELECT)。它就是 SQL 语句的 WHERE 子句。

连接树

查询的连接树显示了 FROM 子句的结构。对于 SELECT FROM a, b, c 这样的简单查询,连接树只是 FROM 项的一个列表,因为允许按任意顺序连接它们。但当使用 JOIN 表达式(特别是外连接)时,就必须按连接所显示的顺序进行连接。连接树展示的是 JOIN 表达式的结构。与特定 JOIN 子句相关的限制(来自 ON 或 USING 表达式)会作为条件表达式附着在相应的连接树节点上。把顶层 WHERE 表达式也存储为附着在顶层连接树项上的一个条件,会很方便。因此,连接树实际上同时表示 SELECT 的 FROM 和 WHERE 子句。

其他

查询树的其他部分,如 ORDER BY 子句,这里不作关注。规则系统在应用规则时会替换其中的项,但这与规则系统的基本原理关系不大。

报告文档问题

阅读 上游文档. 反馈更正前请先核对 当前版本手册.