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等等)