반응형
MySQL 쿼리를 작성할 때 서브쿼리로 할까? 조인으로 할까? 이 고민, 정말 많이 해봤을 것이다. 둘 다 같은 결과를 내지만, 성능은 상황에 따라 천차만별이다. 어떤 경우에 서브쿼리가 유리하고, 어떤 경우에 JOIN이 성능상 우위를 가지는지 실행계획을 활용해 명확히 분석해보자.

📌 기본 구조 비교
✅ 서브쿼리 예시
SELECT name
FROM users
WHERE id IN (
SELECT user_id FROM orders WHERE amount > 5000
);
✅ JOIN 예시
SELECT u.name
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 5000;
결과는 같지만 성능은 다를 수 있다.
반응형
🔍 실행계획(EXPLAIN) 비교 분석
🔬 서브쿼리 실행계획
EXPLAIN
SELECT name
FROM users
WHERE id IN (
SELECT user_id FROM orders WHERE amount > 5000
);
- users 테이블을 탐색하면서 서브쿼리를 반복적으로 수행 (비효율적)
- MySQL 5.x에서는 특히 상관 서브쿼리일 경우 Nested Loop로 처리되어 매우 느릴 수 있음
🔬 JOIN 실행계획
EXPLAIN
SELECT u.name
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.amount > 5000;
- orders.amount에 인덱스가 있으면 range scan 적용
- users와 orders 조인을 통해 한 번에 결과 집합 생성
📈 비교 요약
| 항목 | 서브쿼리 방식 | JOIN 방식 |
| 구조 | 반복 실행 | 병합 수행 |
| 성능 | 느림 (특히 많은 행일 때) | 빠름 |
| 확장성 | 복잡한 로직에 유리 | 구조가 직관적 |
| 인덱스 활용 | 제약 있음 | 인덱스 효율적으로 활용 가능 |
반응형
🧠 실무 팁: 언제 서브쿼리? 언제 JOIN?
| 상황 | 추천 방식 | 설명 |
| 단순 포함 조건 | JOIN | IN → JOIN 변환 시 빠름 |
| 복잡한 조건 필터링 | 서브쿼리 | 집계나 필터가 많을 때 명확함 |
| 뷰(View) 기반 필터링 | JOIN | 실행 최적화 쉬움 |
| 외부 SELECT 참조가 필요한 경우 | 서브쿼리 | 상관 서브쿼리 사용 가능 |
💡 상관 서브쿼리는 조심해야 한다
다음과 같은 형태는 성능 병목이 생길 수 있다:
SELECT name,
(SELECT COUNT(*) FROM orders o WHERE o.user_id = u.id) AS order_count
FROM users u;
위 쿼리는 users의 모든 row에 대해 orders 테이블을 반복 검색한다. 대량의 데이터가 있을 경우 매우 느려질 수 있다. 이럴 때는 다음처럼 JOIN + GROUP BY로 리팩토링하자:
SELECT u.name, COUNT(o.id) AS order_count
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id;
📌 결론
- 성능이 중요하면 JOIN이 기본값
- 간단한 조건 필터도 JOIN이 빠름
- 상관 서브쿼리는 최대한 피하기
- 필요시 EXPLAIN으로 직접 실행계획 확인
📎 참고 공식문서
MySQL Subquery Optimization:
https://dev.mysql.com/doc/refman/8.0/en/subquery-optimization.html
MySQL Join Optimization:
https://dev.mysql.com/doc/refman/8.0/en/join-optimization.html
반응형
'DB' 카테고리의 다른 글
| [MySQL] slow_query_log 주요 설정 옵션 설명 (long_query_time 등) ⚙️ (0) | 2025.07.04 |
|---|---|
| [MySQL] 슬로우 쿼리 로그 설정 방법 (my.cnf + RDS 포함) (1) | 2025.07.04 |
| [MySQL] 슬로우 쿼리 로그란? 원리와 기본 개념 총정리 (0) | 2025.07.04 |
| [MySQL] 실행계획 캐시와 쿼리 플랜 재사용 이해하기 🚀 (1) | 2025.07.04 |
| [MySQL] JOIN이 느릴 때 실행계획으로 튜닝하는 방법 (0) | 2025.07.04 |
| [MySQL] 실무 예제로 배우는 느린 쿼리 튜닝 실습 (EXPLAIN + INDEX 활용) (0) | 2025.07.04 |
| [MySQL] 효율적인 쿼리 작성법: 실행계획 튜닝을 고려한 SQL 설계 전략 🏗️ (1) | 2025.07.04 |
| [MySQL] 인덱스를 잘 써도 느린 이유? EXPLAIN으로 원인 분석하기 (1) | 2025.07.04 |