데이터베이스 인덱스란 — 동작 원리와 면접 답변
데이터베이스 인덱스란, 면접에서 자주 묻는 DB 질문
데이터베이스 인덱스란 무엇이고 어떻게 동작하는지는 DB CS 면접의 핵심 단골 질문입니다. 한 줄로 답하면 인덱스는 테이블의 특정 컬럼(들)에 대해 정렬된 별도의 자료구조를 만들어, 데이터를 빠르게 찾도록 돕는 장치입니다. 책 뒤의 '찾아보기(색인)'와 같습니다. 전체 페이지를 처음부터 넘기는 대신(Full Table Scan), 색인에서 위치를 바로 찾는 것입니다.
인덱스의 동작 원리: B-Tree
대부분의 RDBMS 인덱스는 B-Tree(정확히는 B+Tree) 구조를 사용합니다. 핵심 특징은 다음과 같습니다.
- 균형 트리: 모든 리프 노드까지의 깊이가 같아, 조회가 항상 O(log N)으로 일정합니다.
- 정렬 상태 유지: 키가 정렬되어 있어 범위 검색(
BETWEEN, 부등호)과 정렬(ORDER BY)에 강합니다. - B+Tree: 실제 데이터(또는 포인터)는 리프 노드에만 있고, 리프들이 연결 리스트로 이어져 범위 스캔이 효율적입니다.
즉, 인덱스가 없으면 N건을 모두 훑어야(O(N)) 하지만, B-Tree 인덱스가 있으면 트리를 타고 내려가 O(log N)에 원하는 위치를 찾습니다.
클러스터드 vs 논클러스터드 인덱스
| 구분 | 클러스터드 인덱스 | 논클러스터드(보조) 인덱스 |
|---|---|---|
| 데이터 정렬 | 실제 데이터가 인덱스 순서로 정렬 저장 | 별도 구조, 데이터 위치를 가리킴 |
| 개수 | 테이블당 1개(보통 PK) | 여러 개 가능 |
| 조회 속도 | 매우 빠름(데이터가 바로 있음) | 한 번 더 찾아감(리프→실제 행) |
MySQL InnoDB는 PK가 클러스터드 인덱스이고, 데이터 자체가 PK 순으로 저장됩니다. 보조 인덱스는 리프에 PK 값을 저장해, 실제 행을 찾으려면 PK로 다시 조회하는 추가 비용이 듭니다.
인덱스의 트레이드오프
인덱스는 조회를 빠르게 하지만 공짜가 아닙니다.
- 쓰기 성능 저하: INSERT/UPDATE/DELETE 시 인덱스도 갱신·재정렬해야 합니다.
- 저장 공간 추가: 인덱스 자체가 디스크 공간을 차지합니다.
- 무분별한 인덱스는 독: 조회 빈도가 낮은데 인덱스만 많으면 쓰기 비용만 늘어납니다.
인덱스를 타지 못하는 대표 경우
면접에서 깊이를 보여줄 수 있는 포인트입니다.
-- 컬럼에 함수/연산을 적용하면 인덱스 무효
WHERE YEAR(created_at) = 2026 (X)
WHERE created_at >= '2026-01-01' ... (O)
-- 앞에 와일드카드가 있는 LIKE
WHERE name LIKE '%kim' (X, 인덱스 못 탐)
WHERE name LIKE 'kim%' (O)
-- 복합 인덱스(a,b)에서 선두 컬럼을 건너뛰면 비효율
INDEX(a, b) 인데 WHERE b = 10 만 사용 (X, 선두 a가 없으면 못 탐)복합 인덱스와 선두 컬럼 규칙
복합 인덱스 (a, b, c)는 a부터 정렬되어 있어 a, a,b, a,b,c 순서로 사용할 때 효율적입니다. 선두 컬럼 a 없이 b만 조건으로 쓰면 인덱스를 제대로 활용하지 못합니다. 그래서 자주 쓰는 조건, 선택도(cardinality)가 높은 컬럼을 앞에 두는 설계가 중요합니다.
면접 답변 예시
"인덱스는 특정 컬럼에 대해 정렬된 별도 자료구조를 만들어 조회 속도를 높이는 장치로, 책의 색인과 같습니다. 대부분 B+Tree로 구현돼 균형 트리라 조회가 O(log N)으로 일정하고, 정렬 상태라 범위 검색과 정렬에도 강합니다. 다만 INSERT·UPDATE·DELETE 시 인덱스도 갱신해야 해서 쓰기 성능이 떨어지고 저장 공간도 듭니다. 그래서 조회가 빈번하고 선택도가 높은 컬럼에 선별적으로 걸어야 합니다. 또 컬럼에 함수를 쓰거나, 앞에 와일드카드가 붙은 LIKE, 복합 인덱스의 선두 컬럼을 빼고 조회하면 인덱스를 타지 못한다는 점도 주의합니다."
면접 꼬리질문 대비
Q1. 왜 해시 인덱스가 아니라 B-Tree를 주로 쓰나요?
해시 인덱스는 등호(=) 검색은 O(1)로 매우 빠르지만, 키를 해싱하므로 정렬이 유지되지 않아 범위 검색(>, BETWEEN)이나 ORDER BY를 지원하지 못합니다. B-Tree는 정렬 상태를 유지해 등호·범위·정렬을 모두 처리할 수 있어 범용적입니다. 그래서 RDBMS 기본 인덱스는 B-Tree입니다.
Q2. 커버링 인덱스(Covering Index)란?
쿼리가 필요로 하는 모든 컬럼이 인덱스에 포함되어, 실제 테이블(데이터 행)에 접근하지 않고 인덱스만 읽어 결과를 반환하는 경우입니다. 논클러스터드 인덱스의 '리프에서 실제 행으로 다시 찾아가는' 추가 비용이 사라져 매우 빠릅니다. SELECT 컬럼을 인덱스에 포함시키도록 설계하면 성능을 크게 높일 수 있습니다.
Q3. 선택도(cardinality)가 인덱스 효율에 어떻게 영향을 주나요?
선택도는 컬럼 값의 고유함 정도입니다. 성별처럼 값 종류가 2~3개뿐인 낮은 선택도 컬럼은 인덱스를 타도 걸러지는 행이 많아 효과가 적고, 옵티마이저가 Full Scan을 택하기도 합니다. 반대로 주민번호·이메일처럼 거의 고유한 높은 선택도 컬럼은 인덱스로 후보를 크게 줄여 효율이 좋습니다. 그래서 선택도가 높은 컬럼에 인덱스를 거는 것이 유리합니다.