메뉴 여닫기
개인 메뉴 토글
로그인하지 않음
만약 지금 편집한다면 당신의 IP 주소가 공개될 수 있습니다.
(새 문서: == NO_MERGE` 힌트를 사용하는 이유 == ## NO_MERGE 힌트의 기본 개념 # Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함. # 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법. <source lang=sql> -- 병합 전 (논리적 구조) SELECT * FROM ( SELECT employee_id, salary FROM employees WHERE department_id = 10 ) v WHERE v.salary > 5000; --...)
 
편집 요약 없음
 
(같은 사용자의 중간 판 21개는 보이지 않습니다)
1번째 줄: 1번째 줄:
== NO_MERGE` 힌트를 사용하는 이유 ==  
== NO_MERGE 힌트 ==  


## NO_MERGE 힌트의 기본 개념
::::{{핵심
 
|제목= '''NO_MERGE 힌트의 기본 개념'''
# Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함.  
|내용= - Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함.  
# 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법.
::- 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법.
 
::- NO_MERGE 힌트는 인라인뷰 나 WITH절 쿼리를 메인쿼리와 합치지 말고 별개로 수행하라는 힌트임.
<source lang=sql>
}}
::<source lang=sql>
-- 병합 전 (논리적 구조)
-- 병합 전 (논리적 구조)
SELECT * FROM (
SELECT * FROM (
24번째 줄: 25번째 줄:
=== NO_MERGE 힌트를 사용하는 주요 이유 ===
=== NO_MERGE 힌트를 사용하는 주요 이유 ===
==== 조인 순서 및 방법 제어 ====
==== 조인 순서 및 방법 제어 ====
* 뷰 병합이 일어나면 옵티마이저가 조인 순서를 재결정하는데, 이것이 비효율적일 수 있음.
::* 뷰 병합이 일어나면 옵티마이저가 조인 순서를 재결정하는데, 이것이 비효율적일 수 있음.


<source lang=sql>
::::<source lang=sql>
SELECT /*+ NO_MERGE(v) */  
SELECT /*+ NO_MERGE(v) */  
       d.department_name, v.avg_salary
       d.department_name, v.avg_salary
36번째 줄: 37번째 줄:
</source>
</source>


* 뷰를 먼저 구체화(Materialization)하여 집계를 수행한 후 조인하는 것이 효율적인 경우가 많습니다.
::* 뷰를 먼저 구체화(Materialization)하여 집계를 수행한 후 조인하는 것이 효율적인 경우가 많습니다.


==== 중복 작업 방지 ====
==== 중복 작업 방지 ====
* 병합 시 같은 테이블을 여러 번 접근하게 되는 경우를 방지합니다.
::* 병합 시 같은 테이블을 여러 번 접근하게 되는 경우를 방지합니다.


<source lang=sql>
::::<source lang=sql>
SELECT /*+ NO_MERGE(v) */
SELECT /*+ NO_MERGE(v) */
       v.*, t.additional_col
       v.*, t.additional_col
54번째 줄: 55번째 줄:


==== 집계 후 필터링 강제 ====
==== 집계 후 필터링 강제 ====
* 집계를 먼저 수행한 후 조건을 적용하고 싶을 때 사용.
::* 집계를 먼저 수행한 후 조건을 적용하고 싶을 때 사용.


<source lang=sql>
::::<source lang=sql>
SELECT /*+ NO_MERGE(summary) */
SELECT /*+ NO_MERGE(summary) */
       *
       *
68번째 줄: 69번째 줄:


==== ROWNUM 처리 보존 ====
==== ROWNUM 처리 보존 ====
*  뷰 내부의 ROWNUM 로직을 보존해야 할 때 필수적입니다.
::*  뷰 내부의 ROWNUM 로직을 보존해야 할 때 필수적입니다.
<source lang=sql>
::::<source lang=sql>
SELECT /*+ NO_MERGE(top_n) */
SELECT /*+ NO_MERGE(top_n) */
       e.employee_name, top_n.salary
       e.employee_name, top_n.salary
84번째 줄: 85번째 줄:
==== 분석 함수 결과 활용 ====
==== 분석 함수 결과 활용 ====


* 분석 함수(Window Function) 결과를 필터링 조건으로 사용할 때 필요.
::* 분석 함수(Window Function) 결과를 필터링 조건으로 사용할 때 필요.


<source lang=sql>
::::<source lang=sql>
SELECT /*+ NO_MERGE(ranked) */
SELECT /*+ NO_MERGE(ranked) */
       *
       *
95번째 줄: 96번째 줄:
</source>
</source>


[[category:oracle]]
=== 병렬 처리 최적화 ===
 
 
### 6. **병렬 처리 최적화**


뷰를 독립적으로 병렬 처리하고자 할 때 유용합니다.
::* 뷰를 독립적으로 병렬 처리하고자 할 때 유용합니다.


```sql
::::<source lang=sql>
SELECT /*+ NO_MERGE(v) PARALLEL(v, 4) */
SELECT /*+ NO_MERGE(v) PARALLEL(v, 4) */
       *
       *
110번째 줄: 108번째 줄:
       GROUP BY department_id) v
       GROUP BY department_id) v
WHERE v.cnt > 100;
WHERE v.cnt > 100;
```
</source>
 


## 실행 계획 확인 방법


```sql
{{요점
|배경색 = #f7d4063e
|선굵기 = 3px
|테두리색 = #de5a5a
|사이즈 = 100%
|둥굴기 = 4px
|스타일 = dashed
|내용 ='''* 실행 계획 확인 방법'''
<source lang=sql>
-- 병합 여부 확인
-- 병합 여부 확인
EXPLAIN PLAN FOR
EXPLAIN PLAN FOR
120번째 줄: 126번째 줄:


SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
```
</source>


실행 계획에서 `VIEW` 오퍼레이션이 보이면 뷰가 병합되지 않은 것입니다.
<center>'''(중요) 실행 계획에서 `VIEW` 오퍼레이션이 보이면 뷰가 병합되지 않은 것입니다.'''</center>
}}


## 주의사항
* 주의사항


- NO_MERGE를 사용하면 뷰 구체화 비용이 추가됩니다
- NO_MERGE를 사용하면 뷰 구체화 비용이 추가됩니다
131번째 줄: 138번째 줄:
- 통계 정보가 정확해야 올바른 판단이 가능합니다
- 통계 정보가 정확해야 올바른 판단이 가능합니다


DBA로서 튜닝 작업 시 특정 케이스에 대해 더 자세한 설명이 필요하시면 말씀해주세요!
 
 
[[category:oracle]]

2026년 1월 26일 (월) 11:34 기준 최신판

NO_MERGE 힌트

  vpn_key NO_MERGE 힌트의 기본 개념

  playlist_add_check- Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함.

- 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법.
- NO_MERGE 힌트는 인라인뷰 나 WITH절 쿼리를 메인쿼리와 합치지 말고 별개로 수행하라는 힌트임.
-- 병합 전 (논리적 구조)
SELECT * FROM (
    SELECT employee_id, salary 
    FROM employees 
    WHERE department_id = 10
) v
WHERE v.salary > 5000;

-- 병합 후 (실제 실행)
SELECT employee_id, salary
FROM employees
WHERE department_id = 10 
  AND salary > 5000;

NO_MERGE 힌트를 사용하는 주요 이유

조인 순서 및 방법 제어

  • 뷰 병합이 일어나면 옵티마이저가 조인 순서를 재결정하는데, 이것이 비효율적일 수 있음.
SELECT /*+ NO_MERGE(v) */ 
       d.department_name, v.avg_salary
FROM departments d,
     (SELECT department_id, AVG(salary) avg_salary
      FROM employees
      GROUP BY department_id) v
WHERE d.department_id = v.department_id;
  • 뷰를 먼저 구체화(Materialization)하여 집계를 수행한 후 조인하는 것이 효율적인 경우가 많습니다.

중복 작업 방지

  • 병합 시 같은 테이블을 여러 번 접근하게 되는 경우를 방지합니다.
SELECT /*+ NO_MERGE(v) */
       v.*, t.additional_col
FROM large_table t,
     (SELECT col1, col2, COMPLEX_FUNCTION(col3) as result
      FROM large_table
      WHERE expensive_condition = 'Y') v
WHERE t.key = v.col1;

뷰를 병합하면 `COMPLEX_FUNCTION`이나 비용이 큰 조건이 중복 실행될 수 있습니다.

집계 후 필터링 강제

  • 집계를 먼저 수행한 후 조건을 적용하고 싶을 때 사용.
SELECT /*+ NO_MERGE(summary) */
       *
FROM (SELECT department_id, COUNT(*) cnt, AVG(salary) avg_sal
      FROM employees
      GROUP BY department_id) summary
WHERE summary.cnt > 10;

병합되면 `HAVING cnt > 10`으로 변환되어 실행 계획이 달라질 수 있습니다.

ROWNUM 처리 보존

  • 뷰 내부의 ROWNUM 로직을 보존해야 할 때 필수적입니다.
SELECT /*+ NO_MERGE(top_n) */
       e.employee_name, top_n.salary
FROM employees e,
     (SELECT employee_id, salary
      FROM (SELECT employee_id, salary
            FROM employees
            ORDER BY salary DESC)
      WHERE ROWNUM <= 10) top_n
WHERE e.employee_id = top_n.employee_id;


분석 함수 결과 활용

  • 분석 함수(Window Function) 결과를 필터링 조건으로 사용할 때 필요.
SELECT /*+ NO_MERGE(ranked) */
       *
FROM (SELECT employee_id, salary,
             RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) rn
      FROM employees) ranked
WHERE rn <= 3;

병렬 처리 최적화

  • 뷰를 독립적으로 병렬 처리하고자 할 때 유용합니다.
SELECT /*+ NO_MERGE(v) PARALLEL(v, 4) */
       *
FROM (SELECT /*+ PARALLEL(e, 4) */
             department_id, COUNT(*) cnt
      FROM huge_employees_table e
      GROUP BY department_id) v
WHERE v.cnt > 100;



menu_book * 실행 계획 확인 방법
-- 병합 여부 확인
EXPLAIN PLAN FOR
SELECT /*+ NO_MERGE(v) */ ...

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
(중요) 실행 계획에서 `VIEW` 오퍼레이션이 보이면 뷰가 병합되지 않은 것입니다.


  • 주의사항

- NO_MERGE를 사용하면 뷰 구체화 비용이 추가됩니다 - 항상 실행 계획과 실제 수행 시간을 비교해야 합니다 - Oracle 버전에 따라 옵티마이저 동작이 다를 수 있습니다 - 통계 정보가 정확해야 올바른 판단이 가능합니다