PUSH_SUBQ
힌트는 스칼라 서브쿼리의 실행 시점을 앞당겨서 실행 성능을 최적화할 때 사용됩니다.즉, 스칼라 서브쿼리(Scalar Subquery) 내부의 프레디케이트(Predicate)를 메인 쿼리로 푸시(Push)하는 것을 강제하는 힌트입니다.
✅ 기본 사용법
SELECT e.empno, e.ename,
(SELECT /*+ PUSH_SUBQ */ d.dname
FROM dept d
WHERE d.deptno = e.deptno) AS department_name
FROM emp e
WHERE e.sal > 3000;
위 쿼리에서 PUSH_SUBQ
힌트를 사용하면, e.sal > 3000
조건이 메인 쿼리에서 적용된 후에 서브쿼리가 실행될 수 있도록 최적화됩니다.
✅ 언제 사용해야 하나?
- 스칼라 서브쿼리가 포함된 SQL에서 실행 성능을 향상시킬 때
- 메인 쿼리의 필터 조건이 적용된 후 서브쿼리를 실행하는 것이 더 효율적일 때
- 스칼라 서브쿼리가 여러 번 실행되는 것을 줄이고자 할 때
✅ 주의할 점
- 옵티마이저가 자동으로 푸시할 수 있는 경우도 있으므로 실행 계획을 먼저 확인하는 것이 좋음.
PUSH_SUBQ
힌트를 사용하면 서브쿼리가 먼저 실행되므로, 특정 경우에는 예상보다 더 많은 데이터가 처리될 수도 있음.- 스칼라 서브쿼리가 아닌 인라인 뷰(서브쿼리 테이블) 에는 적용되지 않음. (이 경우
PUSH_PRED
사용)
✅ 함께 사용하면 좋은 힌트
PUSH_PRED
→ 인라인 뷰(서브쿼리 테이블)에서 프레디케이트를 푸시할 때 사용.INLINE
→ 서브쿼리가 뷰로 변환되는 것을 방지하고 인라인 뷰로 유지하도록 강제할 때 사용.
🔹 예제: PUSH_PRED
과 비교
-- PUSH_PRED: 인라인 뷰에서 프레디케이트 푸시
SELECT /*+ PUSH_PRED */ *
FROM (
SELECT e.*, d.dname
FROM emp e
JOIN dept d ON e.deptno = d.deptno
) sub
WHERE sub.sal > 3000;
-- PUSH_SUBQ: 스칼라 서브쿼리에서 푸시
SELECT e.empno, e.ename,
(SELECT /*+ PUSH_SUBQ */ d.dname
FROM dept d
WHERE d.deptno = e.deptno) AS department_name
FROM emp e
WHERE e.sal > 3000;
→ PUSH_PRED
는 인라인 뷰에 적용, PUSH_SUBQ
는 스칼라 서브쿼리에 적용됨.
✅ 결론
PUSH_SUBQ
는 스칼라 서브쿼리의 실행 시점을 앞당겨 최적화할 때 사용.- 메인 쿼리의 필터링이 먼저 적용된 후 서브쿼리가 실행되도록 하여 불필요한 서브쿼리 호출을 줄일 수 있음.
- 인라인 뷰에는 적용되지 않으며, 인라인 뷰에는
PUSH_PRED
을 사용해야 함. - 옵티마이저의 기본 동작과 충돌할 수 있으므로, 실행 계획(EXPLAIN PLAN) 확인 후 적용 여부를 결정하는 것이 좋음.
✅ PUSH_SUBQ
vs. PUSH_PRED
차이점
힌트 | 설명 | 적용 대상 | 실행 최적화 방식 |
---|---|---|---|
PUSH_SUBQ | 스칼라 서브쿼리(Scalar Subquery)의 실행 시점을 앞당겨 성능 최적화 | SELECT 절의 서브쿼리 (스칼라 서브쿼리) | 서브쿼리를 메인 쿼리에서 먼저 실행하도록 강제 |
PUSH_PRED | 서브쿼리 내부로 프레디케이트(Predicate)를 푸시하여 불필요한 데이터 스캔을 줄임 | 인라인 뷰(Inline View) 또는 서브쿼리를 포함한 테이블 | WHERE 조건을 서브쿼리 내부로 푸시하여 필터링을 먼저 적용 |
🔹 차이점 이해하기 위한 예제
✅ 1. PUSH_SUBQ
사용 예제 (스칼라 서브쿼리)
SELECT e.empno, e.ename,
(SELECT /*+ PUSH_SUBQ */ d.dname
FROM dept d
WHERE d.deptno = e.deptno) AS department_name
FROM emp e
WHERE e.sal > 3000;
PUSH_SUBQ
를 사용하면,e.sal > 3000
조건이 먼저 적용된 후SELECT
절의 서브쿼리가 실행됨.- 즉, 스칼라 서브쿼리의 실행 횟수를 줄여 성능 최적화.
✅ 2. PUSH_PRED
사용 예제 (인라인 뷰)
SELECT /*+ PUSH_PRED */ *
FROM (
SELECT e.*, d.dname
FROM emp e
JOIN dept d ON e.deptno = d.deptno
) sub
WHERE sub.sal > 3000;
PUSH_PRED
를 사용하면sal > 3000
조건이 메인 쿼리가 아니라 서브쿼리 내부에서 먼저 적용됨.- 즉, 불필요한 데이터가 조인되기 전에 필터링이 되어 최적화.
🔹 PUSH_SUBQ
vs. PUSH_PRED
정리
구분 | PUSH_SUBQ | PUSH_PRED |
---|---|---|
적용 대상 | SELECT 절의 스칼라 서브쿼리 | FROM 절의 인라인 뷰 |
작동 방식 | 서브쿼리 실행을 앞당겨 메인 쿼리 필터 조건을 먼저 적용 | 서브쿼리 내부로 프레디케이트(Predicate)를 푸시하여 필터링을 먼저 적용 |
사용 목적 | 서브쿼리 실행 횟수를 줄여 불필요한 서브쿼리 호출을 줄임 | 서브쿼리 내부에서 먼저 필터링하여 불필요한 데이터 스캔을 줄임 |
적용 예제 | SELECT 절의 (SELECT ... FROM ...) | FROM 절의 (SELECT ... FROM ...) sub |
함께 사용 가능 힌트 | INLINE , UNNEST | INLINE , MERGE |
✅ 언제 어떤 힌트를 써야 할까?
상황 | 추천 힌트 |
---|---|
SELECT 절의 서브쿼리가 느려서 최적화가 필요할 때 | PUSH_SUBQ |
FROM 절의 서브쿼리가 WHERE 조건을 무시하고 너무 많은 데이터를 반환할 때 | PUSH_PRED |
🔹 결론
PUSH_SUBQ
→ 스칼라 서브쿼리(SELECT 절의 서브쿼리)를 메인 쿼리에서 먼저 실행하도록 강제
→ 서브쿼리 호출 횟수를 줄이는 데 유용PUSH_PRED
→ 인라인 뷰(FROM 절의 서브쿼리) 내부에서 프레디케이트를 미리 적용하도록 강제
→ 불필요한 데이터 스캔을 줄이고 성능을 최적화하는 데 유용
둘 다 실행 계획을 확인한 후, 성능 최적화가 필요한 경우에만 사용하는 것이 좋음! 🚀