쿼리가 느릴 때 추측으로 인덱스를 더하지 말고, 먼저 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을 직접 실행하고 인덱스 추가 전후의 실행계획 변화를 확인하는 실습은 데이터베이스 트랙에서 무료로 할 수 있습니다.