430. 인덱스 패스트 풀 스캔 (Index Fast Full Scan)
⚠️ 이 문서는 데이터베이스에서 "특정 테이블의 데이터 개수가 총 몇 개야?(
COUNT)", "가장 나이가 많은 사람은 몇 살이야?(MAX)" 같은 집계 통계를 낼 때, 무식하게 테이블을 전부 뒤지는 대신 '인덱스(목차)'만 초고속으로 병렬(Parallel) 처리하여 읽어오는 극강의 최적화 기법을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 하드디스크에 있는 진짜 데이터(Table)는 아예 쳐다보지도 않고, 오직 '인덱스(Index)' 구조물 안에 들어있는 데이터만으로 질문에 대답하는 스캔 방식이다.
- 가치: 테이블 전체를 훑는 것(Full Table Scan)보다 읽어야 할 디스크 용량이 훨씬 작고, B-Tree의 정렬 순서를 무시하고 여러 스레드가 동시에 병렬로 읽을 수 있어 집계 속도가 압도적으로 빠르다.
- 조건: 쿼리에서 요구하는 모든 컬럼(
SELECT,WHERE조건 포함)이 **반드시 하나의 인덱스 안에 모두 포함(Covering Index)**되어 있어야만 발동한다.
Ⅰ. 개요: 책을 펴지 않고 목차만 보고 대답하기 (Context & Necessity)
"우리 회사에 대리 직급을 가진 사람이 몇 명이지?"
SELECT COUNT(*) FROM 직원 WHERE 직급 = '대리';
이 질문에 대답하기 위해 DB는 어떻게 움직일까?
- 바보 같은 방법 (Table Full Scan): 직원 1만 명의 인사 기록부(본문)를 처음부터 끝까지 한 장씩 넘기면서 '대리'라는 글자를 찾는다. (시간 엄창 걸림)
- 일반 인덱스 (Index Range Scan): 직급 인덱스(목차)를 펴서 '대리'를 찾은 뒤, 100명이네? 하고 그 100명의 진짜 인사 기록부로 100번 점프(Key Lookup)한다. (비효율적임)
- 천재적인 방법 (Index Fast Full Scan): "어차피 몇 명인지만 알면 되잖아? 진짜 인사 기록부를 열 필요가 뭐 있어? 그냥 직급 인덱스(목차)에 적힌 '대리' 글자 수만 세면 되잖아!"
이처럼 진짜 데이터 블록에 접근하지 않고, 인덱스 자체를 하나의 거대한 테이블처럼 생각하고 처음부터 끝까지 쫙 긁어버리는 것이 인덱스 패스트 풀 스캔이다.
📢 섹션 요약 비유: 이 방식은 책의 내용(본문)은 궁금하지 않고, 오직 **'목차에 적힌 챕터가 총 몇 개인지'**만 세고 싶을 때 쓰입니다. 굳이 무거운 책을 통째로 넘기지 않고, 맨 앞의 가벼운 목차 페이지만 여러 명이 동시에 나눠서 빠르게 세어버리는 마법입니다.
Ⅱ. 일반 인덱스 풀 스캔 vs 패스트 풀 스캔 ★
이름은 비슷하지만 작동 원리는 완전히 다르다. (시험 단골 문제)
1. 인덱스 풀 스캔 (Index Full Scan)
- 방식: B-Tree 인덱스의 규칙(정렬)을 철저하게 지키면서, 리프 노드를 왼쪽 끝부터 오른쪽 끝까지 순서대로(Sequential) 1가닥의 스레드가 쭈욱 읽는다.
- 장점: 다 읽고 나면 결과가 '정렬(ORDER BY)'되어 있다.
- 단점: 혼자서 차례대로 읽어야 하니 속도가 느리다.
2. 인덱스 패스트 풀 스캔 (Index Fast Full Scan)
- 방식: B-Tree의 정렬이고 나발이고 다 무시한다. 하드디스크에 저장된 인덱스 블록들을 뭉텅이로 잘라서 **여러 명(Multi-Thread 병렬 처리)**이 한 번에 싹 다 퍼 올린다. (Multi-block I/O)
- 장점: 병렬로 읽어버리므로 속도가 미친 듯이 빠르다.
- 단점: 마구잡이로 퍼 올렸기 때문에 결과가 정렬되어 있지 않다. 따라서
ORDER BY쿼리가 있으면 이 방식을 쓸 수 없다.
Ⅲ. 발동 조건: 커버링 인덱스 (Covering Index)
옵티마이저가 이 멋진 스캔 방식을 선택하려면 절대적인 전제 조건이 있다. "쿼리에 쓰인 모든 컬럼이 인덱스 안에 들어있어야 한다."
- 인덱스:
[부서명, 직급](결합 인덱스) - 성공 쿼리:
SELECT 부서명, COUNT(*) FROM 직원 GROUP BY 부서명;- (인덱스 안에 부서명이 다 있으니까 본문을 볼 필요가 없음 $\rightarrow$ 패스트 풀 스캔 발동 🚀)
- 실패 쿼리:
SELECT 부서명, 이름 FROM 직원 WHERE 직급 = '대리';- (
이름컬럼은 인덱스에 없다! 결국 '이름'을 보려면 진짜 테이블로 점프를 뛰어야 하므로 패스트 풀 스캔 실패 💥)
- (
┌──────────────────────────────────────────────────────────────┐
│ 인덱스 패스트 풀 스캔 (Fast Full Scan) 병렬 처리 시각화 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [ 📑 디스크에 저장된 거대한 결합 인덱스 블록들 (부서명, 직급) ] │
│ │
│ 블록1 [영업,대리] [개발,사원] ◀── [ 🤖 스레드 1번이 퍼올림! ] │
│ 블록2 [기획,부장] [영업,과장] ◀── [ 🤖 스레드 2번이 퍼올림! ] │
│ 블록3 [개발,대리] [인사,대리] ◀── [ 🤖 스레드 3번이 퍼올림! ] │
│ │
│ (DB 엔진에서 합치기) ──▶ "총 데이터 6건, 대리는 3명입니다!" │
│ │
│ ★ 특징: B-Tree의 규칙(루트->브랜치->리프)을 무시하고 그냥 하드디스크를 │
│ 뭉텅이로 잘라서 동시에 읽어버린다! (그래서 빠르지만 정렬이 안 됨) │
└──────────────────────────────────────────────────────────────┘
Ⅳ. 결론
"데이터베이스 최적화의 꽃은 '안 읽고 대답하기'다." 인덱스 패스트 풀 스캔은 사실상 인덱스를 **'원본 테이블의 얇고 날씬한 복사본(Slim Table)'**으로 취급하는 기법이다. 통계 화면, 대시보드, 어드민 페이지 등에서 무거운 집계(Aggregation) 쿼리가 서버를 짓누를 때, 영리한 DBA는 쿼리에 필요한 컬럼들을 싹 다 모아 '커버링 인덱스'를 만들어준다. 그러면 옵티마이저는 본문 테이블의 멱살을 잡는 대신, 가벼운 인덱스 목차만 0.01초 만에 스캔하여 결과를 리턴하는 예술적인 실행 계획을 보여주게 될 것이다.
📌 관련 개념 맵
- 선행 개념: 실행 계획 (421번), 테이블 풀 스캔 (428번 문서)
- 대칭 개념: Index Range Scan (429번 문서)
- 필수 조건: Covering Index (커버링 인덱스)
- 하드웨어 기술: Multi-block I/O, Parallel Processing (병렬 처리)
👶 어린이를 위한 3줄 비유 설명
- 선생님이 "우리 반에 성이 '김'씨인 애들 몇 명이야?"라고 물어보셨어요.
- 일반 검색은 출석부(인덱스)에서 김씨 이름을 하나하나 가나다순으로 예쁘게 짚어가며 세는 거예요.
- 패스트 풀 스캔은 반장, 부반장, 청소반장 3명이 출석부를 3장씩 확 찢어서 나눠 가진 다음, 순서 무시하고 "나 2명! 나 1명! 나 0명! 총 3명!" 하고 순식간에 대답하는 거랍니다!