인덱스 기본 사용법은 인덱스를 Range Scan 하는 방법을 의미
인덱스를 사용한다는 것
- 인덱스를 정상적으로 사용한다 라는 표현은 리프 블록에서 스캔 시작점을 찾아 거기서부터 스캔하다가 중간에 멈추는 것을 의미
- 즉, 리프블록 일부만 스캔하는 Index Range Scan을 의미
- 인덱스 컬럼을 가공해도 인덱스를 사용할 수 는 있지만, 스캔 시작점을 찾을 수 없고 멈출 수도 없어 리프 블록 전체를 스캔해야만 한다.
- 즉, 일부가 아닌 전체를 스캔하는 Index Full Scan방식으로 작동
인덱스를 Range Scan 할 수 없는 이유
- 인덱스 스캔 시작점을 찾을 수 없기 때문!
- Index Range Scan에서 Range는 범위를 의미
- Index Range Scan은 인덱스에서 일정 범위를 스캔한다는 뜻
- 일정 범위를 스캔하려면 시작지점과 끝지점이 있어야 한다.
ex1) where 생년월일 between 20070101 and 20070131 => 시작점과 끝이 있음
ex2) where 이름 like '%재%' => 재를 포함하는 값은 Range Scan 불가능
- 즉, 리프 블록에서 스캔 시작점을 찾아 거기서부터 스캔하다가 중간에 멈추는 것을 의미.!!
더 중요한 인덱스 사용 조건
- 인덱스를 Range Scan 하기 위한 가장 첫 번째 조건은 인덱스 선두 컬럼이 조건절에 있어야 함!!
- 인덱스 선두 컬럼이 가공되지 않은 상태로 조건절에 있으면 인덱스 Range Scan은 무조건 가능
- 인덱스를 Range Scan 한다고 해서 항상 성능이 좋은건 아님!
- 인덱스를 잘 타는지는 인덱스 리프 블록에서 스캔하는 양을 따져봐야 알 수 있음.
(예를 들어서 Range Scan을 타는데 10건인지 100만건이지 봐야 알 수 있음.)
인덱스를 이용한 소트 연산 생략
- 인덱스를 Range Scan 할 수 있는 이유는 데이터가 정렬되어 있기 때문!!
- 그러면 OrderBy가 있어도 정렬 연산을 따로 수행하지 않음!! (소트 연산 생략!)
- 정렬 연산을 생략할 수 있게 인덱스가 구성되어 있지 않다면 Order By연산 단계를 추가가 됨
ORDER BY 절에서 컬럼 가공
- [주문일자 + 주문번호]로 인덱스가 구성되어 있다고 가정
- 이럴 경우 주문일자, 주문번호는 order by 생략이 가능
- 하지만 주문일자 또는 주문번호를 가공해서 사용할 경우 order by 연산 단계가 추가된다.
SELECT-LIST에서 컬럼 가공
- [장비번호 + 변경일자 + 변경순번]로 인덱스 구성되었다고 가정
- MIN(변경순번), MAX(변경 순번)은 오른쪽 또는 왼쪽 레코드만 읽고 멈춘다.
- 하지만 ()내에서 가공한 값이 들어가는 순간 정렬 연산을 생략할 수 없음.
- 인덱스 컬럼을 가공하면 이전 데이터를 모두 읽어야하기 때문에 성능이 나쁘다.
자동 형변환
- select from 고객 where 생년월일 = 19821225 => 테이블 풀 스캔
- 왜? 인덱스 컬럼이 가공이 됨(자동 형변환)
- 데이터 형식을 정확히 지정해주는 코딩 습관이 필요!
- LIKE, BETWEEN조건을 사용하면 인덱스 스캔 효율이 안좋음
- 자동 형변환때문에 성능, 품질이 문제가 생길 수 있다.
- 데이터 타입을 명시적으로 일치 시켜주자!!
- 자동 형변환에 의존하지말고 인덱스 컬럼 기준으로 반대편 컬럼 또는 값을 정확히 형변환해주자!