PUSH JOIN PREDICATE

EXEM Knowledge Base

Jump to: navigation, 찾기

목차

[편집] 기본 정보

[편집] Parameter 정보


Syntax _PUSH_JOIN_PREDICATE
설정방법
  • Parameter File
  • ALTER SYSTEM SET "_PUSH_JOIN_PREDICATE" = TRUE|FALSE
  • ALTER SESSION SET "_PUSH_JOIN_PREDICATE" = TRUE|FALSE
버전 및 기본값
9iR2 10gR1 10gR2 11g
TRUE TRUE TRUE TRUE



[편집] 설명

_PUSH_JOIN_PREDIATE 파라미터는 Join Predicate를 View의 텍스트안으로 Push하는 기능을 결정한다. Oracle은 View를 사용하는 쿼리에 대해 우선적으로 Complex View Merging을 시도하고 이것이 불가능한 뷰에 대해서는 Join Predicate Pushing을 시도한다.

View Merging이 불가능한 뷰(Nonmergeable View)는 다음과 같은 기능을 사용하는 View를 의미한다.

  1. Set operators (UNION, UNION ALL, INTERSECT, MINUS)
  2. A CONNECT BY clause
  3. A ROWNUM pseudocolumn
  4. Aggregate functions (AVG, COUNT, MAX, MIN, SUM) in the select list

Oracle은 항상 Join Predicate Pushing을 시도하지만 View의 속성에 따라 불가능한 경우도 있음에 주의해야 한다. 가령 일반적으로 View가 UNION ALL 절이나 OUTER JOIN 절을 사용하면 Join Predicate Pushing이 이루어지지 않는다. Join Predicate Pushing이 작동하는 방식은 Oracle Version마다 다르기 때문에 반드시 Version별로 확인해 보아야 한다.

Oracle 10g에서는 Cost에 기반하여 Join Predicate Pushing기능을 제어하는 기능이 추가되었으며, _OPTIMIZER_PUSH_PRED_COST_BASED 파라미터로 사용 여부를 지정한다. 이 파라미터의 값은 기본값 True이다. 만일 9i 버전에서는 Join Predicate Pushing이 동작하여 Query의 성능이 좋았음에도 불구하고 10g로 업그레이드후 Join Predicate Pushing이 동작하지 않는다면 해당 파라미터의 값을 False로 변경함으로써 해결할 수 있다.

[편집] 참고 사항

[편집] Join Predicate Pushing의 적용 예

Join Predicate Pushing의 적용 예는 아래와 같다.

-- UNION 구문을 사용하는 View. UNION 구문에 의해 View Merging이 불가능하다.
CREATE VIEW two_emp_tables 
 (employee_id, last_name, job_id, manager_id, hire_date, salary, 
                                  commission_pct, department_id) AS 
 SELECT employee_id, last_name, job_id, manager_id, hire_date, salary, 

commission_pct, department_id

   FROM emp1 
  UNION  
 SELECT employee_id, last_name, job_id, manager_id, hire_date, 
                         salary, commission_pct, department_id 
   FROM emp2; 

 -- View를 액세하는 쿼리
 SELECT employee_id, last_name 
 FROM two_emp_tables 
 WHERE department_id = 50; 

-- 위의 쿼리는 Join Predicate Pushing에 의해 아래와 같이 변환된다.
 SELECT employee_id, last_name 
 FROM ( SELECT employee_id, last_name, job_id, manager_id, hire_date, 
                               salary, commission_pct, department_id 
          FROM emp1 
         WHERE department_id = 50   -- Predicate가 Subquery안으로 Push됨
         UNION 
         SELECT employee_id, last_name, job_id, manager_id, hire_date, 
                                salary, commission_pct, department_id 
          FROM emp2 
         WHERE department_id = 50 );   -- Predicate가 Subquery안으로 Push됨


[편집] 잘못된 Join Predicate Pushing에 의한 성능 저하

Join Predicate Pushing은 대단히 바람직한 기능이며, 일반적으로 성능을 개선시키는 효과가 있다. 하지만 특정 쿼리에서, 특히 복잡한 쿼리에서는 오히려 잘못된 실행 계획을 만드는 역효과를 가지고 있다. 이 경우에는 Join Predicate Pushing을 비활성화함으로써 문제를 해결할 수 있다. 다음과 같은 방법으로 비활성화할 수 있다.

-- _PUSH_JOIN_PREDICATE 파라미터를 False로 변경한다.
ALTER SESSION SET "_PUSH_JOIN_PREDICATE" = FALSE;
SELECT  *
 FROM employees e, (
       SELECT manager_id FROM employees) v
 WHERE e.manager_id = v.manager_id(+)  AND e.employee_id = 100;

-- NO_PUSH_PRED 힌트를 사용한다. 
SELECT  /*+ NO_PUSH_PRED(v) */ *
 FROM employees e, (
       SELECT manager_id FROM employees) v
 WHERE e.manager_id = v.manager_id(+)  AND e.employee_id = 100;


[편집] 관련된 정보

  1. NO_PUSH_PRED 힌트
  2. _COMPLEX_VIEW_MERGING 파라미터
  3. _OPTIMIZER_PUSH_PRED_COST_BASED 파라미터
  4. _OPTIMIZER_COST_BASED_TRANSFORMATION 파라미터
  5. _UNNEST_SUBQUERY 파라미터

[편집] 외부 참조

  1. http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96533/opt_ops.htm#1005784
  2. http://www.psoug.org/reference/hints.html