WHERE 조건은 인덱스를 타는데 왜 느릴까? – INDEX RANGE SCAN의 함정과 대처법
오라클에서 실행 계획을 보면 INDEX RANGE SCAN
이 잡히는 경우가 있습니다. 일반적으로 이는 인덱스를 잘 활용하고 있다는 의미로 받아들여지지만, 실제로는 쿼리 성능이 기대만큼 나오지 않거나 오히려 느려지는 경우도 존재합니다.
이번 글에서는 인덱스를 타고 있음에도 성능이 저하되는 이유를 다양한 관점에서 분석하고, 이를 해결하기 위한 실무적인 팁을 함께 소개합니다.
1. INDEX RANGE SCAN이란?
INDEX RANGE SCAN은 인덱스를 통해 일부 범위만 탐색하는 방식입니다. 예를 들어 조건절이 WHERE AGE BETWEEN 20 AND 30
처럼 범위 조건일 때 사용됩니다.
실행 계획에서 다음처럼 보입니다:
INDEX RANGE SCAN on IDX_EMP_AGE
인덱스가 사용되므로 성능이 좋을 것으로 기대되지만, 아래와 같은 이유로 성능이 떨어질 수 있습니다.
2. 인덱스를 타는데 느린 이유
① TABLE ACCESS BY ROWID가 병목
인덱스를 타더라도 최종 데이터를 읽기 위해 테이블 본문을 조회해야 하는 경우가 많습니다. 이는 TABLE ACCESS BY ROWID
단계에서 발생하며, 인덱스로 찾은 ROWID를 따라가 테이블을 반복해서 읽는 구조입니다.
행 수가 많다면 디스크 I/O가 상당히 증가합니다.
② 인덱스 조건은 탔지만 FILTER 조건에서 제외됨
예를 들어 다음 쿼리에서:
SELECT * FROM EMP
WHERE AGE BETWEEN 30 AND 40 AND GENDER = 'M';
AGE 컬럼에만 인덱스가 있을 경우, GENDER = 'M'
조건은 인덱스에서 필터링되지 않고, 테이블 조회 후 FILTER 단계에서 제거됩니다. 불필요한 행을 먼저 읽는 구조가 되므로 비효율적입니다.
③ 인덱스 컬럼이 NULLABLE이거나 정렬도가 낮음
조건 컬럼이 NULL 값을 많이 포함하거나, 정렬도가 낮은 컬럼일 경우 오라클 옵티마이저는 예측보다 많은 범위를 탐색하게 됩니다. 결국 인덱스를 사용하고도 실제 I/O 비용은 높은 상황이 됩니다.
④ 조건 범위가 지나치게 넓음
INDEX RANGE SCAN이라도 WHERE AGE > 0
같은 조건이라면 거의 전체 테이블을 읽는 것과 다름없는 범위를 탐색하게 됩니다. 이럴 경우에는 오히려 FTS(FULL TABLE SCAN)가 더 빠를 수 있습니다.
3. 개선 방법
✅ 필요한 컬럼만 SELECT
필요한 컬럼만 조회하면 INDEX ONLY SCAN
으로 전환할 수 있습니다. 이 경우 테이블을 조회하지 않고 인덱스만으로 결과를 반환하므로 매우 빠릅니다.
예시:
SELECT AGE FROM EMP WHERE AGE BETWEEN 20 AND 30;
AGE만 필요하면 INDEX ONLY SCAN이 가능해집니다.
✅ 복합 인덱스 설계
위 예시처럼 AGE
와 GENDER
를 모두 조건으로 사용하는 경우, 두 컬럼을 포함하는 복합 인덱스를 설계하면 FILTER 단계를 제거할 수 있습니다.
CREATE INDEX IDX_EMP_AGE_GENDER ON EMP(AGE, GENDER);
✅ 인덱스 힌트와 실행 계획 확인
실행 계획을 항상 확인하여 실제 인덱스가 어떤 방식으로 사용되는지 점검해야 합니다. 때로는 옵티마이저가 인덱스를 사용하더라도 성능상 불리할 수 있으며, 이럴 경우 힌트를 통해 명시적으로 FTS로 유도하는 것도 방법입니다.
마무리하며
실행 계획에 INDEX RANGE SCAN
이 떴다고 해서 반드시 빠른 쿼리라고 단정지을 수는 없습니다. 실제 쿼리 성능은 테이블 접근 방식, 조건의 범위, 필터 조건 처리 방식 등 다양한 요소가 복합적으로 작용합니다.
이전에 작성한 INDEX가 안 잡힐 때 확인할 조건 및 SELECT COUNT(*)가 느릴 때 – 성능 개선 전략과 대안 글과 함께 참고하면, 인덱스 관련 성능 이슈를 보다 정확하게 진단하고 해결할 수 있습니다.
#오라클 #SQL튜닝 #인덱스성능 #INDEXRANGESCAN #실행계획 #실무팁 #SQL최적화
'오라클 실무 쿼리 튜닝' 카테고리의 다른 글
서브쿼리 성능 최적화 – 서브쿼리에서 성능을 끌어올리는 5가지 방법 (0) | 2025.04.16 |
---|---|
SELECT COUNT(*)가 느릴 때 – 성능 개선 전략과 대안 (0) | 2025.04.15 |
INDEX가 안 잡힐 때 확인할 조건 – 오라클 인덱스 미사용 원인 정리 (0) | 2025.04.15 |
인라인 뷰 vs 테이블 조인 – 같은 결과, 다른 처리 방식 (0) | 2025.04.14 |
INDEX RANGE SCAN과 FULL SCAN, 언제 어떤 게 빠를까? (0) | 2025.04.09 |