편집 요약 없음 |
편집 요약 없음 |
||
| 1번째 줄: | 1번째 줄: | ||
== NO_MERGE 힌트를 사용하는 이유 == | == NO_MERGE 힌트를 사용하는 이유 == | ||
# Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함. | {{핵심 | ||
|제목= NO_MERGE 힌트의 기본 개념 | |||
|내용=# Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함. | |||
# 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법. | # 이는 인라인 뷰나 WITH 절의 쿼리를 메인 쿼리와 합쳐서 하나의 쿼리 블록으로 만드는 최적화 기법. | ||
}} | |||
::<source lang=sql> | ::<source lang=sql> | ||
-- 병합 전 (논리적 구조) | -- 병합 전 (논리적 구조) | ||
2026년 1월 26일 (월) 11:09 판
NO_MERGE 힌트를 사용하는 이유
vpn_key NO_MERGE 힌트의 기본 개념
playlist_add_check# Oracle 옵티마이저는 기본적으로 뷰 병합(View Merging) 을 수행함.
- 이는 인라인 뷰나 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;
- 6. **병렬 처리 최적화**
뷰를 독립적으로 병렬 처리하고자 할 때 유용합니다.
```sql 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; ```
- 실행 계획 확인 방법
```sql -- 병합 여부 확인 EXPLAIN PLAN FOR SELECT /*+ NO_MERGE(v) */ ...
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); ```
실행 계획에서 `VIEW` 오퍼레이션이 보이면 뷰가 병합되지 않은 것입니다.
- 주의사항
- NO_MERGE를 사용하면 뷰 구체화 비용이 추가됩니다 - 항상 실행 계획과 실제 수행 시간을 비교해야 합니다 - Oracle 버전에 따라 옵티마이저 동작이 다를 수 있습니다 - 통계 정보가 정확해야 올바른 판단이 가능합니다
DBA로서 튜닝 작업 시 특정 케이스에 대해 더 자세한 설명이 필요하시면 말씀해주세요!