Outer 조인을 Inner 조인으로 변환 

 - Outer 조인문을 작성하면서 일부 조건절에 Outer 기호 (+)를 빠드리면 Inner 조인할 때와 

   같은 결과가 나온다. 이럴 때 옵티마이저는 Outer 조인을 Inner 조인문으로 바꾸는 쿼리 

   변환을 시행한다. 

 - 옵티마이저가 굳이 이런 쿼리 변환을 시행하는 이유는 조인 순서를 자유롭게 결정하기 

   위해서다. 

 - Outer 조인에서 Inner쪽 테이블에 대한 필터 조건을 아래처럼 where절에 기술한다면 

   inner 조인할 때와 같은 결과집합을 얻게 된다. 따라서 옵티마이저가 Outer 조인을 아예 

   Inner 조인으로 변환해 버린다. 

 - 제대로된 Outer 조인 결과집합을 얻으려면 조건을 on절에 기술해주어야 한다. 

   (이는 즉 조인 후 filter가 되느냐 조인 되기 전에 filter가 되느냐를 결정한다. ) 

 - ANSI Outer 조인문에서 where 절에 기술한 Inner쪽 필터 조건이 의미 있게 사용되는 경우는 

   is null 조건을 체크하는 경우뿐이며, 조인에 실패하는 레코드를 찾고자 할 때 흔히 사용되는 

   SQL이다. 

 - Outer 쪽 필터조건은 on절에 기술하든 where절에 기술하든 결과집합이나 성능에 하등 

   차이가 없다. 

공통 표현식 제거란 

 - 같은 조건식이 여러 곳에서 반복 사용될 경우, 오라클은 해당 조건식이 각 로우당 

   한 번씩만 평가되도록 쿼리를 변환하는데, 이를 '공통 표현식 제거'라고 한다. 

 - ' _eliminate_common_subexpr ' 파라미터를 통해 제어한다. 

 - 이 부분은 단순히 쿼리를 좀 더 보기 쉽고 짧게 바꾼다고 생각할 수 있는데 

 - 위의 ' _eliminate_common_subexpr ' 파라미터를 false로 했을 시 조인 자체가 2번 발생한다. 

   * 이는 내가 했던 테스트 실행계획과 조금 다른 점이 있는데 이 부분은 다시 확인 해보는 것이 

     좋을 것 같다. 

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 분기를 해 줘야만 한다. 

+ Recent posts