🚨 문제 상황 소개
- 개발 DB와 운영 DB, 같은 버전/같은 테이블/같은 쿼리인데 실행계획이 달라졌다.
- 한쪽은 인덱스를 타고, 다른 한쪽은 풀스캔 + filesort 발생
- 원인 추적 과정 간단히 설명 (EXPLAIN 결과 비교)
🧱 실행계획 차이 원인
- 옵티마이저는 비용 기반(cost-based) 으로 플랜을 선택.
- 이때 “선택도(selectivity)” 추정이 중요.
- 그런데 추정 방식이 통계값만 보느냐, 실제 인덱스를 내려가 보느냐에 따라 결과가 달라짐.
⚠️ 인덱스 다이브(Index Dive)란?
- 개념: 옵티마이저가 실제 인덱스 레벨에서 값 분포를 확인해 정확한 선택도를 계산하는 과정.
- 장점: 더 정확한 실행계획.
- 단점: 옵티마이저가 실행계획 계산에 시간이 조금 더 걸림.
⚙️ EQ_RANGE_INDEX_DIVE_LIMIT 파라미터
- 역할: 인덱스 다이브를 몇 개 값까지 허용할지 결정.
- 0 → 인덱스 다이브 안 함 → 통계 의존 → 잘못된 플랜 위험 ↑
- 200(기본) → 200개 값까지 다이브 → 더 정확한 플랜 선택
- 왜 운영 DB만 “0”으로 되어 있었는지, 확인 과정 설명.
### 해결방법-- 현재 값 확인SHOW VARIABLES LIKE 'eq_range_index_dive_limit';-- 세션/글로벌에서 조정SET SESSION eq_range_index_dive_limit = 200;SET GLOBAL eq_range_index_dive_limit = 200;-- 영구 적용(MySQL 8 이상, MariaDB 10.3.30 version)SET PERSIST eq_range_index_dive_limit = 200;
🔖 정리
- 실행계획이 달라질 수 있는 이유는 데이터 분포 차이만 있는 게 아니라, 옵티마이저 파라미터 값 차이도 있다.
- 운영/개발 환경 비교할 때는 SHOW VARIABLES 로 변수 값부터 확인.
- 실행계획 이슈 정리 체크리스트:
- EXPLAIN 플랜 비교
- SHOW INDEX로 카디널리티 확인
- 관련 옵티마이저 변수(eq_range_index_dive_limit, innodb_stats_*, optimizer_switch 등) 확인