인덱스

데이터를 빠르게 찾기 위한 자료구조입니다. 책의 색인(목차)과 같습니다.


비유

책에서 "React" 찾기:

인덱스 없음: 1페이지부터 끝까지 전부 읽음
인덱스 있음: 색인에서 "React → 152페이지" 확인 → 바로 이동

인덱스 없을 때

SELECT * FROM users WHERE name = '철수';
테이블 전체 스캔 (Full Table Scan)

| id | name   | age |
|----|--------|-----|
| 1  | 영희   | 25  |  ← 확인
| 2  | 민수   | 30  |  ← 확인
| 3  | 철수   | 28  |  ← 찾음!
| 4  | 지연   | 22  |  ← 확인 (끝까지 계속)
...

100만 건이면 100만 번 확인합니다.


인덱스 있을 때

CREATE INDEX idx_name ON users(name);
인덱스 (B-Tree)

        [민수]
       /      \
   [영희]    [철수]
              /
          [지연]

철수 찾기: 민수 → 오른쪽 → 철수 (3번 비교)

100만 건이어도 약 20번 비교로 찾습니다.


인덱스 자료구조

구조특징DB 적합성
B-Tree / B+Tree정렬된 균형 트리범위 검색·정렬 가능 → 대부분의 RDB 기본값
HashMap (해시)해시 함수로 O(1) 조회등치만 가능. 범위·정렬 불가 → MEMORY 엔진, Redis 등

→ MySQL InnoDB는 B+Tree를 사용 (리프 노드끼리 연결리스트 → 범위 검색 빠름).


인덱스 종류

구분설명
Clustered Index데이터 자체가 정렬되어 저장. 테이블당 1개 (보통 PK)
Non-Clustered Index별도 인덱스 페이지 → 데이터 포인터. 여러 개 가능
복합 인덱스여러 컬럼을 묶은 인덱스
Hidden Clustered IndexInnoDB가 PK 없을 때 자동 생성

장단점

장점단점
조회 빠름저장 공간 추가 필요
정렬 빠름INSERT/UPDATE/DELETE 느려짐
-- INSERT 시
1. 테이블에 데이터 추가
2. 인덱스도 업데이트 (추가 작업)

언제 만드는가

-- 좋은 경우
CREATE INDEX idx_email ON users(email);  -- 자주 검색하는 컬럼
CREATE INDEX idx_created ON orders(created_at);  -- 정렬에 쓰는 컬럼

-- 안 좋은 경우
CREATE INDEX idx_gender ON users(gender);  -- 값이 몇 개 없음 (남/여)
좋은 경우나쁜 경우
WHERE절에 자주 사용거의 조회 안 하는 컬럼
카디널리티 높음 (값 종류 많음)카디널리티 낮음 (남/여 등)
조회 > 쓰기쓰기 > 조회

주의

만들었다고 항상 타지는 않습니다 → 인덱스가 안 타는 케이스 참고.

CSLOG에서 보기