소트 연산이 불가피하다면 메모리 내에서 처리를 완료할 수 있도록 노력해야 한다.
select lpad(상품번호, 30) || lpad(상품명, 30)
from 주문상품
where ~
order by 상품번호
vs
select lpad(상품번호, 30) || lpad(상품명, 30)
from (
select 상품번호, 상품명
from 주문상품
where ~
order by 상품번호
)
1번 SQL은 레코드당 60(30+30) 바이트로 가공된 결과치를 Sort Area에 담는다. 반면 2번 SQL은 가공되지 않은 상태로 정렬을 완료하고 나서 최종 출력할 때 가공하므로 1번 SQL에 비해 Sort Area를 훨씬 적게 사용한다.
Top-N 쿼리 형태로 작성하면 소트 연산(= 값 비교) 횟수를 최소화함은 물론 Sort Area 사용량을 줄일 수 있다.
select * from (
select 거래일시, 체결건수...
from 시간대별종목거래
where 종목코드 = 'A'
and 거래일시 >= '20260717'
order by 거래일시
)
where rownum <= 10
SELECT ~
COUNT (STOPKEY)
VIEW
TABLE ACCESS (BY INDEX ROWID) ~
INDEX (RANGE SCAN) OF ~
[종목코드 + 거래일시] 순으로 구성된 인덱스가 존재한다면 해당 인덱스를 통해 order by 연산을 대체할 수 있다.
rownum 조건을 사용해 N건에서만 멈추도록 실행
rownum <= 10이면 우선 10개 레코드를 담을 배열을 할당하고, 처음 읽은 10개 레코드를 정렬된 상태로 담는다.
이후 읽는 레코드에 대해서는 맨 우측에 있는 값(가장 큰 값)과 비교해서 그보다 작은 값이 나타날 때만 배열 내에서 다시 정렬을 시도한다. 이 방식으로 처리하면 전체 레코드를 정렬하지 않고도 10개 레코드를 정확히 찾아낼 수 있다.
window sort 시에도 rank()나 row_number()를 쓰면 Top-N 쿼리 알고리즘이 작동해 max() 등 함수를 쓸 때보다 소트 부하를 경감시켜 준다.