조건절 Pushing
- 뷰를 엑세스하는 쿼리를 최적화할 때 옵티마이저는 1차적으로 뷰 Merging을 고려한다.
하지만 아래와 같은 이유로 뷰 Merging에 실해할 수 있다.
● 복합 뷰 Merging 기능이 비활성화
● 사용자가 no_merge 힌트 사용
● Non-mergeable views : 뷰 Merging 시행하면 부정확한 결과 가능성
● 비용기반 쿼리 변환이 작동해 No Merging 선택
조건절 Pushing 종류
● 조건절 : 쿼리 블록 밖에 잇는 조건들을 쿼리 블록 안쪽으로 밀어 넣는 것을 말함
● 조건절 pullup : 쿼리 블록 안에 있는 조건들을 쿼리 블록 밖으로 내오는 것을 말하며,
그것을 다시 다른 쿼리 블록에 Pushdown 하는 데 사용함
● 조인 조건 Pushdown : NL조인 수행 중에 드라이빙 테이블에서 읽은 값을 건건이 inner 쪽
뷰 쿼리 블록 안으로 밀어 넣는 것을 말함
관련 힌트와 파라미터
- 조건절 Pushdown 과 Pullup은 항상 더 나은 성능을 보장하므로 별도의 힌트를
제공하지 않는다. 하지만, 조인 조건 Pushdown은 NL 조인을 전체로 하기 때문에
성능이 더 나빠질 수도 있다.
- 따라서 오라클은 조인 조건 Pushdown을 제어할 수 있도록
push_pred 와 no_push_pred 힌트를 제공한다.
- 조인 조건 pushdown 기능이 10g에서 비용기반 쿼리 변환으로 바뀌었고, 이 때문에
9i에서 빠르게 수행되던 쿼리가 10g로 이행하면서 오히려 느려지는 현상이 종종 나타나고 있다.
이때는 문제가 되는 쿼리 레벨에서 힌트를 이용해 파라미터를 false로 변경하면 된다.
- 10g에서 시스템 환경에 따라 이 기능이 문제를 일으켜 쿼리 결과가 틀리는 문제도 발생하는
것으로 보고되고 있는데, 그때는 패치를 적용하거나 시스템 레벨 변경이 불가피하다.
Non-pushable view
- 뷰안에 rownum, 분석함수를 사용하면 Non-mergeable, Non-pushable view가 되므로
주의해야 한다.
조건절 Pushdown
* 나만의 요약 정리
조건절 push down은 조인 조건을 통해서 한쪽테이블의 조인 조건인 커럶에 조건이 따로
붙을 때 해당 조건이 조인 조건을 타고 들어가서 다른 테이블에도 영향을 주는 것
(기본적으로 바깥에서 안으로 들어간다. )
GROUP BY 절을 포함한 뷰에 대한 조건절 Pushdown
- group by 절을 포함한 복합 뷰 Merging에 실패했을 때, 쿼리 블록 밖에 있는 조건절을
쿼리 블록 안쪽에 밀어 넣을 수 있다면 group by 해야할 데이터량을 줄일 수 있다.
인덱스 상황에 따라서 효과적인 인덱스 선택이 가능해지기도 한다.
UNION 집합 연산자를 포함한 뷰에 대한 조건덜 Pushdown
* 나만의 요약정리
이것도 기본적으로 바깥에서 안으로 적용 되는데 기본적인 것은 위의 조건절 Pushdown과
같지만 특이한 점이 있는 것은 바깥쪽에 조건이 조인 조건이 아니더라도 union all이 있는
뷰에서 해당 컬럼이 있을 시 동일하게 안쪽으로 조건절이 pushdown 된다.
( p.504 예시를 보면 이해하기 쉽다. )
- union 집합 연산자를 포함한 뷰는 Non-mergeable view에 속해 뷰 Merging에 실패한다.
따라서 조건걸 Pushing을 통해서만 최적화가 가능하다
조건절 Pullup
* 나만의 요약정리
일반적으로 조건절을 밖으로 빼냏어서 다시 조건절 pushdown 하기 위해서 사용된다.
즉 조인하려 2개의 view에서 한쪽에 조인 조건 컬럼에 검색 조건이 있고 조인 조건이
바깥에 있을 때, 안쪽에 있던 조인 조건 컬럼에 대한 또 다른 조건이 바깥쪽에
조인 조건을 타고 들어가서 다른 vies에 조인 조건 컬럼의 검색 조건이 적용된다.
조인 조건 Pushdown
- 조인 조건 Pushdown은 말 그대로 조인 조건절을 뷰 쿼리 블록 안으로 밀어 넣는 것으로서,
NL 조인 수행 중에 드라이빙 테이블에서 읽은 조인 컬럼 값을 Inner 쪽 뷰 쿼리 블록내에서
참조할 수 있도록 하는 기능이다.
- 지금까지 보았던 조인문에서 조건절 Pushdown은 상수 조건이 조인 조건을 타고 전이된 것을
Pushing하는 기능이었던 반면, 조인 조건 Pushdown은 조인을 수행하는 중에
드라이빙 집합에서 얻은 값을 뷰 쿼리 블록 안에 실시간으로 Pushing하는 기능이다.
예시 ) 조인 조건은 deptno 이다. 그런데 다른 조건은 loc= 'CHICAGO'라고 한다면
loc가 'CHICAGO'인 deptno 값들이 들어가는 것이다.
- 실행계획상에서 'View Pushed Predicate' 오퍼레이션이 나타나는 것을 통해서도
조인 조건 Pushdown이 일어나는지 알 수 있다.
- 조인 조건 Pushdown을 제어하는 힌트
● push_pred : 조인 조건 Pushdown을 유도한다.
● no_push_pred : 조인 조건 Pushdown을 방지한다.
- 이를 제어하는 파라미터
● _push_join_predite : 뷰 Merging에 실패한 뷰 안쪽으로 조인 조건을 Pushdown 하는
기능을 활성화한다.
● _push_join_union_view : union all을 포함하는 Non-mergeable View 안쪽으로
조인 조건을 Pushdown 하는 기능을 활성한다.
● _push_join_union_view2 : union을 포함하는 Non-mergeable view 안쪽으로 조인 조건을
Pushdown 하는 기능을 활성화한다.
- 위 항목은 10g 기준이며, 9i 에서는 _push_join_union_view2 파라미터가 없다.
9i에서 union all을 포함한 뷰에 대한 조인 조건 Pushdown은 작동하지만
union에는 작동하지 않는다는 뜻이다.
Group by 절을 포함한 뷰에 대한 조인 조건 Pushdown
- group by를 포함하는 뷰에 대한 조인 조건 Pushdown 기능은 11g에 와서야 제공 시작
* 나의 의문증
여기서 궁금한 것은 10g에서 부터는 group by가 있어도 view merging이 나타난다.
그런데 view merging을 하지 않고 조인 조건 pushdown 하는게 더 나은 경우가 있는 건지를
잘 모르겠다.
* 스칼라 서브쿼리에서 집계 함수
스칼라 서브쿼리를 사용하면서 스칼라 서브쿼리의 select 절에서 집계함수를 사용하고
스칼라 서브쿼리에서 메인 쿼리와 조인을 하게 되면 조인 조건으로 group by 된 값들과
동일한 결과가 나타난다.
이 부분에 로직에 대해서 생각해보았는데 스칼라 서브쿼리는 캐싱 기능을 사용해야 하고
그렇게 되면 입력 값이 같다면 그 결고 값들도 같을 것이다. 그리고 입력된 값들만
뭉쳐야 하고 자동으로 group by 된 형태로 계산이 될 것이다.
이 부분에 대해서는 확실한 검증이 되지는 않았지만 테스트 결과로 보아서
스칼라 서브쿼리에서 집계함수는 메인 쿼리와 조인 조건으로 자동으로 group by 된
결과물을 가진다고 생각하고 나는 생각하고 있다.
UNION 집합 연산을 포함한 뷰에 대한 조인 조건 Pushdown
- union 또는 union all을 포함한 뷰 쿼리 블록에 대한 조인 조건 Pushdown은 10g 이전부터
제공되던 기능이다.
- union all은 8.1.6부터, union은 10.1.0부터다.
- 9i에서 use_nl 힌트를 push_pred와 함께 사용하면 조인 조건 Pushdown 기능이 작동하지 않는
현상이 나타나므로 주의해야 한다.
- 이때는 push_pred 힌트만을 사용해야 하며, 조인 조건 pushdown은 NL조인을 전제로 하므로
굳이 use_nl 힌트를 사용할 필요는 없다.
Outer 조인 뷰에 대한 조인 조건 Pushdown
- outer 조인에서 Inner 쪽 집합이 뷰 쿼리 블록일 때, 뷰 안에서 참조하는 테이블 개수에 따라
옵티마이져는 다음 2가지 방법 중 하나를 선택한다.
( 뷰 안에서 참조하는 테이블 개수에 따라 )
● 뷰 안에서 참조하는 테이블이 단 하나일때, 뷰 Merging을 시도한다.
● 뷰 내에서 참조하는 테이블이 두 개 이상일 때, 조인 조건식을 뷰 안쪽으로 Pushin하려고
시도한다.
* 좀 더 생각해 볼 점
p.513 에 있는 실행계획에서는 outer 조인이면 (+) 가 없는 쪽이 먼저 드라이빙 된다.
그런데 실행계획에서 가장 안쪽에 들어가 있는 것을 먼저 읽는다는 규칙을 생각하면
view 안에 테이블들을 먼저 읽은 것으로 생각된다.
그런데 사실 그 테이블을 먼저 읽으면 안된다. 쿼리에 대한 규칙 상이라면 그런데
이 부분을 규칙과도 연관되어서 해석해보자면 view안에 있는 테이블들을 먼저 읽어서
view를 먼저 정의 한다. 그러나 NL 조인 실행계획에서는 (+) 가 없는 쪽 테이블을
먼저 읽는 것으로 보아 NL 조인에서는 드라이빙 테이블이 다른 것으로 생각된다.
즉 view 안에 있는 테이블들을 먼저 읽어서 view를 규정하고 그 값을 기억한 후
NL 조인은 그에 따른 순선대로 진행된다는 것이 일단 지금 나의 생각이다.
- union 집합 연산자를 포함한 뷰에 대한 조인 조건 Pushdown은 10g부터 비용기반으로
작동하기 시작했지만 지금 설명한 Outer 조인 뷰에 대한 기능은 9i에서도 비용기반이었다.
'GROUP BY 절을 포함한 뷰에 대한 조인 조건 Pushdown'은 11g에 도입되면서부터
비용기반으로 작동한다.