查詢轉換方式有很多種:
1、視圖合併(view merge ) 2、子查詢展開( subquery unnesting ) 3、謂詞推入 (predicate pushdown )
1、視圖合併:就是視圖的基表和外部表做連接
創建一個視圖
create view v1 as
select * from emp where deptno = 10;
select *
from v1, dept
where v1.deptno = dept.deptno
and v1.job = 'CLERK';
找到v1的基表emp,做了視圖合併.emp和dept返回的記錄很少,所以走嵌套循環和hash都很正常
不讓他進行視圖合併的方法:
《1》/*+ no_meger(view)*/
《2》查詢塊包含分析函數或聚合函數、集合運算(例如union、intersect、minus),
order by字句或者使用了rownum,視圖合併將會被禁止或者限制。
rownum也會阻止謂詞推入
2、(1)、走子查詢展開:就是where子句後邊有in,not in,exists,not exists,<,<=,>,>=等,CBO認爲對SQL進行等價改寫以後能夠更好的進行優化,等價改寫的過程就是子查詢展開SQL> select ename from emp where deptno in (select deptno from dept where dname like 'S');
執行計劃
----------------------------------------------------------
Plan hash value: 330698451
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 110 | 5 (20)| 00:00:01 |
|* 1 | HASH JOIN SEMI | | 5 | 110 | 5 (20)| 00:00:01 |
| 2 | TABLE ACCESS FULL | EMP | 14 | 126 | 2 (0)| 00:00:01 |
| 3 | VIEW | VW_NSO_1 | 1 | 13 | 2 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL| DEPT | 1 | 12 | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("DEPTNO"="$nso_col_1")
4 - filter("DNAME" LIKE 'S')
統計信息
----------------------------------------------------------
1 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
248 bytes sent via SQL*Net to client
339 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
(2)、加一個Hint禁止走子查詢展開,只要有filter exists一定沒有走子查詢展開,
filter是嵌套表有多少不重複數據就會返回多少條記錄。
SQL> select ename from emp where deptno in (select /*+ no_unnest*/ deptno from dept where dname like 'S');
執行計劃
----------------------------------------------------------
Plan hash value: 1499841400
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 5 | 45 | 8 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 14 | 126 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| DEPT | 1 | 12 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( EXISTS (SELECT /*+ NO_UNNEST */ 0 FROM "DEPT" "DEPT"
WHERE "DEPTNO"=:B1 AND "DNAME" LIKE 'S'))
3 - filter("DEPTNO"=:B1 AND "DNAME" LIKE 'S')
統計信息
----------------------------------------------------------
1 recursive calls
0 db block gets
16 consistent gets
0 physical reads
0 redo size
248 bytes sent via SQL*Net to client
339 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
or是阻止進行子查詢展開的條件。
查詢名字帶S的用戶或者empno>5000的人
(1)、
SQL> select ename from emp where deptno in (select deptno from dept where dname like 'S') or empno >= 5000 ;
執行計劃
----------------------------------------------------------
Plan hash value: 1499841400
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 14 | 182 | 2 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 14 | 182 | 2 (0)| 00:00:01 |
|* 3 | TABLE ACCESS FULL| DEPT | 1 | 12 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMPNO">=5000 OR EXISTS (SELECT 0 FROM "DEPT" "DEPT"
WHERE "DEPTNO"=:B1 AND "DNAME" LIKE 'S'))
3 - filter("DEPTNO"=:B1 AND "DNAME" LIKE 'S')
統計信息
----------------------------------------------------------
1 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
511 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
15 rows processed
(2)、改寫後的SQL語句:
SQL> select ename from emp where deptno in (select deptno from dept where dname like 'S')
2 union all
3 select ename from emp where empno >= 5000 ;
ENAME
--------------------
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
h
已選擇15行。
執行計劃
----------------------------------------------------------
Plan hash value: 527984613
---------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 19 | 250 | 7 (43)| 00:00:01 |
| 1 | UNION-ALL | | | | | |
|* 2 | HASH JOIN SEMI | | 5 | 110 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS FULL | EMP | 14 | 126 | 2 (0)| 00:00:01 |
| 4 | VIEW | VW_NSO_1 | 1 | 13 | 2 (0)| 00:00:01 |
|* 5 | TABLE ACCESS FULL| DEPT | 1 | 12 | 2 (0)| 00:00:01 |
|* 6 | TABLE ACCESS FULL | EMP | 14 | 140 | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPTNO"="$nso_col_1")
5 - filter("DNAME" LIKE 'S')
6 - filter("EMPNO">=5000)
統計信息
----------------------------------------------------------
24 recursive calls
0 db block gets
14 consistent gets
0 physical reads
0 redo size
511 bytes sent via SQL*Net to client
350 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
15 rows processed
3、謂詞推進( predicate pushdown )
不讓他做視圖合併,加一個hint/*+ no_merge(v1) */
select /*+ no_merge(v1) */ *
from v1, dept
where v1.deptno = dept.deptno
and v1.job = 'CLERK';
原本執行計劃應該是,先進行表連接,然後再篩選結果,但是,這裏*4將“DEPTNO"=10 AND "JOB"='CLERK'
這個條件推入到視圖裏,先進行過濾然後進行合併。