*OR조건은 Full Table Scan된다.
1차 단계- OR조건은 Full Table Scan된다.
SELECT * FROM EMP
WHERE JOB = 'CLERK' OR DEPTNO = 20;
2차 단계- JOB과 DEPTNO에 각각 생성된 인덱스를 사용하고 싶다면 UNION ALL 사용
SELECT * FROM EMP
WHERE JOB = 'CLERK'
UNION ALL
SELECT * FROM EMP
WHERE DEPTNO = 20
AND LNNVL(JOB = 'CLERK')
;
JOB과 DEPTNO 칼럼을 선두로 갖는 두 인덱스가 각각 사용되었고, UNION ALL 위쪽 브랜치는 JOB = 'CLERK'인 집합을 읽고 아래쪽 브랜치는 DEPTNO = 20 인 집합만을 읽는다.
분기된 두 쿼리가 각각 다른 인덱스를 사용하긴 하지만, EMP 테이블 액세스가 두 번 일어난다. 따라서 중복 액세스되는 영역(DEPTNO = 20 이면서 JOB = 'CLERK')의 데이터 비중이 작을 수록 효과적이고, 그 반대의 경우라면 오히려 쿼리 수행 비용이 증가한다.
중복 액세스되더라도 결과집합에는 중복이 없게 하려고 UNION ALL 아래쪽에 ORACLE이 내부적으로 LNNVL함수를 사용한 것을 알 수 있다. JOB <> 'CLERK' 이거나 JOB IS NULL인 집합만을 읽으려는 것이며, 이 함수는 조건식이 FALSE이거나 알 수 없는(UNKNOWN) 값일 때 TRUE를 리턴한다.
*ORACLE에서 OR-Expansion 제어(힌트 사용)
SELECT /*+ USE_CONCAT */ FROM EMP -- OR Expansion 기능 유도
WHERE JOB = 'CLERK' OR DEPTNO = 20;
SELECT /*+ NO_EXPAND */ FROM EMP -- OR Expansion 기능 방지
WHERE JOB = 'CLERK' OR DEPTNO = 20;
P.S. 사용자 쿼리를 직접 바꿔주지 않아도 옵티마이저가 2차 단계를 대신해 주는 경우가 있는데 이를 'OR-Expansion'이라고 한다.
'개발 및 관리 > Oracle 9i, 10g, 11g, 12c, 19c' 카테고리의 다른 글
비트맵 인덱스 - SQL전문가 가이드 p.612~p.614 (0) | 2012.10.24 |
---|---|
인덱스 재생성 - SQL전문가 가이드 p.612 (0) | 2012.10.24 |
불필요한 조인 제거 - SQL전문가 가이드 p.585~p.587 (0) | 2012.10.24 |
조인 조건(Join Predicate) Pushdown - SQL전문가 가이드 p.582~p.584 (0) | 2012.10.24 |
SQL 가이드, Oracle 가이드, MS-SQL 가이드 (0) | 2012.08.28 |