21 视图合并(view merge) --优化主题系列
视图合并(viewmerge)
当SQL语句中有内联视图(in-lineview,内联视图就是在from后面有select子查询)
或者SQL语句中有用 createview...创建的视图,CBO会将内联视图/视图给展开,进行等价的改写,这个过程就叫做视图合并。如果没有发生视图合并,在执行计划中,我们可以看到VIEW关键字。
select * from (select ... from x) a,b where a.id=b.id;a就是内联视图
下面举个例子(基于SYSOracle11gR2):
有下面的SQL,其实这个SQL来自于我同事,他请求我优化:
SELECT to_char(wmsys.wm_concat(a.TABLE_NAME))
FROM user_tables a, dba_objects b
WHERE a.TABLE_NAME = b.OBJECT_NAME
AND b.OWNER = 'HBTELEPS'
ANDB.OBJECT_TYPE = 'TABLE';
user_tables 是不是被展开了??被展开了就叫视图合并
现在我们用HINTNO_MERGE 禁止USER_TABLES 进行视图合并
SELECT /*+ no_merge(a) */ to_char(wmsys.wm_concat(a.TABLE_NAME))
FROM user_tables a, dba_objects b
WHERE a.TABLE_NAME = b.OBJECT_NAME
AND b.OWNER = 'HBTELEPS'
AND B.OBJECT_TYPE = 'TABLE';
conn scott/tiger
create or replace view emp1 as select ename,job,deptno from empwhere sal>(select avg(sal) from emp);
select ename,job,dname,loc from emp1,dept whereemp1.deptno=dept.deptno;
没有VIEW关键字并且视图的名字也不见了就视图合并了
create or replace view emp1 as select ename,job,deptno from empwhere sal>(select avg(sal) from emp);
select ename,job,dname,loc from emp1,dept whereemp1.deptno=dept.deptno;
select ename, job, dname, loc
from (select ename, job, deptno
from emp
where sal >(select avg(sal) from emp)) emp1,
dept
where emp1.deptno = dept.deptno;
为什么可以进行视图合并??数学公式的等价转换
我很反对用大量的VIEW用了VIEW会出现性能问题
为什么 CBO要进行VIEWMERGE呢??
CBO认为把视图展开了能更好的进一步优化
因为如果不进行视图合并,那么这个视图就会当成一整块,在SQL执行过程中,这个视图就会被当成一个结果集,然后再去和别的表/结果集关联。如果进行了视图合并,那么这个视图就不会当成一整块了,它会被拆散,分开的执行。CBO通常情况下认为视图进行合并之后,性能较高,所以一般情况下都会发生视图合并。但是并不是每次进行了视图合并性能就高,所以我们在进行SQL优化的时候要特别留意视图合并。
请特别注意:当子查询/视图里面有
1.子查询有ROWNUM
2.子查询有CUBE,ROLLUP
3.子查询有UNION, UNION ALL
4. START WITH ,CONNECT BY
优化器可能就不会发生subqueryunnesting/view merge
这个时候就要改写SQL(比如把exists改写为in,notexists 改写为notin等等)