DB 실행계획 차이: 원인 및 해결책

🚨 문제 상황 소개

  • 개발 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 로 변수 값부터 확인.
  • 실행계획 이슈 정리 체크리스트:
    1. EXPLAIN 플랜 비교
    2. SHOW INDEX로 카디널리티 확인
    3. 관련 옵티마이저 변수(eq_range_index_dive_limit, innodb_stats_*, optimizer_switch 등) 확인