인덱스 레인지 스캔
인덱스 레인지 스캔은 인덱스에서 어디부터 어디까지 읽을지 범위가 정해졌을 때 사용하는 방식.
예시) WHERE name >= 'Kim' AND name < 'Lee’ 와 같은 범위 검색에서
- 단계 1: “어디서부터 읽을지 찾는 과정” 단계
트리 위에서 아래로 내려가면서 시작 지점을 찾는다. - 단계 2: 스캔 단계
시작 리프 노드를 찾았으면 리프 노드 안에서 정렬된 순서대로 쭉 읽는다.
리프 노드는 서로 링크(포인터) 로 연결되어 있어서, 한 리프 노드를 끝까지 읽으면 링크를 타고 다음 리프 노드로 이동해서 계속 읽음 - 단계 3: 실제 데이터 읽기 단계 👉 이 단계에서 랜덤 I/O 발생
인덱스에는 보통 키 값과 레코드 주소(PK 또는 ROWID)- 인덱스에서 얻은 주소를 이용해
- 실제 데이터 페이지를 다시 읽음
- 최종 레코드 반환
언제 3번째 “실제 데이터 읽기” 과정이 필요 없을까?
- 쿼리가 요구하는 컬럼이 모두 인덱스 안에 들어 있다면, 실제 데이터 페이지를 읽을 필요 없음 👉 이걸 커버링 인덱스라고 한다.
인덱스 풀 스캔
인덱스 풀 스캔은 인덱스의 처음부터 끝까지 전부 읽는 방식이다. 즉 범위를 지정하지 않고 인덱스 전체를 스캔하는 방식이다.
다음 조건일 때 자주 사용된다.
- WHERE 조건이 인덱스를 못 탐
- 하지만 SELECT에 필요한 컬럼이 인덱스에 다 있음
- 즉, 커버링 인덱스일 때만 의미 있음
왜 테이블 풀 스캔보다 빠를까?
- 인덱스 크기 < 테이블 크기
- 인덱스는 필요한 컬럼만 저장
- 디스크에서 읽어야 할 양이 더 적음
루스 인덱스 스캔
루스 인덱스 스캔은 인덱스를 범위로 읽되 중간의 불필요한 값은 건너뛰면서(SKIP) 읽는 방식이다.
즉, 필요한 그룹의 대표값만 읽고 다음 그룹으로 점프한다.
- 주로 그룹별로 하나의 값만 필요할 때, 사용된다.
- 대표적으로 GROUP BY, MIN(), MAX() 조합으로 사용.
SELECT dept_no, MIN(emp_no)
FROM dept_emp
WHERE dept_no BETWEEN 'd002' AND 'd004'
GROUP BY dept_no;
- 인덱스: (dept_no, emp_no) → dept_no 기준으로 정렬, 그 안에서 emp_no 정렬
d002, 1001
d002, 1005
d002, 1010
d003, 2001
d003, 2007
d004, 3002
- 위 상황에서 각 그룹의 emp_no의 최소값만 필요함으로
- d002 → 첫 번째 값만 읽으면 됨 (1001)
- d003 → 첫 번째 값만 읽으면 됨 (2001)
- d004 → 첫 번째 값만 읽으면 됨 (3002)
👉 나머지는 읽을 필요 없으로 중간 값 SKIP
인덱스 스킵 스캔
인덱스 스킵 스캔은 Left-most 규칙을 “우회”하는 MySQL 8.0 기능이다.
인덱스가 이렇게 있다고 가정: INDEX idx_gender_birthdate (gender, birth_date)
보통 B-Tree는 왼쪽 컬럼부터 조건이 있어야 인덱스를 탈 수 있다.
하지만 MySQL 8.0 부터는
SELECT gender, birth_date
FROM employees
WHERE birth_date >= '1965-02-01';
앞 컬럼(gender)의 가능한 값들을 하나씩 넣어서 여러 번 range 스캔을 수행
- gender는 ENUM('M', 'F') 가능한 값 2개
- 옵티마이저는 내부적으로 이런 식으로 처리
-- 1번 실행
WHERE gender = 'M'
AND birth_date >= '1965-02-01'
-- 2번 실행
WHERE gender = 'F'
AND birth_date >= '1965-02-01'
-
- range 스캔 가능 👉 결과를 합침
단점 (제약 조건 2가지)
1. 선행 컬럼 유니크 값이 적어야 함
- 만약 gender (200개) 200번 range 스캔 수행 👉 오히려 비효율적
2. 커버링 인덱스여야 유리
- 매번 PK까지 내려가면 랜덤 I/O 폭발 👉 skip scan 이점 사라짐
'Study > MySQL' 카테고리의 다른 글
| 조인 방식 비교 (네스티드 루프 조인 VS 블록 네스티드 루프 조인 VS 해시 조인) (0) | 2026.03.16 |
|---|---|
| MySQL 풀 테이블 스캔과 리드 어헤드 (1) | 2026.03.08 |
| B-Tree 인덱스 사용에 영향을 미치는 요소 (0) | 2026.03.02 |
| 디스크 읽기 방식 HDD VS SSD (0) | 2026.03.01 |
| MySQL 격리 수준 (0) | 2026.02.17 |