오늘의 주제는 “옵티마이저와 인덱스 힌트” 입니다.
관계형 데이터베이스는 기본적으로 인덱스가 생성된 컬럼이 아닌 일반 컬럼을 조건으로 SELECT 명령문을 수행할 경우 테이블 Full Scan 방식을 통해 데이터를 조회합니다.
그렇기 때문에 DBA는 엔지니어들의 쿼리 검수 과정에서 플랜을 확인하고
과도한 I/O가 발생하지는 않는지 확인하여 튜닝 작업을 진행해야 합니다.
DBA가 없는 경우 엔지니어들의 무분별한 인덱스 추가 작업으로 기존에 잘 동작하던 쿼리의 플랜이 깨져 Slow Query 가 발생하는 경우도 존재합니다.
DBA는 위와 같은 케이스가 존재하기 때문에라도 항상 사전 검수 후, 쿼리 튜닝 및 인덱스 추가 작업을 진행해야 합니다.
앞서 설명한 내용을 조금 더 자세히 설명하기에 앞서 우리는 “옵티마이저” 를 알아야 합니다.
옵티마이저 이외에도 많은 내용이 존재하지만,
해당 포스트에서는 맨처음 언급한 기존 플랜이 깨져 Slow Query 가 발생하는 경우에 대해 이야기를 하려고 합니다.

위 쿼리는 정상적인 인덱스 키를 통한 데이터 조회했을 때의 실행계획입니다.
기존 플랜이 깨져 Slow Query가 발생하는 경우는 다양합니다.
무분별한 인덱스 추가로 인해 옵티마이저가 적절한 인덱스가 아닌 엉뚱한 인덱스를 스캔하거나, 테이블 Full Scan 방식의 비용이 더 낮다고 판단하는 경우도 있을 것입니다.
이러한 경우 INDEX HINT 를 통해서 사용자가 원하는 인덱스를 옵티마이저가 스캔할 수 있도록 지정할 수 있습니다.
USE / FORCE / IGNORE 예약어 사용SELECT *
FROM dept USE INDEX (`인덱스명`)
WHERE deptno > 10
;SELECT *
FROM dept FORCE INDEX (`인덱스명`)
WHERE deptno > 10
;SELECT *
FROM dept IGNORE INDEX (`인덱스명`)
WHERE deptno > 10
;INDEX HINT를 사용하기 위해서는 다양한 부분을 고려해야 합니다.
특히나 FORCE INDEX 힌트의 경우 꼭 필요한 상황이 아닌 이상 권장하지 않는 방법입니다.
기본적으로 옵티마이저가 작성한 실행계획에 의해 조회 방식이 결정되기 때문에
FORCE INDEX 힌트는 예기치 못한 사이드 이펙트를 발생시킬 수 있다는 것을 명심해야 합니다.