↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

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 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.5 / 6.4
历史版本PostgreSQL 7.1 已于 2006 年 4 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

第 17 章 Postgres 规则系统

作者

由 Jan Wieck 编写。7.1 的更新由 Tom Lane 完成。

产生式规则系统在概念上很简单,但在实际使用时会涉及许多微妙之处。其中一些要点,以及Postgres规则系统的理论基础,可以在 [ Stonebraker et al, ACM, 1990 ] 中找到。

有些其他数据库系统定义了主动型数据库规则。它们通常是存储过程和触发器,在Postgres中以函数和触发器的形式实现。

查询重写规则系统(下文简称“规则系统”)与存储过程和触发器完全不同。它会修改查询,使其将规则纳入考虑,然后把修改后的查询交给查询规划器进行规划和执行。它非常强大,可用于查询语言过程、视图和版本等许多用途。这一规则系统的能力在 [ Ong and Goh, 1990 ] 以及 [ Stonebraker et al, ACM, 1990 ] 中有讨论。

17.1. 什么是查询树? #

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

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

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

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

17.1.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 子句,这里不作关注。规则系统在应用规则时会替换其中的项,但这与规则系统的基本原理关系不大。

提交更正

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