[Oracle] 오라클 Index Combine, Index Combination, 인덱스 동시에 사용하기
SELECT *
FROM ORD E
WHERE ORD_DT='20120112'
AND BRANCH_CD='BR00000199';
위와 같은 쿼리가 있을 때 ORD 테이블이 [ORD_DT+BRANCH_CD] 컬럼으로 이루어진 결합인덱스를 갖고 있다면 정말 Perfect 하겠지만
ORD_X01 > ORD_DT
ORD_X02 > BRANCH_CD
이렇게 각각의 단일 인덱스만을 갖고 있다면 우리는 둘 중 어떤 인덱스를 타게 하는 것이 좋을지 고민하지 않을 수 없다. (물론 대부분의 경우 그냥 옵티마이저의 판단에 맡길테지만..)
이런 경우 Index Combine을 사용하면 고민할 필요 없이 두 개의 인덱스를 모두 사용할 수 있다.
SELECT /*+ index_combine(e ord_x01 ord_x02) */ *
FROM ORD E
WHERE ORD_DT='20120112'
AND BRANCH_CD='BR00000199';
실행계획을 살펴보자.
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 100 |00:00:00.01 | 222 |
| 1 | TABLE ACCESS BY INDEX ROWID | ORD | 1 | 100 |00:00:00.01 | 222 |
| 2 | BITMAP CONVERSION TO ROWIDS | | 1 | 100 |00:00:00.01 | 134 |
| 3 | BITMAP AND | | 1 | 1 |00:00:00.01 | 134 |
| 4 | BITMAP CONVERSION FROM ROWIDS| | 1 | 1 |00:00:00.01 | 110 |
| 5 | SORT ORDER BY | | 1 | 20263 |00:00:00.01 | 110 |
|* 6 | INDEX RANGE SCAN | ORD_X01 | 1 | 20263 |00:00:00.01 | 110 |
| 7 | BITMAP CONVERSION FROM ROWIDS| | 1 | 1 |00:00:00.01 | 24 |
|* 8 | INDEX RANGE SCAN | ORD_X02 | 1 | 6733 |00:00:00.01 | 24 |
---------------------------------------------------------------------------------------------
순서: 6 → 5 → 4 → 8 → 7 → 3 → 2 → 1
일반 B*Tree 인덱스를 스캔하면서 각 조건을 만족하는 레코드의 RowID 목록을 얻어 비트맵 인덱스 구조를 만든 다음 ORD_X01의 비트값도 1이고 ORD_X02의 비트값도 1인 RowID만을 획득하여 테이블에 access하는 원리임을 실행계획을 통해 알 수 있다.
비트맵 인덱스 구조를 만들어야하는 수고로움이 있으므로 인덱스 하나만을 사용했을 때 비효율적인 테이블 랜덤 액세스가 많이 발생하는 경우에만(액세스 된 레코드가 필터 조건에 의해 많이 버려지는 경우) 사용하도록 하자.
☑ [Oracle] 오라클 인덱스 구조 - Bitmap Index, 비트맵 인덱스 자세히 보기