인라인 뷰에 ROWNUM을 사용하면 쿼리변환이 일어나지 않게 되므로 주의해서 사용해야 된다.
-- 테이블 생성
DROP TABLE rownum_t3 PURGE ;
CREATE TABLE rownum_t3
AS
SELECT level AS c1, chr(65+mod(level,26)) AS c2, level+99999 AS c3
FROM DUAL
CONNECT BY level <= 100000 ;
-- 인덱스 생성
CREATE INDEX rownum_t3_idx_01 ON rownum_t3 (c1) ;
-- 변수 설정
var b1 varchar2(2)
var b2 number
exec :b1 := 'A';
exec :b2 := 102530;
-- 인라인 뷰 안에 rownum 이 있을 때
SELECT t3.*
, t2.*
FROM ROWNUM_T2 t2,
(SELECT ROWNUM rnum
, rownum_t3.*
FROM ROWNUM_T3 ) t3
WHERE t2.c1 = t3.c1
AND t2.c2 = :b1
AND t2.c3 = :b2 ;
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2893 | 177K| 330 (1)| 00:00:04 |
|* 1 | HASH JOIN | | 2893 | 177K| 330 (1)| 00:00:04 |
| 2 | TABLE ACCESS BY INDEX ROWID| ROWNUM_T2 | 2893 | 83897 | 259 (0)| 00:00:04 |
|* 3 | INDEX RANGE SCAN | ROWNUM_T2_IDX_03 | 289 | | 3 (0)| 00:00:01 |
| 4 | VIEW | | 100K| 3320K| 69 (2)| 00:00:01 |
| 5 | COUNT | | | | | |
| 6 | TABLE ACCESS FULL | ROWNUM_T3 | 100K| 1171K| 69 (2)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("T2"."C1"="T3"."C1")
3 - access("T2"."C2"=:B1 AND "T2"."C3"=TO_NUMBER(:B2))
-- 인라인 뷰에 rownum 이 있으므로 뷰 머징이 되지 않아서 view 가 그대로 나타남.
-- 뷰 머징이 되지 않을 때 옵티마이저는 View Predication 을 수행해보는데 인라인 뷰 안의 조건 변경에 의해
-- 데이터에 부여되는 rownum이 달라질 수 있으므로 View Predication 을 수행할 수 없음.
var b1 varchar2(2)
var b2 number
exec :b1 := 'A';
exec :b2 := 102530;
-- 인라인 뷰 밖에 rownum 이 있음
SELECT rownum
, t3.*
, t2.*
FROM rownum_t2 t2
,(SELECT *
FROM rownum_t3 ) t3
WHERE t2.c1 = t3.c1
AND t2.c2 = :b1
AND t2.c3 = :b2 ;
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2893 | 115K| 330 (1)| 00:00:04 |
| 1 | COUNT | | | | | |
|* 2 | HASH JOIN | | 2893 | 115K| 330 (1)| 00:00:04 |
| 3 | TABLE ACCESS BY INDEX ROWID| ROWNUM_T2 | 2893 | 83897 | 259 (0)| 00:00:04 |
|* 4 | INDEX RANGE SCAN | ROWNUM_T2_IDX_03 | 289 | | 3 (0)| 00:00:01 |
| 5 | TABLE ACCESS FULL | ROWNUM_T3 | 100K| 1171K| 69 (2)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("T2"."C1"="ROWNUM_T3"."C1")
4 - access("T2"."C2"=:B1 AND "T2"."C3"=TO_NUMBER(:B2))
-- 인라인 뷰 안에 rownum 이 없으므로 뷰 머징이 일어난 것을 확인할 수 있음.