-- 뷰 생성
create or replace view emp_salesman
as
select empno, ename, job, mgr, hiredate, sal, comm, deptno
from emp
where job = 'SALESMAN';
-- 단순 뷰와 조인
select e.empno, e.ename, e.job, e.mgr, e.sal, d.dname
from emp_salesman e, dept d
where d.deptno = e.deptno
and e.sal >= 1500
;
-- 뷰 Merging 하지 않고 그대로 최적화시 실행계획
SQL> explain plan for
2 select /*+ no_merge */
3 e.empno, e.ename, e.job, e.mgr, e.sal, d.dname
4 from emp_salesman e, dept d
5 where d.deptno = e.deptno
6 and e.sal >= 1500
7 ;
해석되었습니다.
경 과: 00:00:00.00
SQL> @plan
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------
Plan hash value: 3251065420
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 84 | 4 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | | | | |
| 2 | NESTED LOOPS | | 2 | 84 | 4 (0)| 00:00:01 |
|* 3 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 58 | 2 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMP_SAL_IDX | 8 | | 1 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | DEPT_DEPTNO_IDX | 1 | | 0 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID | DEPT | 1 | 13 | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - filter("JOB"='SALESMAN')
4 - access("SAL">=1500)
5 - access("D"."DEPTNO"="DEPTNO")
20 개의 행이 선택되었습니다.
-- 뷰 Merging 작동시 변환된 쿼리 모습 예상
select e.empno, e.ename, e.job, e.mgr, e.sal, d.dname
from emp e, dept d
where d.deptno = e.deptno
and e.job = 'SALESMAN'
and e.sal >= 1500
8i | 기본값이 false. 복합 뷰 Merging 원할 때는 merge 힌트 사용해야 됨. |
9i | 기본값이 true. 동일 결과 보장시 항상 복합 뷰 Merging이 일어남. |
10g | 일단 복합 뷰 Merging 시도. 원본 쿼리 비용도 같이 계산해서 Merging 했을 때의 비용이 더 낮을 때만 변환. 비용기반 쿼리 변환. |
-- 복합 뷰를 포함한 쿼리 - 뷰 Merging 함
SQL> explain plan for
2 select d.dname, avg_sal_dept
3 from dept d
4 ,(select /*+ merge */ deptno, avg(sal) avg_sal_dept
5 from emp
6 group by deptno) e
7 where d.deptno = e.deptno
8 and d.loc = 'CHICAGO'
9 ;
해석되었습니다.
경 과: 00:00:00.12
SQL> @plan
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------
Plan hash value: 1182506179
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 81 | 5 (20)| 00:00:01 |
| 1 | HASH GROUP BY | | 3 | 81 | 5 (20)| 00:00:01 |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 5 | 135 | 4 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | DEPT | 1 | 20 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | EMP_IDX | 5 | | 0 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 35 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - filter("D"."LOC"='CHICAGO')
5 - access("D"."DEPTNO"="DEPTNO")
-- 뷰 Merging 하면 아래와 같은 형태가 됨. 실행계획이 같음을 볼 수 있음.
select d.dname, avg(sal)
from dept d, emp e
where d.deptno = e.deptno
and d.loc = 'CHICAGO'
group by d.rowid, d.dname
;
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 27 | 5 (20)| 00:00:01 |
| 1 | HASH GROUP BY | | 1 | 27 | 5 (20)| 00:00:01 |
| 2 | NESTED LOOPS | | | | | |
| 3 | NESTED LOOPS | | 5 | 135 | 4 (0)| 00:00:01 |
|* 4 | TABLE ACCESS FULL | DEPT | 1 | 20 | 3 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | EMP_IDX | 5 | | 0 (0)| 00:00:01 |
| 6 | TABLE ACCESS BY INDEX ROWID| EMP | 5 | 35 | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
-- 뷰 Merge 되었을 때 SQL 트레이스
select /*+ leading(e) use_nl(d) */
*
from dept d
,(select * from emp) e
where e.deptno = d.deptno
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 14 0 14
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 14 0 14
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 91
Rows Row Source Operation
------- ---------------------------------------------------
14 NESTED LOOPS (cr=14 pr=0 pw=0 time=0 us)
14 NESTED LOOPS (cr=12 pr=0 pw=0 time=32 us cost=17 size=798 card=14)
14 TABLE ACCESS FULL EMP (cr=8 pr=0 pw=0 time=6 us cost=3 size=518 card=14)
14 INDEX RANGE SCAN DEPT_DEPTNO_IDX (cr=4 pr=0 pw=0 time=0 us cost=0 size=0 card=1)(object id 91722)
14 TABLE ACCESS BY INDEX ROWID DEPT (cr=2 pr=0 pw=0 time=0 us cost=1 size=20 card=1)
-- no_merge 힌트 사용했을 때 SQL 트레이스
select /*+ leading(e) use_nl(d) */
*
from dept d
,(select /*+ NO_MERGE */ * from emp) e
where e.deptno = d.deptno
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 14 0 14
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 14 0 14
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 91
Rows Row Source Operation
------- ---------------------------------------------------
14 NESTED LOOPS (cr=14 pr=0 pw=0 time=0 us)
14 NESTED LOOPS (cr=12 pr=0 pw=0 time=39 us cost=17 size=1498 card=14)
14 VIEW (cr=8 pr=0 pw=0 time=8 us cost=3 size=1218 card=14)
14 TABLE ACCESS FULL EMP (cr=8 pr=0 pw=0 time=5 us cost=3 size=518 card=14)
14 INDEX RANGE SCAN DEPT_DEPTNO_IDX (cr=4 pr=0 pw=0 time=0 us cost=0 size=0 card=1)(object id 91722)
14 TABLE ACCESS BY INDEX ROWID DEPT (cr=2 pr=0 pw=0 time=0 us cost=1 size=20 card=1)
-- 뷰가 NL 조인에서 Inner 테이블로 액세스될 때
select /*+ leading(d) use_nl(e) */
*
from dept d
,(select /*+ NO_MERGE */ * from emp) e
where e.deptno = d.deptno
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.02 4 37 0 14
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.02 4 37 0 14
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 91
Rows Row Source Operation
------- ---------------------------------------------------
14 NESTED LOOPS (cr=37 pr=4 pw=4 time=0 us cost=15 size=1498 card=14)
4 TABLE ACCESS FULL DEPT (cr=8 pr=4 pw=4 time=3 us cost=3 size=80 card=4)
14 VIEW (cr=29 pr=0 pw=0 time=3 us cost=3 size=348 card=4)
56 TABLE ACCESS FULL EMP (cr=29 pr=0 pw=0 time=2 us cost=3 size=518 card=14)
-- 인라인 뷰에 order by 절을 추가
select /*+ leading(d) use_nl(e) */
*
from dept d
,(select /*+ NO_MERGE */ * from emp ORDER BY ENAME) e
where e.deptno = d.deptno
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 2 0.00 0.00 0 15 0 14
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 0.00 0.00 0 15 0 14
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 91
Rows Row Source Operation
------- ---------------------------------------------------
14 NESTED LOOPS (cr=15 pr=0 pw=0 time=0 us cost=19 size=1498 card=14)
4 TABLE ACCESS FULL DEPT (cr=8 pr=0 pw=0 time=10 us cost=3 size=80 card=4)
14 VIEW (cr=7 pr=0 pw=0 time=2 us cost=4 size=348 card=4)
56 SORT ORDER BY (cr=7 pr=0 pw=0 time=2 us cost=4 size=518 card=14)
14 TABLE ACCESS FULL EMP (cr=7 pr=0 pw=0 time=1 us cost=3 size=518 card=14)
- 강좌 URL : http://www.gurubee.net/lecture/3286
- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^
- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.