MySQL에서 성능 튜닝을 하기 위해 가장 먼저 살펴봐야 할 도구는 EXPLAIN이다. 특히 EXPLAIN 명령어가 출력하는 주요 컬럼인 type, key, rows, Extra의 의미를 정확히 파악해야 실행계획 기반 쿼리 최적화가 가능하다.
쿼리의 실행 전략을 분석하고, 병목 구간을 찾아내며, 인덱스가 잘 활용되고 있는지를 파악하기 위해 이 컬럼들에 대한 정확한 해석 능력이 필수이다.

🧱 type: 접근 방식의 효율성 판단 기준
type은 MySQL이 테이블에 접근하는 방법을 의미하며, 성능에 매우 큰 영향을 미치는 컬럼이다. 아래로 갈수록 성능이 떨어진다.
| type 값 | 설명 |
| system | 단 하나의 행만 처리하는 가장 빠른 방식 |
| const | 상수 비교 수준의 효율적인 처리 |
| eq_ref | 조인에서 PK 또는 Unique Key로 정확히 일치하는 경우 |
| ref | 인덱스를 사용하지만 여러 행이 걸리는 경우 |
| range | 인덱스 범위 검색 (예: BETWEEN, >, <) |
| index | 테이블 전체를 인덱스만으로 순회 (Index Full Scan) |
| ALL | 테이블 전체를 스캔하는 최악의 경우 |
🔔 ALL 타입이 나오면 인덱스가 작동하지 않았다는 의미이므로 즉시 튜닝이 필요하다.
🔑 key: 실제 사용된 인덱스 확인
key 컬럼은 쿼리 실행 시 실제로 사용된 인덱스를 나타낸다. 이 값이 NULL이라면, 인덱스가 사용되지 않았다는 뜻이다.
예시:
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
결과:
| key |
| email_index |
✅ email_index가 사용되고 있으므로 성능상 문제는 적다.
반면 key가 NULL로 출력되면 아래의 사항을 점검해야 한다.
- WHERE 조건절이 인덱스 컬럼을 제대로 사용하고 있는가
- 함수가 사용되어 인덱스가 무력화되고 있지 않은가
- 데이터 분포가 너무 균등해서 인덱스가 비효율적인가
📊 rows: 예측되는 레코드 수
rows는 MySQL이 해당 쿼리를 수행하기 위해 스캔할 것으로 예상하는 행의 수이다. 수치가 클수록 I/O 비용이 커진다.
EXPLAIN SELECT * FROM orders WHERE order_status = 'DONE';
| rows |
| 18235 |
❗ 예상 스캔 수가 수만 건 이상이라면 인덱스 최적화를 반드시 고려해야 한다.
단, 이 값은 통계 정보 기반의 추정치이므로 100% 정확하진 않지만 튜닝 기준으로 삼기엔 충분하다.
🧾 Extra: 추가적인 실행 정보
Extra 컬럼은 쿼리 실행 시 MySQL이 수행하는 추가 작업에 대한 정보를 보여준다. 다음과 같은 값이 자주 나타난다.
| Extra 값 | 의미 |
| Using where | WHERE 조건이 필터로 사용됨 |
| Using index | 인덱스 커버링으로 테이블 접근 없이 처리 |
| Using temporary | 임시 테이블 생성 (비효율) |
| Using filesort | 정렬 작업을 따로 수행 (성능 저하 유발) |
| Using join buffer | 조인 버퍼 사용 (인덱스 미사용 조인) |
🔎 Using temporary, Using filesort 등이 보인다면 정렬 조건이나 조인 방식을 점검해야 한다.
🧠 실무 팁: 이 4가지만 분석해도 80%는 해결된다
실제 실무에서는 다음과 같은 방식으로 이 4개 컬럼을 분석하면 성능 문제를 빠르게 진단할 수 있다.
- type이 ALL이면 인덱스 적용 여부부터 체크
- key가 NULL이면 WHERE 절 점검 및 인덱스 재설계
- rows 수치가 크면 레코드 스캔 비용 증가 → 성능 저하
- Extra에 filesort, temporary가 있다면 정렬·그룹 조건 재검토
이러한 패턴 분석을 통해 불필요한 전체 스캔을 제거하고, 효율적인 인덱스를 유도할 수 있다.
📚 공식 문서 참고
'DB' 카테고리의 다른 글
| [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 |
| [MySQL] EXPLAIN이란? 실행계획을 확인하는 이유와 기본 구조 정리 🔍 (1) | 2025.07.04 |
| [MySQL] 실무에서 인덱스가 무시되는 이유와 해결법 완전 분석 (0) | 2025.07.03 |
| [MySQL] EXPLAIN으로 인덱스 성능 튜닝하는 법 (실행계획 완전 분석) (0) | 2025.07.03 |
| [MySQL] 인덱스 설계 가이드: 실무에서 실패하지 않는 인덱스 전략 🛠️ (0) | 2025.07.03 |