Foundry
데이터베이스
기초
핵심

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-treeHash
등호 (=)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 인덱스의 구조와 동작 원리를 설명해주세요.

정렬된 키를 여러 층의 노드에 나눠 담아, 위에서 아래로 범위를 좁혀 내려가는 구조입니다.

특성내용
노드당 키수백 개. 디스크 블록 하나에 담을 만큼
높이100만 행이라도 3에서 4
리프실제 데이터나 데이터 위치를 가리킨다
리프 연결서로 이어져 있어 범위 조회가 순차 읽기로 끝난다

노드를 뚱뚱하게 만드는 이유는 디스크 읽기 횟수를 줄이기 위해서입니다. 디스크 접근이 메모리보다 수천 배 느리므로, 높이를 낮추는 것이 곧 성능입니다.

100만 행에서 한 건 찾기
  풀 스캔    100만 번 비교
  B-tree     3에서 4번의 노드 읽기

흔한 실수: 이진 트리와 같은 것으로 설명하는 것. 이진 트리는 노드당 키가 하나여서 높이가 20 안팎이 되고, 그만큼 디스크를 읽어야 합니다.

Q.B-tree와 Hash 인덱스의 차이는 무엇인가요?

항목B-tree해시
등가 조회O(log n)평균 O(1)
범위 조회가능불가능
정렬 순회가능불가능
접두어 검색가능불가능
최댓값과 최솟값가능불가능

해시가 이론상 빠른데도 DB 기본이 B-tree 인 이유는 실무 쿼리에 범위와 정렬이 흔하기 때문입니다.

WHERE created_at BETWEEN ? AND ?    -- 범위
ORDER BY price                      -- 정렬
WHERE name LIKE '김%'                -- 접두어

이 셋이 모두 해시로는 안 됩니다. 등가 조회만 필요한 것이 확실하고 그 차이가 병목일 때만 해시를 고려합니다.

흔한 실수: MySQL InnoDB 에서 해시 인덱스를 만들 수 있다고 답하는 것. 명시적으로는 만들 수 없고(MEMORY 엔진만 가능) 내부 적응형 해시는 엔진이 알아서 관리합니다.

Q.인덱스를 타지 않는 쿼리 패턴은 어떤 것이 있나요?

패턴왜 못 타나
컬럼에 함수를 씌움인덱스는 원본 값으로 정렬돼 있다
타입이 다름암묵적 변환이 일어나 원본 값과 비교되지 않는다
앞에 와일드카드시작점을 정할 수 없다
부정 조건대부분의 행이 해당되어 풀 스캔이 낫다
복합 인덱스의 선행 컬럼 누락정렬 기준이 없다
OR 로 다른 컬럼을 묶음각각 다른 인덱스라 합치기 어렵다
WHERE DATE(created_at) = '2026-01-01'   -- 함수. 범위 조건으로 다시 쓴다
WHERE user_id = '12345'                 -- user_id 가 INT 면 변환이 일어난다
WHERE name LIKE '%김%'                   -- 앞 와일드카드

흔한 실수: 옵티마이저가 알아서 해준다고 보는 것. 함수 적용과 타입 불일치는 논리적으로 동등해도 인덱스 정렬 순서를 쓸 수 없어 옵티마이저도 방법이 없습니다.

Q.인덱스를 많이 만들면 어떤 문제가 생기나요?

읽기를 빠르게 하려고 쓰기와 저장 공간을 내주는 것이라, 과하면 손해가 커집니다.

비용내용
쓰기 지연INSERT, UPDATE, DELETE 마다 모든 인덱스를 갱신한다
저장 공간인덱스가 테이블보다 커지는 경우도 있다
메모리 경쟁버퍼 풀을 인덱스가 차지해 데이터 캐시가 밀린다
옵티마이저 혼란후보가 많아지면 잘못된 계획을 고를 수 있다
잠금 범위인덱스마다 잠금이 걸려 경합이 늘어난다

그래서 쓰이지 않는 인덱스를 찾아 지우는 것이 정기 작업입니다. 대부분의 DB 가 인덱스별 사용 통계를 제공합니다.

흔한 실수: 컬럼마다 인덱스를 하나씩 만드는 것. 조건이 여러 컬럼이면 복합 인덱스 하나가 낫고, 단일 인덱스 여러 개를 합치는 방식은 대개 느립니다.

먼저 스스로 답해보고 아래 답변과 견줘보세요. 막히는 부분은 문제로 확인할 수 있어요.

읽었으면 문제로 확인해보세요

데이터베이스 문제를 풀면 틀린 문제가 자동으로 노트에 쌓입니다. 가입 없이 5문제를 먼저 풀어볼 수도 있어요.