8.1.1 视图重写
PostgreSQL有一个模块,称为规则模块,用以处理规则。规则系统把查询修改为需要考虑规则的形式,然后把修改过的查询传递给查询优化器执行。视图被作为规则的子部分,在此被处理。所以,PostgreSQL通过规则模块(pg_rewrite_query函数)支持逻辑查询优化的视图重写,也就是把视图用视图的定义替代,视图定义在SQL中相当于子查询。PostgreSQL统一对子查询进行优化。
PostgreSQL支持简单视图重写和复杂视图的重写,支持对带有简单视图重写后的SQL语句进行优化,但
支持对带有复杂视图重写后的SQL语句做优化。下面我们通过四组针对视图的查询实例进行对比,以帮助读者掌握PostgreSQL对视图重写的支持情况。
首先让我们做一些准备性的工作。
创建表,命令如下:
CREATE TABLE t1 (a1 int UNIQUE, b1 int);
CREATE TABLE t2 (a2 int UNIQUE, b2 int);
CREATE TABLE t3 (a3 int UNIQUE, b3 int);
创建简单视图,命令如下:
CREATE VIEW v_t_1_2 AS SELECT * FROM t1, t2;
创建复杂视图,命令如下:
CREATE VIEW v_t_gd_1_2 AS SELECT DISTINCT t1.b1, t2.b2 FROM t1, t2 GROUP BY t1.b1, t2.b2;
示例1 在简单视图上执行连接操作。
直接用视图和表做连接操作,查询执行计划如下:
test=# EXPLAIN SELECT * FROM t1, v_t_1_2 WHERE t1.a1<20; QUERY PLAN ------------------------------------------------------------------ Nested Loop (cost=0.00..250291.15 rows=20000000 width=24) -> Nested Loop (cost=0.00..273.65 rows=20000 width=16) //两个t1连接后才与t2连接 -> Seq Scan on t1 (cost=0.00..15.00 rows=1000 width=8) //视图中的t1顺序扫描 -> Materialize (cost=0.00..8.70 rows=20 width=8) //FROM子句中的t1索引扫描后物化 -> Index Scan using t1_a1_key on t1 (cost=0.00..8.60 rows=20 width=8) Index Cond: (a1 < 20) -> Materialize (cost=0.00..20.00 rows=1000 width=8) -> Seq Scan on t2 (cost=0.00..15.00 rows=1000 width=8) (8 行记录)
从查询执行计划看,视图v_t_1_2的名称没有出现,而且视图中的t1表和原先的t1表先进行连接,t2表被最后连接,这说明视图被重写,重写后的视图定义部分作为子查询被上拉处理,上拉后的查询语句已经只是三个表(t1、t1、t2)之间进行连接了。
另外,对于条件“a1 < 20”,只在一个t1表被索引扫描时被使用,没有能在t1表被顺序扫描时使用,且t1表被扫描2次,不能有效利用物化的结果,PostgreSQL对于这种情况有待改进。
等价于上一条视图的子查询,没有视图存在,查询执行计划如下:
test=# EXPLAIN SELECT * FROM t1, (SELECT * FROM t1, t2) t12 WHERE t1.a1<20; QUERY PLAN ------------------------------------------------------------------ Nested Loop (cost=0.00..250291.15 rows=20000000 width=24) -> Nested Loop (cost=0.00..273.65 rows=20000 width=16) -> Seq Scan on t1 (cost=0.00..15.00 rows=1000 width=8) -> Materialize (cost=0.00..8.70 rows=20 width=8) -> Index Scan using t1_a1_key on t1 (cost=0.00..8.60 rows=20 width=8) Index Cond: (a1 < 20) -> Materialize (cost=0.00..20.00 rows=1000 width=8) -> Seq Scan on t2 (cost=0.00..15.00 rows=1000 width=8) (8 行记录)
从查询执行计划看,本条子查询语句的查询执行计划与上一条基于视图的查询语句的查询执行计划完全相同,这表明二者是完全等价的,PostgreSQL支持对简单视图的重写。
转载 http://blog.163.com/li_hx/blog/static/1839914132013119112256257/