- Index Range Scan이 가능한 이유는 데이터가 정렬되어 있기 때문임

- 데이터가 정렬되어 있기 때문에 전체가 아닌 일부분만 읽다가 멈출 수 있음

- 인덱스 컬럼을 가공해도 인덱스를 사용할 수는 있지만, 찾고자 하는 데이터가 전체 구간에 흩어져 있어서 Index Range Scan이 불가능하거나 비효율적임

- 인덱스가 정렬되어 있다는 특성을 활용하여 소트 연산을 생략할 수 있는 효과를 가질 수 있음

 

Ex)

인덱스 : 장비번호+변경일자+변경순번

select *
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'

- 해당 쿼리의 결과는 장비번호가 C이고 변경일자가 20200622인 것들을 변경순번 순으로 조회함

- 이때 ORDER BY연산을 하지 않음 (ORDER BY를 명시해도 수행하지 않음)

 

select *
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'
order by 변경순번 desc

- 내림차순 정렬을 요구하는 경우 인덱스 스캔을 반대로 함

 

select *
from 상태변경이력
where 장비번호 = 'C'
order by 변경일자 || 변경순번

- 이런 경우 인덱스를 활용한 소팅 연산을 생략할 수 없음

- 인덱스에는 가공되지 않은 값을 저장했는데, 가공한 값( || )으로 정렬을 해달라 해서..

 

Ex

인덱스 : 주문일자+주문번호

select to_char(A.주문번호, 'FM000000') as 주문번호, A.업체번호, A.주문금액
from 주문 A
where A.주문일자 = dt
and A.주문번호 > NVL(next_ord_no, 0)
order by 주문번호

- 이 쿼리도 인덱스를 이용한 소팅 연산 생략 불가

- to_char로 가공된 값인 주문번호로 정렬을 해달라고 했기 때문

select to_char(A.주문번호, 'FM000000') as 주문번호, A.업체번호, A.주문금액
from 주문 A
where A.주문일자 = dt
and A.주문번호 > NVL(next_ord_no, 0)
order by A.주문번호

- order by의 주문번호에 A. 를 붙이면 인덱스를 이용한 소팅 생략 가능

 

 

Ex

인덱스 : 장비번호+변경일자+변경순번

select MIN(변경순번)
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'

select MAX(변경순번)
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'

- 최솟값/최대값을 구할 때 소팅 연산이 생략됨

- 최소값 : 수직적 탐색으로 가장 왼쪽으로 내려가서 읽는 첫 번째 레코드(FIRST ROW)

- 최댓값 : 수직적 탐색으로 가장 오른쪽으로 내려가서 읽는 첫 번째 레코드(FIRST ROW)

 

 

select NVL(MAX(TO_NUMBER(변경순번)), 0)
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'

select NVL(TO_NUMBER(MAX(변경순번)), 0)
from 상태변경이력
where 장비번호 = 'C'
and 변경일자 = '20200622'

- 첫 번째 쿼리는 문자 타입의 변경순번 컬럼을 TO_NUMBER로 가공했기 때문에 소팅 연산 생략 불가