PostgreSQL7.0手册-程序员手册 -42. Postgres 规则系统
.sl_len, u.un_fact),
float8mul(sh.slmaxlen, un.un_fact))
)
)
AND bpchareq(sh.slunit, un.un_name)
)
AND bpchareq(s.sl_unit, u.un_name);
同样,我们把它归结为一个与最终的规则系统输出等效的真实 SQL 语句:
SELECT sh.shoename, sh.sh_avail,
s.sl_name, s.sl_avail,
min(sh.sh_avail, s.sl_avail) AS total_avail
FROM shoe_data sh, shoelace_data s, unit u, unit un
WHERE min(sh.sh_avail, s.sl_avail) >= 2
AND s.sl_color = sh.slcolor
AND s.sl_len * u.un_fact >= sh.slminlen * un.un_fact
AND s.sl_len * u.un_fact <= sh.slmaxlen * un.un_fact
AND sh.sl_unit = un.un_name
AND s.sl_unit = u.un_name;
递归的处理规则将把一个从视图的 SELECT 改写为一个分析树,这样做等效于如果没有视图存在时 Al 不得不键入的(SQL)命令.
注意: 目前规则系统中没有用于视图规则递归终止机制(只有用于其他规则的).这一点不会造成太大的损害,因为把这个(规则)无限循环(把后端摧毁,直到耗尽内存)的唯一方法是创建表然后手工用 CREATE RULE 命令创建视图规则,这个规则是这样的:一个从其他(表/视图)选择(select)的视图选择(select)了它自身.如果使用了 CREATE VIEW ,这一点是永远不会发生的,因为第二个关系不存在因而第一个视图不能从第二个里面选择(select).
非 SELECT 语句的视图规则
有两个分析树的细节我们在上面的视图规则中没有涉及到.就是命令类型和结果关系.实际上,视图规则不需要这些信息.
一个 SELECT 的分析树和用于其他命令的分析树只有少数几个区别.显然它们有另一个命令类型并且这回结果关系指向生成结果的可排列元素入口.任何其东西都完全是一样的.所以如果有两个表 t1 和 t2 分别有字段 a 和 b ,下面两个语句的分析树
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
UPDATE t1 SET b = t2.b WHERE t1.a = t2.a;
几乎是一样的.
可排列元素包含表 t1 和 t2 的记录.
目标列包含一个指向字段表 t2 的可排列元素 b 的变量.
格表达式比较两个表的字段 a 以寻找相等(行).
结果是,两个分析树生成相似的执行规划.它们都是两个表的联合.对于 UPDATE 语句来说,优化器把 t1 缺失的字段追加到目标列因而最终分析树看起来象
UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
因此执行器在联合上运行的结果和下面语句
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
是完全一样的.但是在 UPDATE 里有点问题.执行器不关心它正在处理的从联合出来的结果的含义是什么.它只是产生一个行的结果集.一个是 SELECT 命令而另一个是 UPDATE 命令的区别是由执行器的调用者控制的.该调用者这时还知道(查看分析树)这是一个 UPDATE,而且它还知道结果要记录到表 t1 里去.但是现有的666行记录中的哪一行要被新行取代呢?被执行的(查询)规划是一个带有资格(条件)的联合,该联合可能以未知顺序生成 0 到 666 间任意数量的行.
要解决这个问题,在 UPDATE 和 DELETE 语句的目标列表里面增加了另外一个入口.当前的记录 ID(ctid).这是一个有着特殊特性的系统字段.它包含行在(存储)块中的(存储)块数和位置信息.在已知表的情况下,ctid 可以通过简单地查找某一数据块在一个 1.5GB 大小的包含成百万条记录的表里面查找某一特定行.在把 ctid 加到目标列表中去以后,最终的结果可以定义为
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
现在,另一个 Postgres 的细节进入到这个阶段里了.这时,表的行还没有被覆盖,这就是为什么 ABORT TRANSACTION 速度快的原因.在一个 UPDATE 里,新的结果行插入到表里(在通过 ctid 查找之后)并且把 ctid 指向的 cmax 和 xmax 入口的行的记录头设置为当前命令计数器和当前交易ID.这样旧的行就被隐藏起来并且在事务提交之后"吸尘器"(vacumm cleaner)就可以真正把它们删除掉.
知道了这些,我们就可以简单的把视图的规则应用到任意命令中.它们(视图和命令)没有区别.
Postgres 里视图的强大能力
上面演示了规则系统如何融合到视图定义的初始分析树中去.在第二个例子里,一个简单的对视图的 SELECT 创建了一个4个表联合的分析树(unit 以不同的名称用了两次).
益处
在规则系统里实现视图的好处是优化器在一个分析树里拥有所有信息:应该扫描哪个表 + 表之间的关系 + 视图的资格限制 + 初始查询的资格(条件).并且依然是在最初的查询已经是一个视图的联合的情况下.现在优化器必须决定执行查询的最优路径.优化器拥有越多信息,它的决策就越好.并且 Postgres 里的规则系统的实现保证这些信息是目前能获得的所有信息.
考虑
很长一段时间里,Postgres 规则系统被认为是有问题的.规则的使用是不被推荐的而且能工作的部分只有视图规则.而且这些视图规则还常常犯毛病,因为规则系统不能在除 SELECT 语句外的语句里应用它们(例如用从一个视图来的数据 UPDATE 就不能工作).
在那段时间里,开发工作继续进行,许多新特性加入到分析器和优化器里.规则系统的功能越来越陈旧而且越来越难以修复它们.
从 6.4 起,某个人(译注:感谢 Jan )关起门,深吸一口气把所有这些烂东西彻底修理了一便.结果就是本章描述的规则系统.但是还有一些无法处理的构造和一些失效的地方,主要原因是这些东西现在不被 Postgres 查询优化器支持.
带聚集字段的视图有很大问题.在资格列里的聚集表达式必须通过子查询使
float8mul(sh.slmaxlen, un.un_fact))
)
)
AND bpchareq(sh.slunit, un.un_name)
)
AND bpchareq(s.sl_unit, u.un_name);
同样,我们把它归结为一个与最终的规则系统输出等效的真实 SQL 语句:
SELECT sh.shoename, sh.sh_avail,
s.sl_name, s.sl_avail,
min(sh.sh_avail, s.sl_avail) AS total_avail
FROM shoe_data sh, shoelace_data s, unit u, unit un
WHERE min(sh.sh_avail, s.sl_avail) >= 2
AND s.sl_color = sh.slcolor
AND s.sl_len * u.un_fact >= sh.slminlen * un.un_fact
AND s.sl_len * u.un_fact <= sh.slmaxlen * un.un_fact
AND sh.sl_unit = un.un_name
AND s.sl_unit = u.un_name;
递归的处理规则将把一个从视图的 SELECT 改写为一个分析树,这样做等效于如果没有视图存在时 Al 不得不键入的(SQL)命令.
注意: 目前规则系统中没有用于视图规则递归终止机制(只有用于其他规则的).这一点不会造成太大的损害,因为把这个(规则)无限循环(把后端摧毁,直到耗尽内存)的唯一方法是创建表然后手工用 CREATE RULE 命令创建视图规则,这个规则是这样的:一个从其他(表/视图)选择(select)的视图选择(select)了它自身.如果使用了 CREATE VIEW ,这一点是永远不会发生的,因为第二个关系不存在因而第一个视图不能从第二个里面选择(select).
非 SELECT 语句的视图规则
有两个分析树的细节我们在上面的视图规则中没有涉及到.就是命令类型和结果关系.实际上,视图规则不需要这些信息.
一个 SELECT 的分析树和用于其他命令的分析树只有少数几个区别.显然它们有另一个命令类型并且这回结果关系指向生成结果的可排列元素入口.任何其东西都完全是一样的.所以如果有两个表 t1 和 t2 分别有字段 a 和 b ,下面两个语句的分析树
SELECT t2.b FROM t1, t2 WHERE t1.a = t2.a;
UPDATE t1 SET b = t2.b WHERE t1.a = t2.a;
几乎是一样的.
可排列元素包含表 t1 和 t2 的记录.
目标列包含一个指向字段表 t2 的可排列元素 b 的变量.
格表达式比较两个表的字段 a 以寻找相等(行).
结果是,两个分析树生成相似的执行规划.它们都是两个表的联合.对于 UPDATE 语句来说,优化器把 t1 缺失的字段追加到目标列因而最终分析树看起来象
UPDATE t1 SET a = t1.a, b = t2.b WHERE t1.a = t2.a;
因此执行器在联合上运行的结果和下面语句
SELECT t1.a, t2.b FROM t1, t2 WHERE t1.a = t2.a;
是完全一样的.但是在 UPDATE 里有点问题.执行器不关心它正在处理的从联合出来的结果的含义是什么.它只是产生一个行的结果集.一个是 SELECT 命令而另一个是 UPDATE 命令的区别是由执行器的调用者控制的.该调用者这时还知道(查看分析树)这是一个 UPDATE,而且它还知道结果要记录到表 t1 里去.但是现有的666行记录中的哪一行要被新行取代呢?被执行的(查询)规划是一个带有资格(条件)的联合,该联合可能以未知顺序生成 0 到 666 间任意数量的行.
要解决这个问题,在 UPDATE 和 DELETE 语句的目标列表里面增加了另外一个入口.当前的记录 ID(ctid).这是一个有着特殊特性的系统字段.它包含行在(存储)块中的(存储)块数和位置信息.在已知表的情况下,ctid 可以通过简单地查找某一数据块在一个 1.5GB 大小的包含成百万条记录的表里面查找某一特定行.在把 ctid 加到目标列表中去以后,最终的结果可以定义为
SELECT t1.a, t2.b, t1.ctid FROM t1, t2 WHERE t1.a = t2.a;
现在,另一个 Postgres 的细节进入到这个阶段里了.这时,表的行还没有被覆盖,这就是为什么 ABORT TRANSACTION 速度快的原因.在一个 UPDATE 里,新的结果行插入到表里(在通过 ctid 查找之后)并且把 ctid 指向的 cmax 和 xmax 入口的行的记录头设置为当前命令计数器和当前交易ID.这样旧的行就被隐藏起来并且在事务提交之后"吸尘器"(vacumm cleaner)就可以真正把它们删除掉.
知道了这些,我们就可以简单的把视图的规则应用到任意命令中.它们(视图和命令)没有区别.
Postgres 里视图的强大能力
上面演示了规则系统如何融合到视图定义的初始分析树中去.在第二个例子里,一个简单的对视图的 SELECT 创建了一个4个表联合的分析树(unit 以不同的名称用了两次).
益处
在规则系统里实现视图的好处是优化器在一个分析树里拥有所有信息:应该扫描哪个表 + 表之间的关系 + 视图的资格限制 + 初始查询的资格(条件).并且依然是在最初的查询已经是一个视图的联合的情况下.现在优化器必须决定执行查询的最优路径.优化器拥有越多信息,它的决策就越好.并且 Postgres 里的规则系统的实现保证这些信息是目前能获得的所有信息.
考虑
很长一段时间里,Postgres 规则系统被认为是有问题的.规则的使用是不被推荐的而且能工作的部分只有视图规则.而且这些视图规则还常常犯毛病,因为规则系统不能在除 SELECT 语句外的语句里应用它们(例如用从一个视图来的数据 UPDATE 就不能工作).
在那段时间里,开发工作继续进行,许多新特性加入到分析器和优化器里.规则系统的功能越来越陈旧而且越来越难以修复它们.
从 6.4 起,某个人(译注:感谢 Jan )关起门,深吸一口气把所有这些烂东西彻底修理了一便.结果就是本章描述的规则系统.但是还有一些无法处理的构造和一些失效的地方,主要原因是这些东西现在不被 Postgres 查询优化器支持.
带聚集字段的视图有很大问题.在资格列里的聚集表达式必须通过子查询使
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] 下一页

