B-tree 인덱스
B-tree 인덱스
데이터베이스에서 가장 널리 사용되는 인덱스 구조. 정렬된 데이터의 빠른 검색, 범위 조회, 정렬을 지원한다.
왜 인덱스가 필요한가?
| 방식 | 하는 일 | 복잡도 |
|---|---|---|
| 인덱스 없이 | 1,000만 건을 처음부터 끝까지 하나씩 확인한다 | O(N) |
| B-tree 인덱스 | 3에서 4단계만에 찾는다. 1,000만 건이면 약 23번 비교한다 | O(log N) |
B-tree 구조
[ 30 | 60 ] ← Root
/ | \
[10|20] [40|50] [70|80] ← Branch
/ | \ / | \ / | \
[..] [..] [..] [..] [..] [..] [..]
← Leaf
(Leaf 노드끼리 연결 → 범위 조회)
핵심 특징:
- 모든 리프 노드가 같은 깊이
- 리프 노드끼리 연결 (Linked List)
- 키가 정렬된 상태 유지
B-tree vs Hash 인덱스
| 연산 | B-tree | Hash |
|---|---|---|
| 등호 (=) | O(log N) | O(1) |
| 범위 (<, >) | 지원 | 불가 |
| 정렬 (ORDER BY) | 지원 | 불가 |
| LIKE 'abc%' | 지원 | 불가 |
| GROUP BY | 지원 | 불가 |
→ 대부분의 경우 B-tree가 범용적
인덱스 동작 원리
-- 인덱스가 있는 컬럼 조회
SELECT * FROM users WHERE age = 25;
B-tree 탐색:
Root [30|60]
→ 30보다 작으니 왼쪽
Branch [10|20|25]
→ 25 발견!
Leaf → 실제 행 위치 (ROWID)
→ 테이블에서 해당 행 가져옴
인덱스가 안 타는 경우
| 케이스 | 이유 |
|---|---|
WHERE age + 1 = 26 | 컬럼에 연산 |
WHERE name LIKE '%kim' | 앞에 % |
WHERE age != 25 | 부정 조건 |
WHERE age IS NULL | (DB에 따라 다름) |
| 데이터 대부분 매칭 | Full Scan이 더 효율적 |
인덱스의 비용
INSERT/UPDATE/DELETE 시:
테이블 수정 + 인덱스도 수정!
인덱스 많으면:
읽기 ↑ 빨라짐
쓰기 ↓ 느려짐 (인덱스 유지 비용)
→ "읽기 위주" 테이블에 인덱스 추가
→ "쓰기 위주" 테이블은 최소한으로
실무 가이드
| 상황 | 인덱스 전략 |
|---|---|
| WHERE 자주 사용 | 해당 컬럼에 인덱스 |
| JOIN 조건 | FK 컬럼에 인덱스 |
| ORDER BY + LIMIT | 정렬 컬럼에 인덱스 |
| 복합 조건 | 복합 인덱스 고려 |
| 로그 테이블 (쓰기 위주) | 인덱스 최소화 |
- Q.B-tree 인덱스의 구조와 동작 원리를 설명해주세요.
- Q.B-tree와 Hash 인덱스의 차이는 무엇인가요?
- Q.인덱스를 타지 않는 쿼리 패턴은 어떤 것이 있나요?