MySQL 실행 계획(Execution Plan)을 분석하는 것은 성능 최적화의 핵심 중 하나이다.
마치 하나의 프로젝트처럼, 문제 발견 → 실행 계획 확인 → 분석 → 개선안 도출 → 재검증의 흐름으로 진행해야 하고, 이를 통해 쿼리 성능을 체계적으로 개선할 수 있다.
이런 상황에서 우리는 쿼리를 단순히 튜닝하는 것이 아니라 MySQL이 내부적으로 쿼리를 어떻게 실행하는지를 알아야 한다. 이때 사용하는 도구가 실행 계획(EXPLAIN)이다.
EXPLAIN SELECT * FROM users WHERE id = 123;
MySQL 8.0 이상에서는:
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 123;
| 컬럼명 | 설명 |
|---|---|
id | SELECT의 순서 또는 중첩 수준 |
select_type | 쿼리 유형 (SIMPLE, PRIMARY, SUBQUERY 등) |
table | 액세스되는 테이블명 |
partitions | 사용된 파티션 |
type | 조인 방식 (매우 중요) |
possible_keys | 사용 가능한 인덱스 목록 |
key | 실제로 사용된 인덱스 |
key_len | 인덱스 길이 |
ref | 조인 시 참조된 열 |
rows | 예측된 스캔 row 수 |
filtered | 필터 후 남은 비율 (%) |
Extra | 추가 정보 (Using index 등) |
EXPLAIN SELECT * FROM orders WHERE customer_id = 101;
type: ref (좋음)key: idx_customer_idrows: 5Extra: Using where; Using indextype 분석조인 유형 우선순위 (좋음 → 나쁨):
system > const > eq_ref > ref > range > index > ALL
Extra 해석Using filesort: 정렬 → 디스크 작업 가능성 → 정렬 최적화 필요Using temporary: 임시 테이블 사용 → GROUP BY/DISTINCT 튜닝 필요Using index: Covering Index 사용 → 매우 좋음-- Covering index 예시
CREATE INDEX idx_email_name ON users (email, name);
SELECT * 지양EXPLAIN ANALYZE SELECT ...
또는
SET PROFILING = 1;
SELECT * FROM ...
SHOW PROFILES;
| 항목 | 개선 전 | 개선 후 |
|---|---|---|
| 실행 시간 | 3.5s | 0.4s |
| 스캔 row 수 | 100,000 | 1,000 |
| 조인 방식 | ALL | ref |
| 인덱스 사용 여부 | 없음 | 있음 |
목표:
order_summary쿼리의 응답 시간을 5초 → 0.5초로 줄이기
분석:customer_id에 인덱스 없고, FULL SCAN 발생
개선 조치:
customer_id인덱스 생성- 서브쿼리 제거, JOIN으로 재작성
결과: 실행 시간 0.3초, index range scan으로 전환됨
| 도구 | 설명 |
|---|---|
| MySQL Workbench | 시각화된 실행 계획 확인 가능 |
| Percona Toolkit | 슬로우 쿼리 분석 (pt-query-digest) |
| Performance Schema | MySQL 자체 프로파일링 |
SHOW PROFILE / SHOW STATUS | 상세 단계별 시간 측정 |
MySQL 실행 계획은 단순한 쿼리 속도 확인 도구가 아니다.
단계적으로 접근하면 다음과 같은 효과가 있다: