데이터베이스 인덱싱 기술적 원리

서론: 인덱스의 기술적 배경과 I/O 병목 해결

데이터베이스 시스템의 발전 과정은 CPU와 저장 장치(Disk) 간의 처리 속도 차이를 해결하기 위한 과정이다. 중앙 처리 장치(CPU)는 나노초(ns) 단위로 데이터를 처리하지만, 디스크 I/O는 물리적 한계로 인해 밀리초(ms)나 마이크로초(µs) 단위의 지연 시간이 발생한다. 이 ‘I/O Gap’은 시스템 전체 성능의 주요 병목 지점이며, 인덱스(Index)는 이를 보완하는 소프트웨어적 해결책이다.

백엔드 개발자에게 인덱스란 단순한 속도 향상 도구를 넘어, 자료 구조를 활용해 데이터 검색 비용을 선형 시간(O(N))에서 로그 시간(O(log N))으로 줄이는 장치다. 인덱스는 디스크의 최소 읽기 단위인 페이지(Page) 접근을 최소화하도록 설계된 포인터 체계다. 이는 읽기 성능을 높이는 대신, 쓰기 성능 저하와 저장 공간 추가 점유라는 비용을 지불하는 트레이드오프(Trade-off) 관계에 있다.

이에 데이터베이스는 디스크 I/O 효율을 극대화하기 위해 B-Tree 계열의 자료 구조를 핵심적으로 사용한다.

인덱스 자료 구조: B-Tree와 B+Tree

데이터베이스 인덱스는 디스크 I/O 횟수를 줄이기 위해 트리의 높이(Height)를 낮게 유지하는 구조를 사용한다.

B-Tree: 균형 유지 구조

B-Tree는 모든 리프 노드(Leaf Node)가 동일한 깊이를 유지하는 다차원 트리다.

B+Tree: 디스크 최적화 구조

대부분의 현대 DBMS는 B-Tree를 개선한 B+Tree를 사용한다.

비교 항목 B-Tree B+Tree
데이터 위치 모든 노드 리프 노드에만 저장
내부 노드 구성 키 + 데이터 + 포인터 키 + 포인터 (더 많은 키 수용)
트리 높이 상대적으로 높음 매우 낮음
범위 검색 모든 노드 순회 필요 리프 노드 간 순차 읽기 가능

B+Tree가 인덱스의 표준으로 자리 잡았으나, 실제 엔진 레벨에서의 구현은 상이하다. MySQL과 PostgreSQL은 이 자료 구조를 각기 다른 아키텍처 방식으로 해석하여 적용하고 있다.

DBMS 아키텍처별 인덱스 구현

MySQL InnoDB: 클러스터드 인덱스 아키텍처

InnoDB는 데이터와 인덱스가 결합된 Index-Organized Table(IOT) 구조다.

PostgreSQL: 힙(Heap) 테이블 아키텍처

데이터 파일과 인덱스 파일을 독립적으로 관리한다.

각 DBMS의 아키텍처 특성을 파악했다면, 다음으로 이를 활용해 쿼리 성능을 극대화할 수 있는 인덱스 설계 전략을 수립해야 한다.

인덱스 설계 및 최적화 전략

복합 인덱스와 최좌측 접두사(Leftmost Prefix)

(A, B, C) 순서의 인덱스는 A를 기준으로 먼저 정렬된 후 B, C 순으로 정렬된다. 따라서 WHERE 절에 A 조건이 없으면 인덱스를 정상적으로 활용할 수 없다.

커버링 인덱스(Covering Index)

쿼리에 필요한 모든 컬럼이 인덱스 자체에 포함된 경우다. 실제 테이블 데이터를 읽으러 갈 필요가 없으므로 I/O 비용이 대폭 감소한다.

카디널리티와 선택도

인덱스는 읽기 성능을 보장하는 대신, 데이터 변경 시에는 필연적으로 쓰기 오버헤드가 발생한다. 이러한 트레이드오프를 관리하기 위해 내부적으로 다양한 쓰기 최적화 메커니즘이 동작한다.

쓰기 부하와 내부 메커니즘

페이지 분할(Page Splitting)

무작위 UUID(v4)처럼 정렬되지 않은 값을 PK로 삽입하면, B+Tree 중간에 데이터를 끼워 넣어야 한다. 이때 페이지 공간이 부족하면 페이지를 나누는 ‘페이지 분할’이 발생하며, 이는 디스크 쓰기 부하와 인덱스 파편화를 유발한다. (UUID v7 등 정렬 가능한 키 권장)

최적화 기술 (Change Buffer & HOT)

설계한 인덱스와 최적화 기법이 의도대로 동작하는지는 데이터베이스의 실행 계획(Explain)을 분석하여 객관적으로 검증할 수 있다.

실행 계획(Explain) 분석 지표

MySQL 지표

PostgreSQL 지표

결론

인덱스는 데이터베이스의 I/O 비용을 관리하기 위한 핵심적인 공학적 도구다. B+Tree 구조를 바탕으로 각 DBMS가 채택한 아키텍처(Clustered vs Heap)를 이해하면 더욱 정교한 성능 튜닝이 가능하다. 백엔드 개발자는 데이터의 분포와 쿼리 패턴을 분석하여 효율적인 인덱스를 설계하고, 정기적으로 실행 계획을 점검하여 시스템 성능을 유지해야 한다.