반응형
Notice
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Tags
- 자바스크립트
- 디자인패턴
- 네트워크보안
- 빅데이터
- 머신러닝
- 웹개발
- 사이버보안
- 컴퓨터과학
- 클라우드컴퓨팅
- 보안
- 데이터구조
- 파이썬
- 인공지능
- Yes
- 소프트웨어공학
- 컴퓨터비전
- 딥러닝
- 프로그래밍언어
- 데이터과학
- springboot
- 버전관리
- 네트워크
- I'm Sorry
- 소프트웨어
- 알고리즘
- 데이터베이스
- 자료구조
- 컴퓨터공학
- 프로그래밍
- 데이터분석
Archives
- Today
- Total
스택큐힙리스트
Index Skip Scan 완전 정복: 선두 칼럼이 없어도 인덱스를 타는 마법 본문
반응형
Index Skip Scan이란?
B-Tree 인덱스는 보통 왼쪽(선두) 칼럼으로 정렬돼 있어, 그 칼럼이 조건에 없으면 인덱스를 통째로 훑는(Full Scan) 일이 많습니다.
Skip Scan은 선두 칼럼의 각 값(또는 범위)을 “건너뛰며” 하위 칼럼을 탐색해 “마치 여러 단일-칼럼 인덱스가 있는 것처럼” 동작합니다. Oracle·MySQL·TiDB 등은 옵티마이저가 스스로 판단해 적용하며, 실행계획에 INDEX SKIP SCAN(Oracle)·Using index for skip scan(MySQL EXPLAIN Extra) 등이 찍힙니다.
동작 원리 깊이 보기
- 선두 칼럼 Distinct 스캔
- 예) (status, created_at) 인덱스에서 status(A/B/C) 값별 루트→리프 경로를 순차로 탐색
- 하위 칼럼 Range 검색
- 각 status 경로 안에서 created_at ≥ 2025-01-01 조건으로 범위 스캔
- 필요 없는 리프 블록은 건너뜀(skip)
- B, C path의 리프를 재사용하므로 “다중 인덱스” 효과
골든 룰
선두 칼럼 카디널리티가 낮아야(값 종류가 적어야) skip step이 적고 이득이 큽니다.
어떤 DB에서 지원하나?
제품 | 지원 현황 | 힌트/옵션 |
Oracle 9i+ |
기본 지원, 실행계획 OPERATION 열 INDEX SKIP SCAN | 힌트 INDEX_SS() |
MySQL 5.7+ (InnoDB) | Extra = Using index for skip scan | 옵티마이저 힌트 SKIP_SCAN / NO_SKIP_SCAN |
PostgreSQL | 17·18 버전에서 패치 진행 중, 아직 메인라인 포함 전(2025-07 기준) | |
TiDB | 6.0+ 기본 지원 | |
SQL Server / SQLite | 공식 지원 없음 |
언제 사용하면 좋을까?
- 선두 칼럼이 로우 상태값, 타입 코드 등 저카디널리티
- 하위 칼럼에 범위/정렬 조건만 존재할 때
-- status 조건 없이 created_at 범위 + 정렬
SELECT * FROM orders
WHERE created_at >= '2025-01-01'
ORDER BY created_at, id
LIMIT 50;
- 읽기 전용·OLAP형 조회: 테이블 업데이트가 많지 않을수록 효과 극대화
성능 비교 예시(MySQL 8.4, 1 M rows)
패턴 | p95 지연 | 읽은 Rows |
Offset 100 k + Limit 50 | 220 ms | 100 050 |
Skip Scan(covering X) | 9 ms | 50 |
Skip Scan + Covering Index | 4 ms | 50 |
Covering Index까지 결합하면 테이블 접근이 사라져 I/O가 절반 이하로 감소합니다.
옵티마이저가 Skip Scan을 고르지 않을 때
- 힌트 강제
SELECT /*+ SKIP_SCAN(t1) */ … FROM t1 … -- MySQL
SELECT /*+ INDEX_SS(orders idx_status_created) */ … -- Oracle
- 통계 갱신 후 재시도
- 잘못된 NDV(고유값 수) 추정이 선택을 막을 수 있음.
- 인덱스 재설계
- 아예 (created_at, id) 단독 인덱스를 두는 편이 더 빠른 상황도 있음.
한계와 주의점
- 선두 칼럼이 고카디널리티(고유값 많음) → skip 횟수↑, 이득↓
- 높은 업데이트 빈도 → 인덱스 블록 분할 심화, Fragmentation 발생
- Oracle은 함수-기반·언어별 정렬 인덱스에서는 Skip Scan 불가 support.oracle.com
- 실행계획이 INDEX RANGE SCAN과 혼합될 때 성능이 오히려 떨어질 수 있으므로 벤치마크 필수.
실전 체크리스트
질문 | 체크 포인트 |
선두 칼럼 NDV가 충분히 낮은가? | SELECT COUNT(DISTINCT col1)/COUNT(*) |
통계 최신화돼 있는가? | ANALYZE TABLE / DBMS_STATS.GATHER_* |
Covering 가능한가? | SELECT 칼럼을 인덱스에 다 포함 |
실행계획에서 Skip Scan 확인? | Oracle PLAN OP, MySQL Extra |
힌트·파라미터? | SKIP_SCAN, index_ss_dj_enabled=true(Oracle) |
반응형
'개발' 카테고리의 다른 글
멀티모듈 테스트 격리 & Fixture 전략 (0) | 2025.07.12 |
---|---|
자바 스프링 개발 시작하기 - 6일차 빌드 & 의존성 마스터하기 (1) | 2025.07.12 |
Index Skip Scan과 Covering Index를 활용한 초고속 페이징 쿼리 패턴 (0) | 2025.07.11 |
실전 튜닝 Q&A: 요청 지연 파악부터 CDN-비용, 인덱스 설계까지 한 방에! (0) | 2025.07.11 |
Redis로 읽기 부하 줄이기 – 캐시 전략 실전 가이드 (5) | 2025.07.11 |
Comments