고급 SQL 튜닝
조건절 작성, 서브쿼리 변환, 불필요한 정렬 제거, 부분 범위 처리 같은 고급 튜닝 사고방식을 정리합니다.
서브쿼리 변환부분범위불필요한 정렬 제거 고급 튜닝은 SQL 모양을 바꾸는 일
인덱스를 추가하지 않아도 SQL 작성 방식만 바꿔 성능이 좋아질 수 있습니다. 고급 튜닝은 옵티마이저가 더 좋은 계획을 선택할 수 있도록 SQL을 명확하고 효율적인 형태로 고치는 작업입니다.
조건절을 인덱스 친화적으로 작성하기
컬럼을 함수로 감싸면 일반 인덱스를 사용하기 어려울 수 있습니다.
WHERE SUBSTR(phone, 1, 3) = '010'
가능하면 저장 구조와 조건을 함께 검토합니다. 날짜도 마찬가지입니다.
WHERE TO_CHAR(order_date, 'YYYY-MM-DD') = '2026-04-22'
대신 범위 조건을 사용하면 컬럼 원형을 유지할 수 있습니다.
WHERE order_date >= DATE '2026-04-22'
AND order_date < DATE '2026-04-23'
불필요한 정렬 줄이기
ORDER BY, GROUP BY, DISTINCT, UNION은 정렬이나 해시 작업을 유발할 수 있습니다. 꼭 필요한지 확인해야 합니다.
SELECT DISTINCT customer_id
FROM orders;
이미 customer_id가 유일한 결과를 만드는 구조라면 DISTINCT는 불필요할 수 있습니다. UNION도 중복 제거가 필요 없다면 UNION ALL이 더 단순합니다.
서브쿼리와 조인 변환
서브쿼리와 조인은 같은 결과를 만들 수 있는 경우가 많습니다.
SELECT *
FROM customer c
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.customer_id = c.customer_id
);
이 쿼리는 주문이 있는 고객을 찾습니다. 같은 목적을 조인으로 작성할 수도 있습니다. 어떤 방식이 빠른지는 데이터 양, 중복 여부, 인덱스, 옵티마이저 변환 가능성에 따라 달라집니다.
부분 범위 처리
사용자가 첫 화면에서 일부 결과만 보는 업무라면 전체 결과를 모두 만든 뒤 보여주는 것보다 필요한 만큼 먼저 가져오는 방식이 유리할 수 있습니다.
SELECT *
FROM orders
ORDER BY order_date DESC
FETCH FIRST 20 ROWS ONLY;
정렬 기준과 맞는 인덱스가 있으면 상위 일부만 빠르게 읽을 수 있습니다.
집계 튜닝
대량 집계는 많은 데이터를 읽습니다. 조건을 먼저 줄이고, 필요한 컬럼만 읽고, 적절한 그룹 기준을 사용하는 것이 중요합니다.
SELECT customer_id, SUM(amount)
FROM orders
WHERE order_date >= DATE '2026-01-01'
GROUP BY customer_id;
WHERE에서 기간을 먼저 줄이면 그룹화 대상도 줄어듭니다.
튜닝할 때 피해야 할 습관
- 실행 계획을 보지 않고 인덱스부터 추가합니다.
SELECT *로 필요 없는 컬럼까지 읽습니다.- 중복 제거가 필요 없는데
DISTINCT를 붙입니다. - 조건 컬럼에 함수를 습관적으로 적용합니다.
- 데이터 분포를 보지 않고 힌트를 고정합니다.
한 문장 요약
고급 튜닝은 같은 결과를 더 적게 읽고, 덜 정렬하고, 더 빨리 멈추도록 SQL을 바꾸는 일입니다.