현재 선택한 SQL 과정

SQLP 이론 학습

이론 목록으로 돌아가기

View Merging·Predicate Pushdown: Query Block 통합과 조건 조기 적용

View를 합치거나 조건을 내부로 밀어 읽을 Row를 줄이는 두 변환과 적용 제한을 비교합니다.

예상 읽기 23

핵심 요약

View Merging과 Predicate Pushdown은 모두 View·Inline View의 경계를 최적화하지만, 바꾸는 대상이 다릅니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
View Merging
→ View Query Block을 바깥 Query Block과 통합
→ View 내부 Table과 바깥 Table을 하나의 Join Graph에서 검토
→ Join Order·Access Path·다른 Transformation 후보 확대

Predicate Pushdown
→ View Query Block이 남아 있어도 바깥 Predicate를 View 내부에 적용
→ 내부 Scan·Join·Group에 전달되는 행을 조기에 감소

이때 다음 세 개념을 분리해야 합니다.

  • 일반 Filter Predicate Pushdown: 바깥 Filter 조건을 Merge되지 않은 View 안으로 이동
  • Join Predicate Pushdown(JPPD): 바깥 Row의 Join Key를 View 내부 Access에 전달해 View를 상관 방식으로 탐색
  • Materialization: View 또는 공통 결과를 Temporary Object에 저장한 뒤 다시 읽는 실행 방식

실행계획의 VIEW는 논리 Row Source 또는 Optimizer가 만든 Projection View일 수 있으므로, VIEW가 보인다는 사실만으로 “Merge 실패”나 “TEMP 저장”을 단정하면 안 됩니다. Query Block·Alias·Predicate Information·Outline·TEMP TABLE TRANSFORMATION·Runtime Statistics를 함께 확인해야 합니다.

학습 목표

이 이론을 학습한 뒤에는 다음을 설명할 수 있어야 합니다.

  1. View Merging과 Predicate Pushdown의 차이를 구분한다.
  2. Query Block 통합이 Join Order와 Access Path 후보를 넓히는 이유를 설명한다.
  3. Simple View Merging과 Complex View Merging의 적용 범위를 구분한다.
  4. 복합 Merging 후에도 Projection View가 남을 수 있음을 이해한다.
  5. VIEW Operation과 Materialization을 구분한다.
  6. Set View에 Filter Predicate가 Push될 때 Branch별 Access 기회를 설명한다.
  7. Grouping Key 조건과 Aggregate 결과 조건의 평가 시점을 구분한다.
  8. 일반 Predicate Pushdown과 Join Predicate Pushdown을 구분한다.
  9. Outer Join의 ON·WHERE Predicate가 행 보존 의미에 미치는 영향을 설명한다.
  10. MERGE, NO_MERGE, PUSH_PRED, NO_PUSH_PRED, QB_NAME을 비교 실험에 사용한다.
  11. 실제 Cursor의 Starts, A-Rows, Buffers로 반복 비용을 평가한다.

1. Query Block 경계와 최적화 공간

다음 Inline View는 부서와 위치를 Join합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT e.employee_id,
       v.department_name,
       v.city
FROM   employees e
JOIN   (
         SELECT d.department_id,
                d.department_name,
                l.city
         FROM   departments d
         JOIN   locations l
           ON   l.location_id = d.location_id
       ) v
  ON   v.department_id = e.department_id
WHERE  e.last_name = :last_name;

View가 Merge되지 않으면 개념적으로 다음과 같은 경계가 유지됩니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
OUTER QUERY BLOCK
├─ EMPLOYEES
└─ VIEW V
   ├─ DEPARTMENTS
   └─ LOCATIONS

Optimizer는 View 내부 Subplan과 바깥 Block을 별도로 다뤄야 하므로, View 내부 Table과 바깥 Table을 자유롭게 섞는 Join Order가 제한될 수 있습니다.

View Merging이 유효하고 유리하면 내부 Query Block이 바깥 Block에 통합됩니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
MERGED QUERY BLOCK
├─ EMPLOYEES
├─ DEPARTMENTS
└─ LOCATIONS

이제 세 Table을 하나의 Join Graph에서 검토할 수 있으므로 다음 후보가 늘어날 수 있습니다.

  • EMPLOYEES의 선택적인 조건을 먼저 사용하는 Join Order
  • View 내부 Table과 바깥 Table 사이의 Index Nested Loops
  • Merging 후 새로 가능해진 Join Elimination이나 Predicate 이동
  • 전체 Cardinality를 기준으로 한 다른 Join Method

View Merging은 저장된 SQL Text를 수동으로 풀어쓰는 기능이 아니라 Optimizer 내부의 논리 Transformation입니다.


2. Simple View Merging

Simple View Merging은 주로 Select·Project·Join으로 구성된 View를 바깥 Query Block과 통합합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT e.employee_id,
       v.city
FROM   employees e
JOIN   (
         SELECT d.department_id,
                l.city
         FROM   departments d
         JOIN   locations l
           ON   l.location_id = d.location_id
       ) v
  ON   v.department_id = e.department_id
WHERE  e.last_name = 'Smith';

Merge 후의 동등한 개념 형태는 다음과 같습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT e.employee_id,
       l.city
FROM   employees e
JOIN   departments d
  ON   d.department_id = e.department_id
JOIN   locations l
  ON   l.location_id = d.location_id
WHERE  e.last_name = 'Smith';

Simple View Merging을 제한할 수 있는 대표 구조는 다음과 같습니다.

  • GROUP BY, Aggregate, DISTINCT
  • Set Operator
  • MODEL, CONNECT BY
  • SELECT 목록의 Subquery
  • Outer Join이 포함되어 추가적인 행 보존 조건을 만족하지 못하는 경우

이 목록은 “View Merging 전체가 영원히 불가능하다”는 뜻이 아닙니다. 일부 집계·DISTINCT View는 Complex View Merging의 후보가 될 수 있고, Merge되지 않더라도 Predicate Pushdown 같은 다른 Transformation은 가능할 수 있습니다.


3. Complex View Merging

Complex View Merging은 GROUP BY 또는 DISTINCT가 있는 View를 비용 기반으로 바깥 Query Block에 통합하는 Transformation입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT c.customer_id,
       v.total_amount
FROM   customers c
JOIN   (
         SELECT o.customer_id,
                SUM(o.amount) AS total_amount
         FROM   orders o
         GROUP BY o.customer_id
       ) v
  ON   v.customer_id = c.customer_id
WHERE  c.region_code = :region_code;

Optimizer는 다음과 같은 처리 순서를 비교할 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
A. ORDERS 전체를 고객별 집계
   → CUSTOMERS와 Join
   → REGION Filter

B. REGION 고객을 먼저 선택
   → 관련 ORDERS와 Join
   → 줄어든 행을 집계

어느 방식이 유리한지는 다음 요소에 따라 달라집니다.

  • Region 조건의 선택도
  • 고객별 주문 분포
  • Join 후 행 증가 또는 감소
  • 원래 Group 수와 집계 축소율
  • Join Key의 유일성과 바깥 Table의 Row 식별 가능성

복합 Merging은 GROUP BY를 무조건 뒤로 미루는 규칙이 아닙니다. 집계를 먼저 수행해 행 수를 크게 줄이는 편이 유리할 수도 있고, 선택적인 Join 뒤에 집계하는 편이 유리할 수도 있으므로 Cost와 Validity를 비교합니다.

GROUPING SETS, ROLLUP, PIVOT, CONNECT BY, MODEL 같은 구조는 Complex View Merging을 제한할 수 있습니다. Hint는 Cost나 Heuristic 때문에 거절된 후보를 시험할 수 있지만, 결과 동등성에 관한 Validity 제한을 없애지는 못합니다.


4. Projection View: VIEW가 보여도 Merging됐을 수 있다

복합 View Merging이 발생하면 원래 View의 Table들이 바깥 Query Block에 통합되지만, 실행계획에 Optimizer가 만든 VM_NWVW... 같은 Projection View가 남을 수 있습니다.

Projection View는 다음과 같은 경우에 나타날 수 있습니다.

  • DISTINCT View가 Merging된 경우
  • GROUP BY View가 집계·HAVING·Aggregate가 있는 바깥 Block과 Merging된 경우

이 View는 원래 Inline View가 그대로 독립 실행된다는 뜻이 아닙니다. Merging 뒤에도 중복 제거 또는 집계 의미를 보존하기 위해 Optimizer가 추가한 논리 Row Source일 수 있습니다.

따라서 다음 판단은 잘못될 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
실행계획에 VIEW가 있다
→ 원래 View는 Merge되지 않았다   (항상 성립하지 않음)

정확한 판별을 위해 다음을 함께 확인합니다.

  • Query Block Name / Object Alias
  • Outline Data의 Merging 관련 Hint
  • 원래 View 내부 Table의 Query Block 소속
  • Predicate Information의 조건 위치
  • Projection View 이름과 Operation 하위 구조

5. VIEW Operation과 Materialization 구분

다음 Plan은 View Row Source가 남아 있음을 보여 줍니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
VIEW
  HASH GROUP BY
    TABLE ACCESS FULL ORDERS

VIEW는 부모 Operation에 행을 전달하는 논리적 경계일 수 있습니다. 행을 Memory나 Temporary Tablespace에 저장했다가 다시 읽었다는 증거는 아닙니다.

Materialization은 다음과 같은 Operation에서 더 직접적으로 확인합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
TEMP TABLE TRANSFORMATION
  LOAD AS SELECT
  TABLE ACCESS FULL SYS_TEMP_...

분석할 때 다음 질문을 분리합니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
1. 원래 View Query Block이 Merging됐는가?
2. VIEW Row Source가 남아 Streaming되는가?
3. Projection View가 의미 보존용으로 생성됐는가?
4. 결과가 Temporary Object로 Materialize됐는가?

NO_MERGE Hint는 바깥 Query와 Inline View를 하나의 Query Block으로 합치지 않도록 지시합니다. 그러나 View 결과를 반드시 TEMP에 저장하라고 지시하는 Hint는 아닙니다.


6. 일반 Filter Predicate Pushdown

Merge할 수 없는 Set View에서도 바깥 Filter를 내부 Branch로 Push해 각 Branch의 Access를 개선할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT v.employee_id,
       v.last_name
FROM   (
         SELECT employee_id,
                last_name,
                department_id
         FROM   employees
         UNION ALL
         SELECT employee_id,
                last_name,
                department_id
         FROM   contract_workers
       ) v
WHERE  v.department_id = :department_id;

의미가 보존되면 개념적으로 다음과 같이 각 Branch에 조건을 적용할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT employee_id, last_name
FROM   employees
WHERE  department_id = :department_id
UNION ALL
SELECT employee_id, last_name
FROM   contract_workers
WHERE  department_id = :department_id;

각 Branch에서 다음 기회가 생길 수 있습니다.

  • DEPARTMENT_ID Index Range Scan
  • Partition Pruning
  • Branch별 Cardinality 감소
  • 상위 Set Operation으로 전달되는 Row 수 감소

핵심은 View가 Merge되지 않아도 Predicate가 내부 Access 또는 Filter에 사용될 수 있다는 점입니다. 실제 적용 여부는 Predicate Information에서 각 Base Access의 access·filter 조건을 확인합니다.


7. Aggregate View에서 Predicate 평가 시점

다음 View는 부서별 급여 합계를 계산합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT v.department_id,
       v.total_salary
FROM   (
         SELECT department_id,
                SUM(salary) AS total_salary
         FROM   employees
         GROUP BY department_id
       ) v
WHERE  v.department_id = 50;

DEPARTMENT_ID는 Grouping Key입니다. 결과 의미가 같으므로 집계 전에 Base Row를 DEPARTMENT_ID=50으로 줄일 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
EMPLOYEES에서 DEPARTMENT_ID=50 Filter
→ 해당 행만 Grouping·SUM

반면 다음 조건은 Aggregate 결과에 대한 조건입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
WHERE v.total_salary >= 1000000

이를 다음처럼 개별 사원 Row 조건으로 바꾸면 의미가 달라집니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
WHERE salary >= 1000000

Aggregate 결과 조건은 Group 계산 뒤 Filter하거나 동등한 HAVING으로 평가해야 합니다.

바깥 조건안전한 평가 시점의 기본 원칙
Grouping Key 등치·범위의미가 보존되면 Grouping 전 Base Access로 Push 가능
Aggregate 결과 조건Grouping 후 Filter 또는 동등한 HAVING
Analytic 결과 조건Window 계산 후 평가가 필요한 경우가 많음
Top-N 결과를 제한하는 조건정렬·행 제한 범위가 바뀌지 않는지 Validity 확인

Predicate를 안쪽으로 이동할 수 있는지는 “더 빨라 보이는가”가 아니라 변환 전후 결과가 같은가로 먼저 판단합니다.


8. Join Predicate Pushdown(JPPD)

Join Predicate Pushdown은 바깥 Query의 Join Key를 Merge되지 않은 View 내부로 전달하여, View를 Outer Row마다 상관 방식으로 탐색할 수 있게 하는 Transformation입니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT c.customer_id,
       v.total_amount
FROM   customers c
LEFT JOIN (
    SELECT o.customer_id,
           SUM(o.amount) AS total_amount
    FROM   orders o
    GROUP BY o.customer_id
) v
  ON v.customer_id = c.customer_id
WHERE c.region_code = :region_code;

개념적 동작은 다음과 같습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
선택된 고객 Row
→ CUSTOMER_ID를 View 내부로 전달
→ 해당 고객의 ORDERS만 탐색·집계
→ 고객 Row와 결합

Plan에는 다음과 같은 형태가 나타날 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
NESTED LOOPS OUTER
  CUSTOMERS
  VIEW PUSHED PREDICATE
    SORT GROUP BY
      TABLE ACCESS BY INDEX ROWID ORDERS
        INDEX RANGE SCAN ORDERS_CUSTOMER_IX

이 방식은 Outer 고객 수가 작고 고객별 주문 Probe가 선택적일 때 유리할 수 있습니다. 그러나 Outer Row가 많으면 View 내부 Row Source가 반복 실행돼 총 비용이 커질 수 있습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
JPPD 총 작업량
≈ Outer Row 수 × View 1회 처리 비용

일반 Filter Predicate Pushdown과 JPPD를 혼동하지 않습니다.

  • 일반 Filter Pushdown: DEPARTMENT_ID=:b1 같은 바깥 Filter를 View Branch 안으로 이동
  • JPPD: v.customer_id=c.customer_id 같은 Join Predicate를 View 내부 Access에 전달

Oracle의 PUSH_PRED·NO_PUSH_PRED Hint는 공식 문서상 Join Predicate를 View 안으로 Push하는 동작을 시험하거나 제한하는 Hint입니다. 모든 종류의 Filter Predicate 이동을 포괄적으로 강제하는 Hint라고 해석하지 않습니다.


9. JPPD Runtime Statistics 해석

다음은 VIEW PUSHED PREDICATE Row Source의 마지막 실행 통계 예시입니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
Starts  = 5,000
A-Rows  = 4,500
Buffers = 15,000

계산하면 다음과 같습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
A-Rows/Start  = 4,500 ÷ 5,000 = 0.9행/회
Buffers/Start = 15,000 ÷ 5,000 = 3블록/회

한 번의 Probe는 3 Buffers로 가벼워 보이지만 5,000회 반복되어 총 15,000 Buffers가 발생했습니다. 따라서 다음 두 관점을 함께 봅니다.

  • 총량: 전체 SQL이 사용한 Buffers·Physical Reads·Elapsed·TEMP
  • 1회당 비용: A-Rows ÷ Starts, Buffers ÷ Starts

Starts는 마지막 실행 중 해당 Operation이 시작된 횟수이며, A-Rows는 해당 Row Source가 출력한 누적 행 수입니다. Starts=0인 비활성 Adaptive Branch에는 1회당 나눗셈을 적용하지 않습니다.

JPPD 대안으로 View를 한 번 집계해 Hash Join하는 Plan이 선택될 수도 있습니다. 어느 쪽이 유리한지는 Outer Row 수, Probe 선택도, 집계 축소율, Memory·TEMP, 전체 Fetch 범위를 함께 비교해야 합니다.


10. Outer Join과 Predicate 위치

다음 두 SQL은 결과 의미가 다릅니다.

오른쪽 조건을 ON에 둔 경우

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT c.customer_id,
       o.order_id
FROM   customers c
LEFT JOIN orders o
  ON   o.customer_id = c.customer_id
 AND   o.status = 'PAID';

모든 고객을 보존하면서 PAID 주문만 연결합니다. PAID 주문이 없으면 오른쪽 Column이 NULL로 확장됩니다.

오른쪽 조건을 WHERE에 둔 경우

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT c.customer_id,
       o.order_id
FROM   customers c
LEFT JOIN orders o
  ON   o.customer_id = c.customer_id
WHERE  o.status = 'PAID';

미매칭 고객의 O.STATUSNULL이고 WHERE o.status='PAID'는 TRUE가 아니므로 해당 고객이 제거됩니다. 결과는 PAID 주문이 있는 고객만 남아 Inner Join과 가까운 의미가 됩니다.

Optimizer는 Preserved Row의 의미를 바꾸는 방식으로 Predicate를 임의 이동할 수 없습니다. Outer Join에서 Predicate Pushdown을 검토할 때는 다음을 확인합니다.

  • 어느 쪽 Table이 보존되는가?
  • 미매칭 Row가 NULL 확장되는 시점은 언제인가?
  • Predicate가 ON 조건인지 Join 후 WHERE Filter인지?
  • Push 후에도 보존 Row 수와 NULL 의미가 같은가?

11. Hint의 정확한 역할과 한계

다음처럼 Query Block 이름을 지정하면 비교 실험의 대상을 명확히 할 수 있습니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT /*+ GATHER_PLAN_STATISTICS QB_NAME(main_qb) */
       c.customer_id,
       v.total_amount
FROM   customers c
LEFT JOIN (
    SELECT /*+ QB_NAME(order_agg_qb) */
           o.customer_id,
           SUM(o.amount) AS total_amount
    FROM   orders o
    GROUP BY o.customer_id
) v
  ON v.customer_id = c.customer_id
WHERE c.region_code = :region_code;
Hint정확한 시험 목적
MERGE유효한 View의 Merging을 시험
NO_MERGEView Query Block 통합을 제한해 분리 Plan과 비교
PUSH_PREDJoin Predicate를 View 내부로 Push하는 후보를 시험
NO_PUSH_PREDJoin Predicate Pushdown을 제한
QB_NAMEQuery Block에 고유한 이름을 부여해 Hint 대상과 Plan Alias를 추적

주의점은 다음과 같습니다.

  • MERGE는 결과 동등성 Validity를 위반하는 Merging을 가능하게 하지 못합니다.
  • NO_MERGE는 Materialization을 항상 강제하지 않습니다.
  • PUSH_PRED는 일반 Filter Predicate 전체를 강제로 아래로 이동하는 만능 Hint가 아닙니다.
  • 같은 Query Block 이름을 중복 사용하거나 잘못된 Alias를 참조하면 Hint가 무시될 수 있습니다.
  • Hint가 SQL Text에 적혀 있다는 사실만으로 적용됐다고 단정하지 않고 실제 Cursor의 Outline·Alias·Note를 확인합니다.

12. 실제 Cursor에서 검증하는 방법

Runtime Statistics를 수집하도록 SQL을 실행한 뒤 실제 Cursor Plan을 확인합니다.

SQL코드 영역 안에서 좌우로 이동할 수 있습니다.
SELECT *
FROM TABLE(
    DBMS_XPLAN.DISPLAY_CURSOR(
        NULL,
        NULL,
        'ALLSTATS LAST +ALIAS +PREDICATE +OUTLINE +NOTE'
    )
);

ALLSTATS LAST는 마지막 실행의 I/O·Memory 관련 Runtime Statistics를 확인하는 데 사용합니다. 이를 보려면 GATHER_PLAN_STATISTICS Hint 또는 적절한 통계 수집 설정이 필요합니다.

검증 순서는 다음과 같습니다.

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
1. 원본 SQL의 View·Inline View와 Query Block을 표시한다.
2. ALIAS에서 Table이 어느 Query Block에 속하는지 확인한다.
3. OUTLINE에서 Merging·Push 관련 Hint를 확인한다.
4. PREDICATE에서 조건이 어느 access·filter에 적용됐는지 확인한다.
5. VIEW가 원래 View인지 Projection View인지 하위 구조와 이름을 확인한다.
6. TEMP TABLE TRANSFORMATION·LOAD AS SELECT 존재 여부를 확인한다.
7. Starts·A-Rows·Buffers·Memory·TEMP를 비교한다.
8. 결과 행 수, 첫 행 응답시간, 전체 Fetch 완료시간을 함께 검증한다.

EXPLAIN PLAN은 예상 Plan이며 실제 Bind, Adaptive 선택, 실행 통계가 반영된 실제 Cursor와 다를 수 있습니다. Transformation과 반복 작업량을 분석할 때는 실제 실행 후 DISPLAY_CURSOR를 우선합니다.


13. 혼동하기 쉬운 판단

혼동하기 쉬운 판단정확한 기준
View Merging과 Predicate Pushdown은 같은 변환이다Merging은 Query Block 통합, Pushdown은 경계를 유지한 조건 내부 적용이다
실행계획에 VIEW가 있으면 Merging되지 않았다복합 Merging 후 Projection View가 남을 수 있으므로 Alias·Outline·하위 구조를 확인한다
VIEW가 있으면 TEMP에 저장한다TEMP TABLE TRANSFORMATION, LOAD AS SELECT, SYS_TEMP_...를 확인한다
NO_MERGE는 Materialization Hint다Query Block 통합을 제한할 뿐 저장 방식을 항상 강제하지 않는다
PUSH_PRED는 모든 Filter Pushdown을 강제한다공식적으로 Join Predicate Pushdown을 지시하는 Hint다
Grouping Key와 Aggregate 결과 조건은 같은 시점에 Push할 수 있다Grouping Key는 집계 전 가능성이 있지만 Aggregate 결과는 Grouping 후 평가해야 한다
VIEW PUSHED PREDICATE는 항상 빠르다Outer Row 수와 View의 Starts, 총 Buffers를 함께 봐야 한다
Predicate는 안쪽으로 갈수록 항상 안전하다Outer Join·Aggregate·Analytic·Top-N은 평가 시점이 결과를 바꿀 수 있다

실전 적용 절차

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
1. View 한 행의 Grain과 Query Block 경계를 정의한다.
2. Simple Merging 후보인지 Complex Merging 후보인지 구분한다.
3. Merging 전후 중복·집계·Outer 보존 의미를 검증한다.
4. 바깥 조건이 Filter Predicate인지 Join Predicate인지 구분한다.
5. Grouping Key 조건과 Aggregate 결과 조건을 구분한다.
6. 실제 Cursor의 ALIAS·OUTLINE·PREDICATE로 변환 결과를 확인한다.
7. VIEW와 Projection View, TEMP Materialization을 구분한다.
8. Starts·A-Rows·Buffers의 총량과 1회당 비용을 계산한다.
9. MERGE·NO_MERGE·PUSH_PRED 비교는 한 번에 하나씩 수행한다.
10. 여러 Bind와 데이터 분포에서 결과 동등성과 성능을 회귀 검증한다.

핵심 정리

CODE코드 영역 안에서 좌우로 이동할 수 있습니다.
View Merging
→ View Query Block 통합
→ Join Order·Access Path·Transformation 후보 확대

Filter Predicate Pushdown
→ View가 남아 있어도 바깥 Filter를 내부 Branch에 적용
→ 내부 입력 행 감소 가능

Join Predicate Pushdown
→ 바깥 Join Key를 View 내부 Access에 전달
→ 선택적 Probe가 가능하지만 Starts가 증가할 수 있음

Projection View
→ Merging 후에도 의미 보존을 위해 VIEW가 남을 수 있음

검증
→ ALIAS·OUTLINE·PREDICATE·TEMP Operation·Starts·A-Rows·Buffers
스스로 확인하기

개념 확인 문제

문제를 누르면 바로 아래에서 정답과 해설을 확인할 수 있습니다.

01View Merging과 Predicate Pushdown의 가장 큰 차이는 무엇인가?
정답 및 해설

View Merging은 View Query Block을 바깥 Query Block과 통합하고, Predicate Pushdown은 View 경계가 남아 있어도 바깥 Predicate를 View 내부 Access나 Filter에 적용합니다.

02Simple View Merging과 Complex View Merging은 어떻게 다른가?
정답 및 해설

Simple View Merging은 주로 Select·Project·Join View를 통합하고, Complex View Merging은 GROUP BY·DISTINCT View를 Validity와 Cost에 따라 통합합니다.

03실행계획에 VIEW가 있어도 View Merging이 발생했을 수 있는 이유는 무엇인가?
정답 및 해설

복합 Merging 뒤에도 중복 제거나 집계 의미를 보존하기 위해 Optimizer가 VM_NWVW... 같은 Projection View를 만들 수 있기 때문입니다. 따라서 VIEW 존재만으로 원래 View의 Merging 여부를 판단하지 않습니다.

04VIEW Operation과 Materialization은 어떻게 구분하는가?
정답 및 해설

VIEW는 논리 Row Source일 수 있습니다. Materialization은 TEMP TABLE TRANSFORMATION, LOAD AS SELECT, SYS_TEMP_... Access 같은 Operation으로 확인합니다.

05Set View에 일반 Filter Predicate가 Push되면 어떤 Access 기회가 생기는가?
정답 및 해설

각 Branch에서 Index Range Scan, Partition Pruning, 조기 Filter, Branch별 Cardinality 감소가 가능해지고 상위 Set Operation으로 전달되는 Row가 줄 수 있습니다.

06Grouping Key 조건과 Aggregate 결과 조건의 평가 시점은 어떻게 다른가?
정답 및 해설

Grouping Key 조건은 결과 의미가 유지되면 Grouping 전에 Base Row를 줄일 수 있지만, Aggregate 결과 조건은 Group 계산 뒤 Filter하거나 동등한 HAVING으로 평가해야 합니다.

07일반 Filter Predicate Pushdown과 Join Predicate Pushdown은 어떻게 다른가?
정답 및 해설

일반 Filter Predicate Pushdown은 바깥 Filter 조건을 View 내부로 이동하고, Join Predicate Pushdown은 바깥 Row의 Join Key를 View 내부 Access에 전달해 View를 반복 탐색할 수 있게 합니다.

08Outer Join의 오른쪽 조건을 ON에서 WHERE로 옮기면 결과가 달라질 수 있는 이유는 무엇인가?
정답 및 해설

미매칭 오른쪽 Row는 NULL로 확장되는데, Join 후 WHERE 오른쪽_컬럼=값은 이 NULL 확장 Row를 제거하기 때문입니다. ON 조건은 왼쪽 Row를 보존하면서 연결할 오른쪽 Row만 제한합니다.

09NOMERGE와 PUSHPRED Hint의 정확한 역할은 무엇인가?
정답 및 해설

NO_MERGE는 바깥 Query와 Inline View의 Query Block 통합을 제한하며 TEMP 저장을 항상 강제하지 않습니다. PUSH_PRED는 공식적으로 Join Predicate를 View 안으로 Push하는 후보를 시험하는 Hint입니다.

10VIEW PUSHED PREDICATE Plan의 반복 비용을 어떤 통계와 계산으로 평가하는가?
정답 및 해설

View Root의 Starts, A-Rows, Buffers를 확인하고 A-Rows ÷ Starts, Buffers ÷ Starts를 계산합니다. 총 Buffers와 1회당 Probe 비용을 함께 비교해 반복 횟수 효과를 평가합니다.