메인 콘텐츠로 건너뛰기

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
쿼리가 느릴 때 첫 번째 행동은 EXPLAIN입니다. MySQL이 쿼리를 어떻게 실행할 계획인지 정확히 보여줍니다 — 어떤 인덱스를 사용하는지, 몇 행을 스캔할 것으로 예상하는지, 어디서 비싼 작업을 하는지. 읽을 수 있게 되면 거의 모든 느린 쿼리를 고칠 수 있습니다.

EXPLAIN 실행하기

아무 SELECT 앞에 EXPLAIN을 붙이세요:
MySQL은 쿼리의 테이블마다 한 행을 반환합니다. 조인에서는 여러 행을 받습니다 — 관련된 테이블마다 하나씩.

중요한 열

전체 EXPLAIN 행은 다음과 같습니다:
대부분의 열은 가끔 중요합니다. 다음 열들은 거의 항상 중요합니다:

type — MySQL이 테이블을 스캔하는 방식

가장 중요한 열입니다. 접근 방법을 알려주며, 가장 빠른 것부터 가장 느린 것 순으로: ALL이 고쳐야 할 것입니다. MySQL이 테이블의 모든 행을 읽고 있다는 뜻입니다. 백만 행짜리 테이블에서는 쿼리 실행마다 백만 번의 읽기입니다.

key — MySQL이 선택한 인덱스

NULL은 인덱스를 사용하지 않았다는 뜻입니다. possible_keys에 인덱스가 나열되어 있는데 key가 NULL이면, MySQL이 전체 스캔이 더 싸다고 판단한 것입니다 — 보통 테이블이 작거나 쿼리의 선택도가 충분하지 않기 때문입니다.

rows — 검사할 것으로 추정되는 행 수

보장이 아니라 추정치입니다. MySQL은 통계를 사용해 이 숫자를 만듭니다. rows: 1인 쿼리는 빠르고, 프로덕션 테이블에서 rows: 5000000은 문제입니다.

Extra — 추가 실행 세부 정보

Extra 열에는 중요한 플래그가 들어 있습니다: 큰 테이블에서 Using filesort와 Using temporary가 함께 나오면 위험 신호입니다.

실습 예제

두 가지 문제: 전체 테이블 스캔(ALL)과 filesort입니다. 복합 인덱스로 둘 다 고치세요(인덱스 설계 원칙은 MySQL 인덱스의 동작 방식을 보세요):
rows가 1,000,000에서 4,200으로 떨어졌습니다. type은 이제 ref — status에 대한 동등 조회입니다. 인덱스가 이미 각 status 값 안에서 행을 created_at 순으로 정렬하기 때문에 filesort가 사라졌습니다.

EXPLAIN ANALYZE

EXPLAIN ANALYZE는 쿼리를 실제로 실행하고 추정치와 함께 실제 시간을 반환합니다:
cost와 rows는 옵티마이저의 추정치입니다. actual time과 actual rows는 실제로 일어난 일입니다. 추정 행 수와 실제 행 수 사이의 큰 차이는 오래된 통계를 뜻합니다 — ANALYZE TABLE orders를 실행해 갱신하세요.

자주 묻는 질문

EXPLAIN과 커버링 인덱스의 관계는 무엇인가요?

Extra: Using index는 MySQL이 커버링 인덱스를 사용하고 있다는 뜻입니다 — 테이블 행을 읽지 않고 인덱스만으로 쿼리에 답할 수 있습니다. 읽기가 많은 테이블에서 가장 효과가 큰 최적화 중 하나입니다. 설계 방법은 MySQL의 커버링 인덱스를 보세요.

내 쿼리에 type: index가 나옵니다 — 괜찮은가요?

별로 그렇지 않습니다. type: index는 MySQL이 (테이블 대신) 전체 인덱스를 스캔했다는 뜻으로, ALL보다 빠르지만 여전히 전체 스캔입니다. 쿼리가 모든 행을 필요로 하지만 인덱스에서 그것을 충족할 수 있을 때 나타납니다. 큰 테이블에서 이것을 만난다면, 커버링 인덱스나 WHERE 절로 스캔 범위를 좁힐 수 있는지 확인하세요.

MySQL은 왜 내가 만든 인덱스를 무시하나요?

옵티마이저는 통계를 바탕으로 인덱스를 선택합니다. 테이블이 작으면 MySQL은 전체 스캔이 더 싸다고 판단할 수 있습니다. 통계가 오래되었으면 인덱스의 선택도를 과소평가할 수 있습니다. ANALYZE TABLE을 실행해 통계를 새로 고친 뒤 EXPLAIN을 다시 확인하세요.

INSERT, UPDATE, DELETE에 EXPLAIN을 사용할 수 있나요?

예 — MySQL 8.0 이상에서 EXPLAIN은 모든 DML 문에 동작합니다. 출력은 수정될 행에 대한 접근 방법을 보여주며, UPDATE나 DELETE가 느릴 때 유용합니다. 어떤 쿼리를 먼저 EXPLAIN할지 찾아야 한다면, MySQL 슬로우 쿼리 로그가 서버에서 가장 느린 쿼리를 수집하고 총 시간순으로 순위를 매깁니다.

문제 해결

함께 보기