Skip to content

MySQL ‐ Index Dive Using In Query

woojin.jang edited this page Jul 19, 2026 · 1 revision

Index Dive

  • MySQL은 같은 쿼리라도 여러 실행 방법(인덱스 A, 인덱스 B, 풀스캔) 중 하나를 고른다.
  • 이 때, 아무거나 고르는 게 아니라 각 방법의 예상 비용(Cost)을 계산해 가장 싼 것을 택한다. 이를 비용 기반 옵티마이저(Cost-Based Optimizer)라고 한다.
  • 비용을 계산하려면 "이 조건에 몇 건이나 걸리는지"를 먼저 알아야 한다. 인덱스 다이브는 바로 이 행 수를 추정하는 기술이다.

왜 "걸리는 행 수"가 중요한가(선택도)

  • 선택도(Selectivity) : 어떤 조건이 전체 데이터에서 몇 %를 걸러내는지를 나타내는 개념이다.
    • 예시 : 100만 건 중 조건에 10건만 남으면 → 선택도 높음 → 인덱스 레인지 스캔이 매우 유리
    • 100만 건 중 90만 건이 남으면 → 선택도 낮음 → 차라리 풀스캔이 유리할 수 있음
  • 즉 옵티마이저는 "몇 건 걸리는지"를 알아야 인덱스를 쓸지 말지 판단할 수 있다.

행 수를 추정하는 두 가지 방법

A. 인덱스 통계 (Index Statistics)

  • ANALYZE TABLE로 미리 수집해 둔 카디널리티 값으로 대략 계산한다.
  • 빠르지만 부정확하다. 데이터가 고르게 분포한다고 가정하기 때문이다.

B. 인덱스 다이브 (Index Dive)

  • 실행 시점에 실제 인덱스 B-Tree로 직접 내려가서(dive), 범위의 시작 경계와 끝 경계 위치를 찾고 그 사이에 몇 건이 있는지 추정한다.
  • 정확하지만 비싸다. 트리를 실제로 탐색하기 때문이다.
  • MySQL은 범위(range) 조건에 대해 기본적으로 이 방식을 쓴다.
구분 인덱스 통계 인덱스 다이브
방식 미리 수집한 카디널리티 실행 시 B-Tree 직접 탐색
정확도 낮음 높음
비용 비쌈

EXPLAIN의 rows는 "추정치"다

  • EXPLAIN의 rows 컬럼은 다이브(또는 통계)가 계산한 예상 행 수이지, 실제 값이 아니다.
  • 이 추정이 실제와 크게 어긋나면 옵티마이저가 잘못된 인덱스를 골라 성능이 나빠질 수 있다.
  • 그래서 EXPLAIN을 볼 때 rows는 "옵티마이저가 이렇게 예상했다"로 읽어야 한다.
EXPLAIN
SELECT * FROM stock_trade_history
WHERE trade_date BETWEEN '2026-01-01' AND '2026-03-31';

IN 절의 함정과 eq_range_index_dive_limit

  • 이 폭주를 막는 설정이 eq_range_index_dive_limit(기본값 200)이다
    • IN 값 개수가 한도 이하 → 정확한 index dive 사용
    • 그러나 한도 초과 → 다이브를 포기하고 부정확한 통계로 대체(계획 품질 저하 가능)
-- IN 값이 1,000개면 다이브도 1,000번 → 쿼리 실행 전 '최적화 단계'에서 시간 소모
WHERE stock_code IN ('005930', '000660', /* ... */ );
SHOW VARIABLES LIKE 'eq_range_index_dive_limit';

통계가 낡으면 계획이 나빠진다

  • 다이브를 타지 않는 경우(또는 통계로 대체된 경우) 옵티마이저는 인덱스 통계에 의존한다.
  • 대량 삽입·삭제로 데이터 분포가 크게 바뀌었는데 통계가 낡아 있으면 옵티마이저가 헛다리를 짚는다.
  • 이럴 때 ANALYZE TABLE로 통계를 갱신하면 계획이 정상화될 수 있다.
ANALYZE TABLE stock_trade_history;

📖 Code Philosophy

📖 Java

📖 Kotlin

📖 Coroutine

📖 Spring

📖 Spring Security

📖 Spring Batch

📖 Database

📖 MySQL

📖 Redis

📖 JPA

📖 QueryDsl

📖 MSA

📖 Kafka

📖 Apache Flink

  • [Apache Flink - Apache Flink Architecture]
  • [Apache Flink - Stream Processing]
  • [Apache Flink - Data Stream API & Window]
  • [Apache Flink - State Management]

📖 HTTP

📖 AWS

📖 Docker

📖 Kubernetes

📖 Github Actions

📖 Jenkins

📖 Nginx

📖 Monitoring

📖 Test(feat. Load Testing)

  • [Test - Load Testing Fundamentals]
  • [Test - Identifying Bottlenecks with Load Testing]
  • [Test - Resolving Bottlenecks and Improving Performance]

📖 Test(feat. Java)

📖 Spring AI

📖 gRPC

  • [gRPC - Writing .proto Files with Protocol Buffers]
  • [gRPC - Various Communication Patterns in gRPC]
  • [gRPC - gRPC Optimization Techniques and Advanced Features]

📖 TDD(Test-Driven-Development)

📖 PostgreSQL

  • [PostgreSQL - Docker만을 사용하는 경량화된 환경 구성 방법]
  • [PostgreSQL - PostgreSQL에서 제공하는 데이터 타입]
  • [PostgreSQL - PostgreSQI의 JSONB, 역인덱싱과 활용 방법]
  • [PostgreSQL - 데이터베이스 성능을 위한 최적화 패턴 및 전략]
  • [PostgreSQL - 트랜잭션과 ACID, Isolation 수준별 차이]
  • [PostgreSQL - Database Lock 교착상태와 읽기/쓰기 성능을 보장하는 MVCC 모델]
  • [PostgreSQL - pgvector와 벡터 저장, 유사도 검색 패턴 개념]
  • [PostgreSQL - 벡터 인덱스 최적화와 벡터 검색과 전문 검색 결합 패턴]
  • [PostgreSQL - PostgreSQL 플러그인]
  • [PostgreSQL - PostGIS - 공간 쿼리와 GIST 인덱스, 지리 타입과 공간 쿼리를 위한 타입과 기본 함수]
  • [PostgreSQL - pg_search - 검색 엔진 없이 텍스트 검색 구현과 주의사항]
  • [PostgreSQL - 단일 인스턴스 한계를 극복하는 분산 패턴과 스케줄링, 분산 환경 구축 방법]
  • [PostgreSQL - Citus - 분산 테이블과 분산 쿼리를 위한 Extension과 데이터 분산 처리]
  • [PostgreSQL - pg_cron - PostgreSQL로 구성하는 CronJob]
  • [PostgreSQL - 스케줄러 + 분산 처리를 동시에 도입하는 주기적 집계 쿼리 패턴]

📖 Workflow-Driven Techniques for Large-Scale Traffic Processing

  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Kafka + Debezium을 활용한 CDC 패턴 설계]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Temporal을 활용한 워크플로우 패턴]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Docker와 경량 이미지를 활용한 환경 구축 방법]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Kafka에서의 메시지 Delivery Guarantee]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - 실시간 동기화의 핵심 CDC]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - MySQL Binary Log 기반의 CDC]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Binary Log 기반의 CDC 구현 플랫폼 Debezium이란?]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Debezium Architecture]
  • [Workflow-Driven Techniques for Large-Scale Traffic Processing - Debezium Architecture Best Practice와 주의사항]

📖 Reactive Programming

📖 ElasticSearch

  • [ElasticSearch - Search Fundamentals & How Search Works]
  • [ElasticSearch - Korean-Optimized Search]
  • [ElasticSearch - Mapping & Data Types]
  • [ElasticSearch - Common Search Features]
  • [ElasticSearch - Building a Product Search Engine with Elasticsearch]
  • [ElasticSearch - Deploying Elasticsearch with Elastic Cloud]
  • [ElasticSearch - Managing Documents]
  • [ElasticSearch - Analysis & Mapping]
  • [ElasticSearch - Search Fundamentals]
  • [ElasticSearch - Query Joins]
  • [ElasticSearch - Processing Search Results]
  • [ElasticSearch - Aggregations]
  • [ElasticSearch - Tips for Improving Search Results]
  • [ElasticSearch - Elasticsearch Clients]
  • [ElasticSearch - Understanding How Elasticsearch Works]
  • [ElasticSearch - Monitoring Elasticsearch]
  • [ElasticSearch - Elasticsearch Troubleshooting]

Clone this wiki locally