728x90
이슈)
새로운 개발 건 때문에 부하 정도를 러프하게라도 알아보려고 일주일치에 대한 통계를 내는 쿼리를 작성을 하던 도중,,,
실행 계획을 보니 빨간 글자가 너무 많았다.(대충 쿼리를 잘못짜서 실행하면 속 터진다... 라는 일종의 경고문..)
쿼리 구조는 테이블 A에 있는 값과 테이블 B, C, D 각각을 join 하고 group by를 사용해 집계함수를 쓰는 것이였다.
속도가 너무 느려 방법이 없을까 하다가 WITH절을 사용했는데 한번 정리해본다.
WITH절
→ 쿼리 앞부분에 하위 쿼리를 미리 정의해두고, 이후 메인 쿼리에서 미리 정의한 쿼리를 참조할 수 있게 해준다.
일종의 임시 뷰(temporary view) 역할을 한다고 생각하면 된다.
장점
- 쿼리 가독성 향상 : 복잡한 서브쿼리를 여러 번 쓰지 않고, 이름을 붙여 재사용 가능
- 성능 최적화 : 옵티마이저가 공통 서브쿼리를 한 번만 수행하도록 할 수 있음
- 재귀 쿼리 지원 : WITH + CONNECT BY 없이도 계층형 테이터를 재귀적으로 조회할 수 있음(Oracle 11g 이상)
WITH subquery_name AS (
SELECT ...
FROM ...
WHERE ...
)
SELECT *
FROM subquery_name
WHERE ...;
사용 예시)
1) 기본적인 서브쿼리 팩터링
WITH dept_avg AS (
SELECT department_id, AVG(salary) AS avg_sal
FROM employees
GROUP BY department_id
)
SELECT e.employee_id, e.salary, d.avg_sal
FROM employees e
JOIN dept_avg d ON e.department_id = d.department_id
WHERE e.salary > d.avg_sal;
2) 다중 서브쿼리 정의
WITH
high_sal AS (
SELECT employee_id, salary FROM employees WHERE salary > 10000
),
low_sal AS (
SELECT employee_id, salary FROM employees WHERE salary <= 10000
)
SELECT * FROM high_sal
UNION ALL
SELECT * FROM low_sal;
재귀적 WITH(Oracle 11g~)
→ 계층 구조 데이터를 재귀적으로 탐색할 수 있게 해주는 문법
구조)
WITH subquery_name (col1, col2, ...) AS (
-- 1. Anchor member (기준이 되는 최초 쿼리)
SELECT ...
FROM ...
WHERE ... -- 시작 조건
UNION ALL
-- 2. Recursive member (자기 자신을 다시 호출)
SELECT ...
FROM ...
JOIN subquery_name ON ... -- 재귀적으로 연결
)
SELECT *
FROM subquery_name;
예제) 숫자 생성시 (1 ~ 10 까지)
WITH numbers (n) AS (
SELECT 1 FROM dual -- Anchor
UNION ALL
SELECT n + 1 -- Recursive
FROM numbers
WHERE n < 10
)
SELECT * FROM numbers;
※주의할 점
- 무한 루프 방지 → 반드시 (종료 조건 WHERE절 필요)
- 성능
- 큰 데이터셋에서는 인덱스와 필터링 조건을 잘 걸어줘야 함.
728x90
'DB > Oracle' 카테고리의 다른 글
| [Oracle] Where절에서 괄호 우선순위가 동작하지 않는 경우 (옵티마이저) (0) | 2025.10.16 |
|---|---|
| [Oracle] EXISTS 란? (0) | 2025.10.16 |
| [Oracle] NVL, DECODE, COALESCE (0) | 2025.10.16 |
| [Oracle] 옵티마이저 힌트 LEADING 과 INDEX_SS (0) | 2025.10.16 |
| [Oracle] INSERT 내부에 SELECT절 (0) | 2025.10.16 |