인덱스에 관한 FAQ와 오해
Q) 뷰에서도 인덱스가 사용되는가?
- 뷰는미리 생성된 쿼리일 뿐이다.
- 뷰를 인덱싱하고자 한다면, 베이스 테이블을 인덱싱하면 된다.
Q) NULL과 인덱스는 함께 사용되는가?
- B*Tree 인덱스는 인덱스를 구성히논 모든 컬럼이 NULL 인 엔트리를 저장하지 않는다.( 클러스터 B*Tree 인덱스를 제외)
Q) 참조 키에는 인덱스가 생성되어야 하는가?
- 인덱스가 없는 참조 키는 데드락의 가장 큰 이유라고 언급하였다.
- 부모 테이블의 기본 키를 수정하거나 부모 로우를 제거하려고 할 때 자식 테이블에 락 (lock)을 걸게 되기 때문이다
- 부모 테이블을 삭제하지 않는다.
- 의도하지 않은 경우(툴을 통한)에라도 부모 테이블의 유니크 또는 기본 커 값에 수정이 발생하지 않는다.
- 부모 테이블과 자식 테이블을 조인하지 않는 경우 또는 참조 키가 자식 테이블을 조회하는 주요한 액세스 패스가 아니며 테이블의 데이터를 추출하기 위한 조건으로 사용하지 않는다.
- 이 세 가지 조건을 만족한다면 인텍스를 만들지 않아도 된다. 불필요할 뿐 아니라 자식 테이블의 DML을 느려 지게 할 뿐이다.
Q) 해당 인텍스를 왜 사용하지 않을까?
- 다양한 이유가 존재한다. 가장 일반적인 이유를 살펴보자.
- CASE 1
- B*Tree 인덱스를 사용하지만, 조건절의 컬럼이 인덱스의 선두 컬럼을 이용하지 않는 경우다.
- 테이블 T에 (x, y) 컬럼에 인텍스가 존재하는데 SELECT * FROM T WHERE Y = 5라는 쿼리를 사용한 경우다.
- CASE 2
- SELECT COUNT(*) FROM T와 같거나 유사한 쿼리를 사용하며 테이블 T에 B*Tree 인덱스를 가진 경우다.
- 옵티마이저는 훨씬 크기가 작은 인덱스 엔트리를 카운트하기보다는 테이블 전체 스캔을 선택한다. ( 인덱스 컬럼이 NULL값을 가질경우 잘못된값이 나옴)
- CASE 3
- INDEX_COLUMN 의 함수사용은 인덱스를 사용되지 않을 것이다
- 이런 때에는 함수에 인덱스를 생성하면된다.
select * from t where f(indexed_column) = value
- CASE 4 - 오직숫자값만을 가진 문자컬럼에 인덱스를생성한경우다.
- CASE 5 \- 인텍스를사용하는것이 더 느린 경우
- 인덱스를 경유하는 예상 로우 수가 임계치를 넘어선다면, 전체 테이블 스캔을 고려해보아야 한다.
- CASE 6 - 오랫동안 태이블의 통계정보를 수집하지 않는 경우다.
- 인덱스 사용CASE 정리
- 옵티마이저가 인덱스를 사용하지않는 이유는 '잘못된 결괴를 리턴하거나 또는 오히려 성능이 악화될 수 있기 때문에 인텍스를 사용하지 않는다 '
Q) 오해 : 인덱스 공간은 절대 재사용되지 않는다
- 인덱스에서도공간은재사용된다.
- 인덱스 슬롯이 한번 사용되면 동일한 값으로 사용되는 경우에만 재사용된다
Q)오해: 가장 변별력이 있는요소가선두에 와야한다
- 선두인지 아닌지는 별 문제가 되지 않는다 .
- 높은 식별력을 가지는 순서로 인텍스 컬럼을 배치하면 인텍스 압축시 훨씬 더 많이 압축될것이다.