← 아티클 목록

슬로우 쿼리, EXPLAIN 읽는 법 — 인덱스가 안 타는 이유

2026-06-29#database#MySQL#성능#인덱스

쿼리가 느릴 때 추측으로 인덱스를 더하지 말고, 먼저 EXPLAIN으로 옵티마이저가 실제로 어떻게 실행하는지를 봅니다. 쿼리 앞에 EXPLAIN만 붙이면 됩니다.

SQL
EXPLAIN SELECT * FROM orders WHERE user_id = 42 AND status = 'paid';

먼저 보는 4개 컬럼

컬럼의미위험 신호
type접근 방식ALL(풀스캔)이면 인덱스 못 탐
key실제 사용된 인덱스NULL이면 인덱스 미사용
rows검사 예상 행 수클수록 비쌈
Extra부가 정보Using filesort, Using temporary 주의

type은 좋은 순서로 대략 const > ref > range > index > ALL. ALL이 보이면 그 테이블을 통째로 스캔한다는 뜻이라 1순위 점검 대상입니다.

인덱스가 안 타는 흔한 패턴

① 컬럼에 함수·연산을 씌움

SQL
WHERE DATE(created_at) = '2026-06-29'   -- 인덱스 못 탐
WHERE created_at >= '2026-06-29' AND created_at < '2026-06-30'  -- 탐

② 앞에 와일드카드 LIKE LIKE '%검색'은 인덱스를 못 탑니다. LIKE '검색%'는 탑니다.

③ 복합 인덱스의 순서(선두 컬럼 규칙) (user_id, status) 인덱스는 user_id 조건이 있어야 효과적입니다. status만으로 조회하면 인덱스를 제대로 못 씁니다.

④ 타입 불일치 암묵 변환 문자열 컬럼에 숫자로 조회(WHERE phone = 1012345678)하면 형변환 때문에 인덱스를 못 탈 수 있습니다.

Extra의 경고

  • Using filesort — 정렬을 위해 별도 작업. ORDER BY 컬럼을 인덱스로 커버하면 사라짐.
  • Using temporary — 임시 테이블 생성(GROUP BY/DISTINCT). 큰 데이터에서 비쌈.
  • Using index — 인덱스만으로 해결(커버링 인덱스). 좋은 신호.

순서대로 본다

SQL
EXPLAIN <쿼리>;        -- type=ALL, key=NULL 먼저 확인
SHOW INDEX FROM <테이블>;  -- 어떤 인덱스가 있는지

type=ALL 또는 key=NULL이면 위 4가지 패턴 중 하나일 가능성이 높습니다.


EXPLAIN을 직접 실행하고 인덱스 추가 전후의 실행계획 변화를 확인하는 실습은 데이터베이스 트랙에서 무료로 할 수 있습니다.