DB

[MySQL] 인덱스를 잘 써도 느린 이유? EXPLAIN으로 원인 분석하기

인생아 2025. 7. 4. 08:12
반응형

인덱스를 걸었는데도 쿼리가 느릴 때가 있다. 실제로 많은 개발자가 인덱스를 적용했음에도 성능이 개선되지 않는 현상을 경험한다. 이런 경우에는 EXPLAIN을 통해 실행계획을 분석하고 인덱스가 실제로 사용되는지, 비효율적인 접근이 있는지를 체크해야 한다.

🔍 인덱스를 걸었는데 왜 느릴까?

인덱스는 자동으로 성능을 올려주지 않는다. 다음과 같은 이유로 인덱스가 무시되거나 비효율적으로 사용될 수 있다.

1. 함수 또는 연산 사용

-- 잘못된 예: 인덱스를 타지 않는다
SELECT * FROM user WHERE YEAR(created_at) = 2024;

2. LIKE 앞에 와일드카드 사용

-- %가 앞에 있으면 인덱스 무시
SELECT * FROM product WHERE name LIKE '%신발';

3. OR 조건 다중 사용

-- OR은 인덱스를 무시하게 할 가능성이 크다
SELECT * FROM board WHERE writer = 'kim' OR subject = '공지';

4. 통계적으로 효율이 없을 때

-- 인덱스가 있어도 대부분의 row를 읽는다면 풀스캔(FULL SCAN) 발생
SELECT * FROM users WHERE gender = 'M';
반응형

🧪 EXPLAIN으로 실행계획 분석하기

예제 쿼리

EXPLAIN SELECT * FROM orders WHERE status = 'SHIPPED';

주요 컬럼 분석

  • type: ALL, index, range, ref, eq_ref 등 → ALL은 풀스캔이라 경고
  • key: 사용된 인덱스 이름
  • rows: 몇 건의 레코드를 탐색하는지 예상
  • Extra: Using where / Using index / Using temporary 등 힌트 제공

분석 포인트

항목 설명 예시
type = ALL 전체 테이블 탐색(비효율적) ❌ 성능 저하
key = NULL 인덱스 사용 안 함 ❌ 원인 분석 필요
rows = 100000 많은 행을 탐색함 ❗ 필터 조건이 효율적이지 않음
Extra = Using temporary 임시 테이블 사용 ❗ 정렬, 그룹핑이 느릴 수 있음
반응형

⚠️ 잘못된 인덱스 사용 예시

-- 인덱스는 있지만, 정렬 때문에 임시 테이블과 filesort 발생
EXPLAIN SELECT * FROM orders ORDER BY created_at DESC LIMIT 10;
  • Extra에 Using temporary; Using filesort가 나타난다.
  • 해결법: created_at에 인덱스를 생성하거나 Covering Index 구성
CREATE INDEX idx_orders_created_at ON orders(created_at DESC);

🛠️ 해결 방법 정리

문제 유형 해결 방안
함수 사용 조건에서 함수 제거
OR 조건 쿼리 분리 후 UNION
와일드카드 전체 검색 필요시 FULLTEXT 인덱스 고려
인덱스 미사용 컬럼 순서, 조건, 통계적 효율 점검
정렬/임시테이블 ORDER BY 포함 인덱스 구성

🧠 실전 팁: 쿼리 리팩토링으로 속도 개선

쿼리가 느릴 땐 단순히 인덱스를 추가하기보다 EXPLAIN 결과를 기반으로 리팩토링하는 것이 핵심이다.
불필요한 조건 제거, 인덱스 커버링, 조건 최적화 등을 통해 수백 배의 성능 향상도 가능하다.

📎 공식 문서

MySQL 공식 EXPLAIN 문서:
https://dev.mysql.com/doc/refman/8.0/en/explain-output.html

반응형