인덱스를 스캔하는 범위(Range)를 얼마만큼 줄일 수 있느냐, 테이블로 액세스하는 횟수를 얼마만큼 줄일 수 있느냐가 관건이다. 이는 인덱스 설계와 SQL 튜닝의 핵심 원리 중 하나이다.
Index Range Scan이 가능하게 하려면 인덱스를 구성하는 선두 컬럼이 조건절에 사용되어야 한다. 그렇지 못한 상황에서 인덱스를 사용하도록 힌트로 강제하면, 바로 이어서 설명할 Index Full Scan 방식으로 처리된다.
Index Range Scan 과정을 거쳐 생성된 결과 집합은 인덱스 컬럼 순으로 정렬된 상태가 되기 때문에, 이런 특성을 잘 이용하면 osrt order by 연산을 생략하거나, min/max 값을 빠르게 추출할 수 있다.
나. Index Full Scan
수직적 탐색 없이, 인덱스 리프 블록을 처음부터 끝까지 수평적으로 탐색하는 방식이다. 대개는 데이터 검색을 위한 최적의 인덱스가 없을 때 차선으로 선택된다.
실제로는, 맨 첫 리프 노드까지 가기 위해 한번의 수직적 탐색이 일어나긴 한다 (그림의 점선)
Index Full Scan의 효용성
인덱스 선두 컬럼이 조건절에 없으면, 옵티마이저는 우선적으로 Table Full Scan을 고려한다. 그런데 대용량 테이블이어서 Table Full Scan의 부담이 크다면, Index Full Scan을 고려한다.
데이터 저장공간은 가로 X 세로 즉 컬럼길이 * 레코드수 에 의해 결정된다. 대개 인덱스가 차지하는 면적은 테이블보다 훨씬 적다. 만약 인덱스 스캔 단계에서 대부분 레코드를 필터링하고 일부에 대해서만 테이블 액세스가 발생하는 경우라면, 테이블 전체를 스캔하는 것보다 낫다. 이럴 때 옵티마이저는 Index Full Scan 방식을 선택할 수 있다.
인덱스를 이용한 소트 연산 대체
Index Full Scan은 Index Range Scan과 마찬가지로, 그 경로가 집합이 인덱스 컬럼 순으로 정렬되므로 Sort order By연산을 생략할 목적으로 사용될 수도 있다. (차선책 x 옵티마이저가 전략적으로 선택)
where sal > 1000
대부분 사원 연봉이 5000을 넢어 Index Full Scan을 하면 거의 모든 레코드에 대해 테이블 액세스가 발생해 Table Full Scan보다 오히려 불리
만약 sal이 인덱스 선두 칼럼이어서 Index Range Scan을 하더라도 마찬가지임
그런데도 여기서 인덱스가 사용된 것은 사용자가 first_rows 힌트를 이용해 옵티마이저 모드를 바꾸었기 때문임 - 즉 옵티마이저가 소트 연산을 생략함으로써 전체 집합 중 처음 일부만을 빠르게 리턴할 목적으로 Index Full Scan 방식을 선택한 것
다. Index Unique Scan
수직적 탐색만으로 데이터를 찾는 스캔 방식
Unique 인덱스를 ‘=’ 조건으로 탐색하는 경우에 작동
Oracle의 실행계획
INDEX (UNIQUE SCAN)
SQL Server는 Range Scan 과, Unique Scan을 구분하지 않고 똑같이 Index Seek으로 표시한다.
라. Index Skip Scan
원래 인덱스 선두 컬럼이 조건절에 사용되지 않으면 → Table Full Scan, 또는 I/O를 줄일 수 있거나 정렬된 결과를 쉽게 얻을 수 있을 때 Index Full Scan인데
오라클 9i 버전부터 인덱스 선두 컬럼이 조건절에 빠졌어도 인덱스를 활용하는 새로운 스캔방식을 선보임. 그게 Index Skip Scan이다.
예) 성별 - 연봉 인덱스가 있는 테이블에서 인덱스 선두 컬럼인 성별이 조건절에 없는 쿼리 실행시
Skip Scan 의 원리: 루트 또는 브랜치 블록에서 읽은 칼럼 값 정보를 이용해 조건에 부합하는 레코드를 포함할 ‘가능성이 있는’ 하위 블록(브랜치 또는 리프 블록)만 골라서 액세스 (가능성을 어케 판단하지?)
이 스캔 방식은 조건절에 빠진 인덱스 선두 컬럼의 Distinct Value 개수가 적고, 후행 컬럼의 Distinct Value 개수가 많을 때 유용
이렇게 쿼리 작성자가 직접 성별에 대한 조건식을 추가해주면 Index Skip Scan에 의존하지 않고도 빠르게 결과 집합을 얻을 수 있다. 단 이처럼 In-List를 명시하려면 성별 값의 종류가 더 이상 늘지 않음이 보장되어야 한다. 그리고, In-List로 제공하는 값의 종류가 적어야 한다.
In-List를 제공하는 튜닝 기법을 익히 알던 독자라면 Index Skip Scan이 옵티마이저가 내부적으로 In-List를 제공해주는 방식이라고 생각하기 쉽지만 내부 수행 원리는 전혀 다르다.
마. Index Fast Full Scan
말 그대로, Index Full Scan보다 빠른 검색 방식이다.
이유는 인덱스 트리 구조를 무시하고 인덱스 세그먼트 전체를 Multiblock Read 방식으로 스캔하기 때문이다. Index Full Scan과의 차이점을 요약하면 다음과 같다:
바. Index Range Scan Descending
Index Range Scan과 기본적으로 동일한 스캔 방식이다. 그림처럼 인덱스를 뒤에서부터 앞으로 스캔하기 때문에, 내림차순으로 정렬된 결과 집합을 얻는다는 점만 다르다.
예2 ) emp 테이블을 empno 기준으로 내림차순 정렬하는 쿼리이며, empno 컬럼에 인덱스가 있는 경우
옵티마이저가 알아서 인덱스를 거꾸로 읽는 실행계획을 수립한다.
SQL Server버전
예2 ) Max 값 구하기
Max 값을 구하려는 컬럼에 인덱스가 있으면, 인덱스를 뒤에서부터 한건만 읽고 멈추는 실행계획이 수립된다.