📝 데이터베이스 강의 노트: 인덱스와 데이터 저장 구조의 이해¶
1. 핵심 질문: "왜 행(Row)만 콕 집어 가져오지 않고, 전체 페이지(Page)를 읽나요?"¶
많은 입문자가 "데이터가 어디 있는지(Row ID 등) 알면 그 부분만 읽으면 되지 않느냐"고 질문합니다. 하지만 현대 데이터베이스 구조상 이는 불가능하거나 비효율적입니다.
이유 1: 가변적인 행 크기 (Variable Row Size)¶
- 고정 크기의 한계: 과거 MyISAM 방식처럼 행 크기를 고정하면 위치 계산은 쉽지만, 빈 공간(Null 값이나 짧은 문자열)에 메모리를 낭비하게 됩니다.
- 현대의 방식: 오늘날 대부분의 엔진(InnoDB 등)은 가변 크기 행을 사용합니다. 행마다 두께가 다르기 때문에, 특정 행이 페이지 내 정확히 몇 바이트 지점에 있는지 미리 계산할 수 없습니다.
이유 2: 하드웨어의 물리적 제약 (Block I/O)¶
- 바이트 단위 접근 불가: HDD나 SSD 같은 저장 장치는 '1바이트' 단위로 데이터를 전송할 능력이 없습니다. 기본적으로 블록(Block) 또는 섹터(Sector) 단위로 묶어서 읽고 씁니다.
- 추상화 계층: OS의 파일 시스템 블록과 DB의 페이지 단위가 맞물려 작동하므로, 최소 단위인 '페이지' 전체를 메모리(RAM)로 올려야만 그 안의 데이터를 살펴볼 수 있습니다.
2. 페이지와 행의 관계 (Storage Hierarchy)¶
강의에서 언급된 용어들이 혼용될 수 있으나, 아래와 같이 구분하면 명확합니다.
| 용어 | 주체 | 설명 |
|---|---|---|
| 페이지(Page) | 데이터베이스 | DB가 데이터를 관리하는 최소 단위 (보통 8KB 또는 16KB) |
| 블록(Block) | 디스크/OS | 물리적 저장 장치에서 한 번에 읽어오는 최소 단위 |
| 힙(Heap) | 데이터 구조 | 데이터가 정렬되지 않은 채로 저장되는 공간 (페이지들의 집합) |
| 행 ID(RID) | 식별자 | 특정 행을 찾기 위한 논리적 주소 (포인터나 배열 인덱스가 아님) |
3. 인덱스 탐색 과정 (B-Tree에서 힙까지)¶
인덱스를 사용해도 결국 페이지를 읽어야 하는 과정은 동일합니다.
- B-Tree 탐색: 루트 페이지부터 리프 페이지까지 이동하며 '페이지 단위'로 읽어 들입니다.
- 리프 페이지 도달: 리프 페이지에는 인덱스 키와 해당 행을 찾을 수 있는 Row ID가 들어있습니다.
- 힙(Heap) 접근: Row ID가 가리키는 실제 데이터 페이지를 디스크에서 RAM으로 가져옵니다.
- 필터링: RAM에 올라온 페이지 내부를 스캔하여 조건에 맞는 행만 추출해 사용자에게 반환합니다.
💡 강의 내용 보충 (Deep Dive)¶
1. 클러스터형 인덱스 (Clustered Index)의 이점¶
"페이지를 가져올 때 필요한 게 다 들어있도록 하는 영리한 방법"이 바로 이것입니다.
- 개념: 인덱스의 리프 페이지에 Row ID 대신 실제 데이터 행 전체를 저장하는 방식입니다.
- 효과: 인덱스를 찾으면 바로 데이터가 있으므로, 별도의 '힙' 페이지를 다시 읽으러 가는 추가 I/O(더블 호핑)를 줄일 수 있습니다. (예: MySQL의 InnoDB 기본 키)
2. 슬롯 디렉토리 (Slot Directory) 구조¶
DB는 페이지 내에서 행의 위치를 찾기 위해 페이지 끝부분에 '슬롯 디렉토리'라는 지도를 가집니다.
- 페이지 전체를 읽은 후, 이 지도를 보고 "아, 3번 행은 이 페이지의 120바이트 지점에서 시작하는구나"라고 파악하여 가변 크기 문제를 해결합니다.
3. 미래의 기술: Byte-Addressable Storage¶
"바이트 주소 지정 가능 시스템"은 NVDIMM이나 CXL(Compute Express Link) 기반의 차세대 메모리 기술을 뜻합니다. 이 기술이 보편화되면 페이지 단위가 아닌 행 단위의 초고속 데이터 접근이 가능해져 DB 아키텍처가 완전히 바뀔 수도 있습니다.