OR-Expansion 기본
- or-expansion은 기본적으로 or로 묶인 where 절에 조건의 경우 or의 사용으로 index를
사용할 수 없어 full table scan을 해야 한다. 그러나 or-expansion을 사용하게 되면
index를 사용할 수 있게 되면서 해당 결과 집합을 union all로 합쳐서 사용한다.
- 즉, 결론적으로 index를 사용하며 union all로 합쳐주는 작업으로 이해하면 쉽다.
하지만 테이블을 2번 엑세스 한다는 단점이 있어서 겹치는 부분이 적을 때 효과적이다.
- OR-Expansion을 제어하기 위해 사용하는 힌트로는 use_concat 과 no_expand 두가지가 있다.
use_concat은 OR-Expansion을 유도하고자 할 때 사용하고,
no_expand는 이 기능을 방지하고자 할 때 사용한다.
( or-expansion 기능은 _no_or_expansion 파라미터를 true로 설정하여 아예 막을 수 있다. )
OR-Expansion 브랜치별 조인 순서 최적화
- OR-Expansion에 의해 분기된 브랜치마다 각기 다른 조인 순서를 가질 수 있음은 매우 중요한
사실이다.
- where 절에서 () 안에 들어간 or 에서도 or-expansion이 발생할 수 있다.
* LNNVL 함수
- 두 쿼리의 교집합이 두번 출력되는 것을 방지하기 위해서 or-expansion 사용시
자동으로 사용되는 함수
같은 컬럼에 대한 OR-Expansion
- 9i 까지는 같은 컬럼에 대한 or 조건이나 in-list도 or-expansion이 작동할 수 있었지만
10g부터는 기본적으로 아래와 같이 IN-List Iterator 방식으로만 처리된다.
- 만약 억지로 OR-Expansion으로 유도하려면 use_concat 힌트에 qb_name 인자를 제공하면
되지만 , IN-List Iterator에 비해 나은 점이 없으므로 굳이 그렇게 할 이유는 없다.
- 주의할 사항이 한가지 있다. 9i까지는 OR 조건이나 IN-List를 힌트로 이용해 OR-Expansion으로
유도하면 뒤쪽에 놓인 조건이 항상 먼저 출력됐었다.
- 하지만 10g CPU 비용 모델에서는 위와 같이 OR-Expansion으로 유도했을 때 통계적으로
카디널리티가 작은 값이 먼저 출력된다.
- 9i 이전 처럼 뒤쪽에 놓인 값이 먼저 출력되도록 하려면 ordered_predicate 힌트를 사용하거나
IO 비용 모델로 바꿔주어야 한다.
- 10g 이후 버전에서도 비교 연산자가 '=' 조건이 아닐 때는 일반적인 use_concat 힌트만으로도
같은 컬럼에 대한 OR-Expansion이 잘 작동한다.
* 테스트에서 알아 낸 점
- 기본적으로 index가 있어야 하는 것 같다. or-expansion이 되려면 index가 없으면
full table scan이 발생하여 concatenation 실행계획이 발생하지 않았다.
( 한 번 더 테스트 하고 증거 남기기 )
nvl/decode 조건식에 대한 or-expasion
- 조건절에 nvl 이나 decode 함수를 사용하면 or-expansion 실행계획이 발생한다.
- 해당 변수 값의 null 여부에 따라 위 또는 아래쪽 브랜치만 수행하는 것이다.
- 무엇보다 중요한 것은 변수 값 입력 여부에 따라 다른 인덱스를 사용하다는 사실이다.
- 이 유용하 닉능을 제어하는 파라미터는 ' _or_expand_nvl_predicate '이다.
- nvl 또는 decode를 여러 컬럼에 대해 사용했을 때는 그 중 변별력이 가장 좋은 컬럼 기준으로
한 번만 분기가 일어난다.
- 옵션 조건이 복잡할 때는 이 방식에만 의존하기 어려운 이유가 여기에 있고, 그럴 때는
여전히 수동으로 union all 분기를 해 줘야만 한다.