🎯 개요
실무에서 데이터를 다루다 보면
쿼리가 느려서 기능이 제대로 안 되는 순간을 자주 겪게 됩니다.
저 역시 비슷한 상황을 여러 번 마주하면서
단순한 WHERE절 수정이 아닌,
DB 내부 동작을 기준으로 튜닝하는 감각을 조금씩 익혀가고 있습니다.
이번 글은
“직접 느려본 쿼리, 그리고 고치면서 배운 것”들을
정리해보는 자리입니다.
🔍 쿼리 튜닝이 왜 중요한가?
✅ 느린 쿼리는 곧 사용자 경험 하락
✅ 복잡한 SQL 구조는 성능 저하 + 유지보수 난이도 상승
✅ 단 한 줄의 WHERE절, JOIN 조건이 시스템 전체 병목의 원인이 될 수 있음
✅ 인덱스가 있어도 사용되지 않거나, 비효율적으로 작동하면 더 큰 문제
📋 자주 사용하는 튜닝 전략 5가지
전략 | 설명 |
1. 불필요한 SELECT 제거 | SELECT * 대신 필요한 컬럼만 선택 |
2. 인덱스 히트 유도 | WHERE절에 인덱스가 걸린 컬럼부터 사용 |
3. JOIN 방향 최적화 | 작은 테이블 먼저, 명확한 ON 조건 지정 |
4. 서브쿼리 → JOIN 또는 EXISTS | 인라인 뷰 줄이고, 명확한 조건 분리 |
5. LIMIT, OFFSET 과다 사용 주의 | 페이지네이션 성능 저하 → ID 기반 커서 처리 검토 |
🛠 실습 기반 쿼리 튜닝 예시
✅ BEFORE – 느린 쿼리
SELECT *
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.status = 'DELIVERED';
- users, orders 둘 다 100만 건 이상
- SELECT *, JOIN 순서, WHERE 조건 인덱스 미사용 → 전체 테이블 스캔 발생
✅ AFTER – 튜닝 후 개선
SELECt u.id, u.name, o.order_date
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE o.status = 'DELIVERED';
- 필요한 컬럼만 SELECT
- 인덱스가 걸린 orders.status부터 조건 적용
- JOIN 대상 테이블 순서도 최적화
→ 쿼리 실행 시간 2.8초 → 0.7초로 단축
✅ BEFORE – 느린 서브쿼리
SELECT name, email
FROM users
WHERE id IN (
SELECT user_id
FROM orders
WHERE order_date >= '2024-01-01'
AND status = 'CANCELLED'
);
- orders 테이블에 300만 건 이상 존재
- 서브쿼리에서 인덱스 미사용 + IN 조건으로 비효율적인 탐색 발생
- 실행 시간 5.2초 소요됨
✅ AFTER – JOIN + EXISTS로 튜닝
SELECT DISTINCT u.name, u.email
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE o.order_date >= '2024-01-01'
AND o.status = 'CANCELLED';
또는 좀 더 범위가 큰 경우에는 EXISTS 방식도 사용 가능:
SELECT name, email
FROM users u
WHERE EXISTS (
SELECT 1
FROM orders o
WHERE o.user_id = u.id
AND o.order_date >= '2024-01-01'
AND o.status = 'CANCELLED'
);
- JOIN을 사용하면서 user_id, order_date, status 복합 인덱스 유도
- 서브쿼리 제거로 옵티마이저가 계획 수립을 더 쉽게 함
→ 실행 시간 5.2초 → 1.1초로 개선
✅ 느낀 점
- IN 서브쿼리는 대량 테이블에서 매우 느릴 수 있음
- EXISTS나 JOIN으로 바꾸는 것이 성능적으로 훨씬 효율적
- 특히 JOIN + 인덱스 구조가 잘 맞을 경우, 성능 체감은 몇 배 차이남
- MyBatis에서 XML SQL 작성 시 조건 분리 및 튜닝이 명확히 보이도록 구조화하는 것이 매우 중요함
✍️ 마무리 요약
- 쿼리 튜닝은 단순 성능 문제가 아니라, 시스템의 전체 응답성과 연결되는 핵심 영역입니다.
- 실무에서는 쿼리가 느리다고 해서 DB 탓만 할 수 없고,
개발자 관점에서 구조를 설계하는 능력이 중요해집니다. - 결국은 데이터 구조 + 인덱스 + 조건 순서의 조합을 이해하고
경험을 바탕으로 튜닝 방향을 찾는 감각이 필요합니다. - 직접 느린 쿼리를 고쳐보면서 “왜 빨라졌는지”를 이해하는 과정이
쿼리 튜닝을 내 기술로 만드는 가장 좋은 방법임을 다시 한 번 느꼈습니다.
'컴퓨터 과학 > 데이터베이스' 카테고리의 다른 글
💻 [데이터베이스] ORM과 JPA 제대로 이해하기 (0) | 2025.05.09 |
---|---|
💻 [데이터베이스] 락(Lock)과 트랜잭션 격리 수준의 관계 (0) | 2025.05.09 |
💻 [데이터베이스] 인덱스 원리와 동작 구조 정리 (0) | 2025.05.09 |
💻 [데이터베이스] 정규화 vs 비정규화 차이 정리 (0) | 2025.05.09 |
💻 [데이터베이스] 트랜잭션 격리 수준 (Isolation Level) (0) | 2025.04.29 |