(基于成本的优化器组件)
查询变换器
被解析器解析过的查询语句进入查询变换器,表现出来的是一组查询块(query block),
这些查询块之间是相互关联的或者是嵌套的,查询的形式决定这些查询块相互之间如何被关联。查询变换器的主要目的就是决定改变查询的形式是否有利于产生一个好的执行计划。查询变换器使用四种不同的查询变换技术:
1- 视图合并(View Merging)
2- 谓词推进(Predicate Pushing)
3- 非嵌套子查询(Subquery Unnesting)
4- 物化视图的查询重写(Query Rewrite with Materialized Views)
最终应用于查询的也可以是以上四种变换技术的任意组合。
视图合并
查询中的每个视图都会被解析器扩展到一个独立的查询块中,这个查询块本质上是用来描述视图定义的,是视图的结果。优化器的一个任务就是去分析这个独立视图查询块(view query block)并产生一个视图子计划(subplan),然后优化器在产生整个查询执行计划的同时使用视图子计划来处理剩余的查询部分。由于视图是被独立在整个查询之外被优化的,因此这种技术常常会导致一个不良执行计划的产生。
查询变换器通过将视图查询块合并到查询块中从而消除这种不良执行计划。绝大多数类型的视图是可以被合并的。在一个视图被合并后,它原有的视图查询块被包含到查询块中,也就是说视图查询块不存在了,因此也不再需要产生一个子计划。
SQL> create view v_emp as
2 select a.* ,b.dname ,b.loc from scott.emp a ,scott.dept b
3 where a.deptno = b.deptno
4 and b.deptno =20;
View created.
Elapsed: 00:00:00.13
SQL> set autot traceonly exp
SQL> set linesize 999
SQL> select a.empno from v_emp a where a.empno >1000;
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 2122483104
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 50 | 2 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 5 | 50 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | PK_DEPT | 1 | 3 | 0 (0)| 00:00:01 |
|* 3 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 35 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | PK_EMP | 14 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("B"."DEPTNO"=20)
3 - filter("A"."DEPTNO"=20)
4 - access("A"."EMPNO">1000)
----可以看出上述计划发生了视图合并。关于视图的执行计划和下面的是等价的。
SQL> select a.* ,b.dname,b.loc from scott.emp a,scott.dept b
2 where a.deptno = b.deptno
3 and b.deptno =20
4 and a.empno >1000;
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
Plan hash value: 3257024035
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 285 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 5 | 285 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPT | 1 | 20 | 1 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_DEPT | 1 | | 0 (0)| 00:00:01 |
|* 4 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 185 | 2 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | PK_EMP | 14 | | 1 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("B"."DEPTNO"=20)
4 - filter("A"."DEPTNO"=20)
5 - access("A"."EMPNO">1000)