반응형
실제 운영환경에서 느린 쿼리(Slow Query)는 곧 서비스 지연으로 이어진다. 단순히 인덱스를 추가한다고 해결되지 않고, 실행계획(EXPLAIN)을 기반으로 구조적 원인 파악과 튜닝이 병행되어야 한다.

🏁 사전 준비: 테스트 테이블 생성
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
status VARCHAR(20),
created_at DATETIME,
INDEX idx_user_id (user_id),
INDEX idx_created_at (created_at)
);
그리고 약 10만 건 이상의 더미 데이터를 미리 삽입했다고 가정하자.
반응형
🐌 느린 쿼리 예제: 전체 테이블 스캔
SELECT * FROM orders
WHERE YEAR(created_at) = 2024
AND status = 'COMPLETED';
이 쿼리는 실행 속도가 매우 느리다. created_at에 인덱스가 있음에도 YEAR() 함수로 인해 인덱스가 무시된다.
🔎 EXPLAIN으로 실행계획 확인
EXPLAIN SELECT * FROM orders
WHERE YEAR(created_at) = 2024
AND status = 'COMPLETED';
Extra 항목에 Using where; Using temporary; Using filesort가 표시된다. 이는 인덱스 범위 검색이 안 되고, 정렬과 임시 테이블까지 발생했다는 의미다.
⚡ 성능 개선 방법 1: 함수 제거
SELECT * FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-12-31'
AND status = 'COMPLETED';
이렇게 바꾸면 created_at 인덱스를 정상적으로 사용할 수 있게 된다.
⚡ 성능 개선 방법 2: 복합 인덱스 추가
CREATE INDEX idx_status_created_at
ON orders(status, created_at);
WHERE 조건의 조합 순서에 맞춰 인덱스를 구성하면 복합 인덱스가 covering index로 작동할 수 있다.
반응형
🔍 튜닝 전후 실행계획 비교
| 항목 | BEFORE | AFTER |
| type | ALL (Full Table Scan) | range / ref |
| key | NULL | idx_status_created_at |
| rows | 100,000 이상 | 5,000 이하 |
| Extra | Using filesort | Using index |
type이 ALL인 경우 테이블 전체를 순회하므로, ref, range, const 등으로 개선해야 한다.
⚠️ 실무 팁: 느려지는 대표 패턴
- LIKE '%abc%' → 와일드카드 앞 위치는 인덱스 무시
- OR 조건 다중 필드 → 조건별 인덱스 결합 어려움
- JOIN 시 필터조건 누락 → 조인 후 필터링 발생
- ORDER BY + LIMIT에 인덱스 미적용 → filesort 발생
🛠️ INDEX가 있어도 느릴 때 체크포인트
- WHERE에 함수 또는 연산이 있는가?
- WHERE 컬럼이 인덱스에 포함되어 있는가?
- 복합 조건 순서가 인덱스 순서와 일치하는가?
- SELECT * 사용으로 인해 Covering Index 무효화된 건 아닌가?
반응형
✅ 최적화된 쿼리 완성 예시
SELECT id, user_id, status, created_at
FROM orders
WHERE status = 'COMPLETED'
AND created_at BETWEEN '2024-01-01' AND '2024-12-31'
ORDER BY created_at DESC
LIMIT 50;
위 쿼리는 idx_status_created_at 복합 인덱스가 완전히 활용되며, 정렬, 필터링, 페이징까지 한 번에 처리할 수 있는 형태로 구성된다.
📌 정리 요약
| 항목 | 내용 |
| 느린 원인 | WHERE 함수, 인덱스 미사용, SELECT *, ORDER BY filesort |
| 개선 방법 | WHERE 최적화, 복합 인덱스 구성, SELECT 컬럼 제한, LIMIT 최적화 |
| EXPLAIN 활용 | 쿼리 실행방식 확인, rows/Extra 주의 깊게 보기 |
📎 참고 공식문서
MySQL Optimizing Queries:
https://dev.mysql.com/doc/refman/8.0/en/query-optimization.html
반응형
'DB' 카테고리의 다른 글
| [MySQL] 슬로우 쿼리 로그란? 원리와 기본 개념 총정리 (0) | 2025.07.04 |
|---|---|
| [MySQL] 실행계획 캐시와 쿼리 플랜 재사용 이해하기 🚀 (1) | 2025.07.04 |
| [MySQL] 서브쿼리 vs JOIN 성능 비교와 실행계획으로 분석하기 (1) | 2025.07.04 |
| [MySQL] JOIN이 느릴 때 실행계획으로 튜닝하는 방법 (0) | 2025.07.04 |
| [MySQL] 효율적인 쿼리 작성법: 실행계획 튜닝을 고려한 SQL 설계 전략 🏗️ (1) | 2025.07.04 |
| [MySQL] 인덱스를 잘 써도 느린 이유? EXPLAIN으로 원인 분석하기 (1) | 2025.07.04 |
| [MySQL] Extra 컬럼에 자주 뜨는 문구 해석법 (Using temporary 등) 🧐 (1) | 2025.07.04 |
| [MySQL] key vs possible_keys vs rows 차이점 제대로 알기 🔍 (0) | 2025.07.04 |