ROWNUM DATA 를 추출한 후 조회 하자


ex) rownum 의 잘못된 사용 사례

WHERE ROWNUM = N ( N > 1 )

WHERE ROWNUM > N ( N > 1 )


추출하려면

select 

    rnum,

    t.*

from

(

select

    e1.*,

    rownum rnum

from

(select * from emp order by empno desc) e1 ) t

where rnum >= 6 and rnum <= 12


와 같이 추출 해야한다.




ORDER BY 와 ROWNUM 을 같은 위치에 두지 말자

sql 구성요소들은 아래와 같은 순서로 실행 된다


1) FROM, WHERE 절을 처리

2) ROWNUM 조건 적용

3) SELECT COLUMN LIST 절을 적용

4) GROUP BY 절을 적용

5) HAVING 절을 적용

6) ORDER BY 절을 적용




ROWNUM=1 은 ROWNUM<=1 로 사용하자


CURSOR_SHARING 을 FORCE나 SIMILAR로 적용 하였을 경우

ROWNUM=1을 ROWNUM=:"SYS_B_0" 


1이라는 상수값을 바인드 변수값으로 재해석하여 실행한다


고로 전체 DATA를 다 수행한 뒤 1개 값을 가져오므로 성능악화 된다


하지만 ROWNUM<=:"SYS_B_0" 는 값보다 작거나 같은 값이라는 범위

(STOPKEY)가 정해지기 때문에 변수의 값을 확인하여

작거나 같은 데이터를 추출하므로 전체 데이터를 처리하지 않고, 1건만 추출하고

SQL의 수행은 종료된다




INDEX_DESC와 ROWNUM<=1을 함께 사용하지 말자


완벽해 보이는 방법일수도 있겠으나 index가 unusabled이거나 없는 경우라면

데이터의 정합성이 훼손될 수 있으므로 이 방법 대신


max() 혹은 order by desc 후 ronum <= 1 값을 가져오는 쿼리를 쓰는 방법이 좋다.




ROWNUM<=1 은 항상 빠르지 않다


ROWNUM<=1이 빠른경우는 INDEX RANGE SCAN 하여 COLUMN 의 NUM_DISTINCT (종류가 적은)

최종 추출 건수가 적은 경우에만 빠르다.


즉 INDEX SCAN 하지 않고 FULL TABLE ACCESS 하여 NUM_DISTINCT가 많은 경우

모든 것을 실행뒤 COUNT STOPKEY 하므로 이러한 상황에선 느릴 수도 있다.




인라인 뷰에 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;


>> rownum_t3 테이블을 table access full 하여 view 한 cost 비용이 높다


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;


>> rownum_t3과 t2모두 index range scan 하여 join 후 count를 먹여

     cost 비용이 적게 든다

+ Recent posts