- 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로 가공했기 때문에 소팅 연산 생략 불가
'DATABASE > 튜닝' 카테고리의 다른 글
[SQL 튜닝] 테이블 랜덤 액세스, ROWID, 인덱스 손익분기점 (0) | 2020.06.29 |
---|---|
[SQL 튜닝] 자동 형변환과 Index 스캔 (0) | 2020.06.29 |
[SQL 튜닝] 인덱스 기본 사용법 (0) | 2020.06.15 |
[SQL 튜닝] 인덱스 구조 및 탐색 (0) | 2020.06.15 |
[SQL 튜닝] Table Full Scan VS Index Range Scan VS Index Full Scan (0) | 2020.06.08 |