
전체 내용을 큰 그림부터 차례로 쉽게 설명해 드릴게요. 먼저 이 강의의 전체 구조를 한눈에 볼 수 있는 다이어그램입니다.---
1. 파일 구성 기초: DB > 파일 > 레코드 > 필드
데이터베이스는 내부적으로 이렇게 계층 구조로 저장돼요.
- 데이터베이스 → 여러 파일들로 구성 (디스크에 영구 저장)
- 파일 → 여러 레코드의 모음
- 레코드 → 여러 필드 (예: ID, 이름, 부서, 급여)
블록(Block) 이 핵심 개념이에요. 블록은 고정 크기(보통 4~16KB)의 저장 단위로, 디스크와 메모리 사이에 데이터를 주고받는 기본 단위입니다. 한 블록 안에 여러 레코드가 들어가요.
중요한 규칙: 하나의 레코드는 반드시 한 블록 안에 완전히 들어가야 해요. 이미지처럼 블록보다 훨씬 큰 데이터는 따로 저장하고, 레코드에는 그 위치를 가리키는 포인터만 넣습니다.
2. 고정 길이 레코드

고정 길이 레코드는 모든 레코드 크기가 똑같아서 i번째 레코드의 위치를 바로 계산할 수 있어요. 문제는 두 가지예요.
문제 1 — 블록 경계 문제: 블록 크기가 53의 배수가 아니면 레코드가 두 블록에 걸쳐질 수 있어요. 해결책은 블록에 딱 맞는 만큼만 채우고 나머지는 비워두는 것이에요. 블록에 들어갈 레코드 수 = 블록 크기 // 레코드 크기 (정수 나눗셈).
문제 2 — 삭제 문제: 가장 좋은 방법은 **자유 리스트(free-list)**예요. 파일 앞에 헤더를 만들어 삭제된 빈 공간들을 연결 리스트로 관리하고, 새 레코드를 삽입할 때 헤더가 가리키는 빈 자리에 넣는 방식이에요.
3. 가변 길이 레코드

레코드 크기가 제각각인 경우예요 (varchar, 여러 릴레이션이 섞인 파일 등).
표현 방법: 레코드의 앞부분에 [오프셋, 길이] 쌍으로 가변 속성의 위치를 기록하고, 실제 데이터는 뒤에 붙여요. 또 null 비트맵으로 어떤 속성이 null인지 표시해요.
슬롯 페이지 구조(slotted-page structure): 블록 안에 가변 길이 레코드를 저장하는 핵심 기술이에요.블록의 앞(헤더)에는 각 레코드의 위치/크기 정보를, 뒤에서부터는 실제 레코드를 채워요. 포인터는 레코드를 직접 가리키지 않고 헤더 슬롯을 가리켜서, 레코드를 이동해도 포인터가 깨지지 않아요. 이게 단편화 방지의 핵심이에요.
4. 대형 객체 저장 (BLOB/CLOB)
이미지나 동영상처럼 블록보다 훨씬 큰 데이터는 레코드와 따로 저장하고, 레코드에는 포인터만 넣어요. 저장 방법은 두 가지예요.
- DB가 관리하는 파일 시스템 영역에 저장
- DB 내부의 B+ 트리 파일 구성으로 저장 (임의 위치 접근 가능)
Oracle은 SecureFiles + Database File System으로 파일 시스템과 DB를 통합해서 관리해요.
5. 파일에 레코드를 구성하는 방법 5가지

힙 파일: 가장 단순해요. 공간 있는 곳에 그냥 넣어요. **여유공간 맵(free-space map)**으로 빈 블록을 추적하는데, 3비트로 블록의 여유 비율을 저장해요. 대용량에선 2계층 여유 공간 맵을 써서 탐색을 1/n으로 줄여요.
순차 파일: 검색 키 기준으로 정렬 저장해요. 삽입/삭제하면 오버플로 블록이 생기고 물리적 정렬이 깨지므로 주기적으로 파일 재구성이 필요해요.
다중 테이블 군집: department와 instructor처럼 자주 조인하는 테이블을 같은 블록에 저장해요. 조인 성능은 올라가지만 단일 테이블 전체 스캔은 느려질 수 있어요. Oracle에서 CREATE CLUSTER로 구현해요.
분할: transaction_2019, transaction_2020 처럼 연도별로 나눠서 해당 연도 데이터만 스캔해도 되게 해요. Oracle에서 PARTITION BY RANGE, MySQL에서 PARTITION BY LIST로 구현해요.
















6. 데이터 사전 (시스템 카탈로그)
데이터베이스에 관한 데이터(메타데이터)를 저장하는 곳이에요. 릴레이션 이름, 속성 정보, 뷰 정의, 무결성 제약조건, 사용자 권한, 물리적 저장 위치, 인덱스 정보 등이 담겨요. DBMS는 이 메타데이터를 DB 자체의 릴레이션에 저장하고, 자주 접근하므로 시작할 때 인메모리 구조로 미리 읽어와요.
7. 데이터베이스 버퍼와 버퍼 관리자

버퍼(Buffer): 디스크 블록의 복사본을 메모리에 올려두는 공간이에요. 디스크 접근 횟수를 줄이는 게 목표예요.
핵심 개념들:
- Pin/Unpin: 프로세스가 블록을 사용하는 동안 핀을 걸어 교체되지 않게 해요. 핀 수가 0이 되어야 교체할 수 있어요.
- Dirty Bit: 버퍼에서 수정된 블록 표시. 디스크에 다시 써야 하는 블록을 구분해요.
- 공유/독점 잠금: 여러 프로세스가 동시에 읽을 땐 공유 잠금, 쓸 땐 독점 잠금을 써요.
- 강제 출력(forced output): 트랜잭션 커밋 시 데이터가 손실되지 않도록 디스크에 강제로 써요. WAL(로그를 먼저 쓰는 방식)과 함께 사용해요.
버퍼 교체 전략:
- LRU: 최근에 가장 적게 참조된 블록을 교체. 일반적으로 쓰는 방식
- 즉시 전달(toss-immediate): 다시 안 볼 블록은 즉시 버려요 (예: natural join에서 instructor의 마지막 튜플 처리 후)
- MRU: 가장 최근에 사용된 블록을 교체. 특정 조인 패턴에서 LRU보다 효율적이에요 (예: department 릴레이션을 반복 스캔할 때)














8. 열 지향 저장소 (Column-oriented Storage)

열 지향 저장소의 장점:
- 필요한 열만 읽으므로 I/O 감소
- 같은 타입의 값이 모여 있어 압축률이 높음
- CPU 벡터 연산에 유리
단점: 한 행의 여러 속성이 필요할 때는 여러 번 I/O. 갱신도 복잡해요.
열 지향은 데이터웨어하우스처럼 분석 중심 환경에 적합하고, 행 지향은 트랜잭션 처리에 적합해요. ORC, Parquet 같은 파일 포맷은 빅데이터 환경(Hadoop 등)에서 쓰는 열 기반 포맷이에요. 데이터를 스트라이프(stripe) 단위로 나눠 열별로 압축 저장해요.
9. 메인 메모리 데이터베이스
요즘은 RAM이 충분히 커서 DB 전체를 메모리에 올릴 수 있어요. 이 경우:
- 디스크 읽기 I/O가 없으므로 훨씬 빨라요
- 버퍼 관리자가 불필요해요
- 레코드에 직접 포인터를 쓸 수 있어요
- 다만 갱신된 블록은 여전히 디스크에 써야 해요 (영속성)
- 메모리 단편화 관리가 필요해요
요약 정리
주제 핵심 내용
| 파일 구성 | DB > 파일 > 레코드 > 필드, 블록이 저장/전송 단위 |
| 고정 길이 | 자유 리스트로 삭제 공간 관리 |
| 가변 길이 | [오프셋, 길이] 쌍 + 슬롯 페이지 구조 |
| 파일 구성 방법 | 힙 / 순차 / 다중군집 / B+트리 / 해싱 |
| 버퍼 관리 | LRU/MRU 교체, Pin/Unpin, 공유/독점 잠금 |
| 열 지향 저장소 | 분석 쿼리에 유리, 압축률 높음, ORC/Parquet |
어느 부분이 더 궁금하거나 헷갈리는 게 있으면 말씀해 주세요!