一个查询语句在进行完语句和权限检查后,会有一步查询转换的步骤,再到优化器为了决定最终的执行计划计算成本评估。
查询转换的主要目的是确定如果改变查询的写法会不会提供更好的查询计划
如:
select *
from hr.employees
where department_id in (select department_id from hr.departments); --1
可能会被转化为
select t1.*
from hr.employees t1, hr.departments t2
where t1.department_id = t2.department_id; --2
结果集没有改变,但是在优化器看来,转化后的版本执行计划的选择将会更好
几种基本的查询转换如下:
1.视图合并
2.子查询嵌套
3.谓语前推
4.使用物化视图进行查询重写
视图合并
视图合并,顾名思义,就是将原有的内嵌式视图展开为独立分析或者与剩余查询部分合并成总体执行计划的独立查询块的转换。
这句话有点绕,在我理解来,就是将视图还原为表查询,再寻找最合适的执行计划
look:
--语句1
select *
from scott.emp e, (select empno from scott.emp) e_view
where e.empno = e_view.empno;
--我们在视图加入一个提示( /*+ merge*/强制视图合并, /*+ no_merge*/强制视图不合并)来防止语句被重写
--语句2
select *
from scott.emp e,
(select /*+ no_merge*/
empno
from scott.emp) e_view
where e.empno = e_view.empno;
查看执行计划
-- 语句1视图被合并
执行计划
----------------------------------------------------------
Plan hash value: 4089764794
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 1400 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 14 | 1400 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | EMP | 14 | 1218 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN| PK_EMP | 1 | 13 | 0 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."EMPNO"="EMPNO")
-- 语句2视图未合并
执行计划
----------------------------------------------------------
Plan hash value: 1614380175
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 1400 | 6 (17)| 00:00:01|
|* 1 | HASH JOIN | | 14 | 1400 | 6 (17)| 00:00:01|
| 2 | TABLE ACCESS FUL | EMP | 14 | 1218 | 3 (0)| 00:00:01|
| 3 | VIEW | | 14 | 182 | 2 (0)| 00:00:01|
| 4 | INDEX FAST FULL SCAN| PK_EMP | 14 | 182 | 2 (0)| 00:00:01|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("E"."EMPNO"="E_VIEW"."EMPNO")
查询转换的主要目的是确定如果改变查询的写法会不会提供更好的查询计划
如:
select *
from hr.employees
where department_id in (select department_id from hr.departments); --1
可能会被转化为
select t1.*
from hr.employees t1, hr.departments t2
where t1.department_id = t2.department_id; --2
结果集没有改变,但是在优化器看来,转化后的版本执行计划的选择将会更好
几种基本的查询转换如下:
1.视图合并
2.子查询嵌套
3.谓语前推
4.使用物化视图进行查询重写
视图合并
视图合并,顾名思义,就是将原有的内嵌式视图展开为独立分析或者与剩余查询部分合并成总体执行计划的独立查询块的转换。
这句话有点绕,在我理解来,就是将视图还原为表查询,再寻找最合适的执行计划
look:
--语句1
select *
from scott.emp e, (select empno from scott.emp) e_view
where e.empno = e_view.empno;
--我们在视图加入一个提示( /*+ merge*/强制视图合并, /*+ no_merge*/强制视图不合并)来防止语句被重写
--语句2
select *
from scott.emp e,
(select /*+ no_merge*/
empno
from scott.emp) e_view
where e.empno = e_view.empno;
查看执行计划
-- 语句1视图被合并
执行计划
----------------------------------------------------------
Plan hash value: 4089764794
-----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 1400 | 3 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 14 | 1400 | 3 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | EMP | 14 | 1218 | 3 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN| PK_EMP | 1 | 13 | 0 (0)| 00:00:01 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("E"."EMPNO"="EMPNO")
-- 语句2视图未合并
执行计划
----------------------------------------------------------
Plan hash value: 1614380175
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time|
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 1400 | 6 (17)| 00:00:01|
|* 1 | HASH JOIN | | 14 | 1400 | 6 (17)| 00:00:01|
| 2 | TABLE ACCESS FUL | EMP | 14 | 1218 | 3 (0)| 00:00:01|
| 3 | VIEW | | 14 | 182 | 2 (0)| 00:00:01|
| 4 | INDEX FAST FULL SCAN| PK_EMP | 14 | 182 | 2 (0)| 00:00:01|
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("E"."EMPNO"="E_VIEW"."EMPNO")
注意:还有一些情况会阻止视图合并的发生,如果一个查询块包含分析函数,或者聚合函数,集合运算(union/intersect/minus..),order by子句或者用了rownum,视图合并将会被禁止或限制
Oracle Database Performance Tuning Guide>11.1.2.1
The view merging optimization applies to views that contain only selections, projections, and joins. That is, mergeable views do not contain set operators, aggregate functions, DISTINCT , GROUP BY , CONNECT BY , and so on.
Oracle Database Performance Tuning Guide>11.1.2.1
The view merging optimization applies to views that contain only selections, projections, and joins. That is, mergeable views do not contain set operators, aggregate functions, DISTINCT , GROUP BY , CONNECT BY , and so on.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26477854/viewspace-1072251/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/26477854/viewspace-1072251/