개발

[DB SQL] JOIN · WITH 절을 활용한 쿼리 최적화

qwas15788hj 2025. 7. 31. 23:23

📝 상황

실무 중 약 600만 건이 넘는 데이터를 대상으로, 공간에 대한 사진 및 관련 메타데이터를 조회해야 했다. 초기(AS-IS) 쿼리가 단순한 테이블 간 JOIN 없이 WHERE 절로만 되어있었기에, 성능이 7초 이상 소요되어 개선이 필요했다. 이를 최적화 하기 위해 JOIN과 WITH(CTE)절을 사용하였다.

 

이에 아래와 같은 단계로 쿼리 최적화를 진행했다:

단계 구조 전략 시간 개선
1차 암시적 조인 + 직접 연산 모든 연산을 한 번에 처리 약 7초
2차 서브쿼리 분리 + 명시적 JOIN 집계 연산을 별도 처리 약 5초
3차 WITH 절 + 정렬 선처리 정렬 우선 처리 약 0.5초

 

💬 예시 전제 설명

본 예시에서는 600만 건의 데이터를 가진 테이블(주 테이블)을 customer, 조인 대상 테이블을 product로 가정하여 쿼리 구조를 작성 하였습니다.

 

✅ 1차 쿼리(AS-IS) – 기본 ANSI 스타일 (암시적 조인)

📌 형태: FROM A, B WHERE ... 식의 옛날 방식 ANSI SQL

  • 가장 기본적인 ANSI SQL 방식
  • 테이블 간 조인을 JOIN 키워드 없이 처리
* 예시 쿼리 *

SELECT *
FROM customer c, product p
WHERE c.id = p.c_id
AND c.address LIKE '서울%'
ORDER BY c.name;

 

📌 문제점

  • 연산이 한 번에 몰려 쿼리 비용이 높음
  • 특히, 데이터가 다수일 때, 정렬 + 조인이 겹치면 부하 발생

 

✅ 2차 쿼리 – 명시적 JOIN + 서브쿼리 분리

📌 형태: JOIN (SELECT ...) ON ... 형태의 명시적 ANSI SQL + 서브쿼리 구조

  • 메인 쿼리는 가볍게 조인 후 필요한 데이터만 정렬
* 예시 쿼리 *

SELECT *
FROM customer c
JOIN product p ON c.id = p.c_id
WHERE c.address LIKE '서울%'
ORDER BY c.name;

📌 개선점

  • 메인 쿼리 가볍고 유지보수 용이

 

✅ 3차 쿼리 – WITH 절 + 정렬 선처리 + ROW_NUMBER()

형태: WITH + 서브쿼리 + ROW_NUMBER() 구조의 최신 ANSI SQL + CTE 최적화 방식

  • 정렬을 먼저 처리한 결과를 WITH로 재사용
* 예시 쿼리 *

WITH sorted_customer AS (
    SELECT *
    FROM customer sc
    WHERE sc.address LIKE '서울%'
    ORDER BY sc.name
)
SELECT *
FROM sorted_customer c
JOIN product p ON c.id = p.c_id;

📌 최적화 포인트

  • WITH 절에서 정렬 우선 처리 → 정렬 비용 분리
  • 이후 JOIN만 수행해서 불필요한 연산 최소화

 

✍️ 느낀점

이번 경험을 통해, 단순히 인덱스와 같은 물리적 요소만이 아니라, SQL 구문을 어떻게 구성하고 작성하느냐에 따라서도 쿼리 성능에 큰 차이가 발생한다는 것을 체감할 수 있었다. 특히, 정렬과 집계 연산을 적절히 분리하고, WITH절 등 구조적인 SQL 문법을 잘 활용하는 것이 성능 최적화에 중요하다는 점을 배웠다.