35. 블로킹 팩터 (Blocking Factor)와 메모리 I/O 최적화
핵심 인사이트 (3줄 요약)
- 본질: 블로킹 팩터(Blocking Factor)는 하나의 물리적 디스크 블록(Block) 내에 온전히 저장될 수 있는 논리적 데이터 레코드(Record)의 개수를 의미하는 수치 지표다.
- 가치: 블로킹 팩터 수치가 높을수록 한 번의 디스크 암(Arm) 접근으로 더 많은 데이터를 메모리에 퍼 올릴 수 있어, 전체 쿼리 시스템의 디스크 I/O 지연(Latency)을 획기적으로 낮춘다.
- 융합: 운영체제의 페이지/블록 사이즈와 하드웨어 디스크 섹터 구조가 융합된 지점이며, 블록 간 걸침 현상(Spanning) 통제 등 DBMS 스토리지 엔진 설계의 알파이자 오메가이다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
데이터베이스 시스템의 가장 치명적인 약점은 중앙처리장치(CPU)와 보조기억장치(디스크) 간의 처리 속도 격차에 있다. 데이터베이스는 데이터를 1건(1 Record) 단위로 디스크에 읽고 쓰지 않는다. 운영체제의 파일 시스템과 마찬가지로, 데이터를 **블록(Block) 또는 페이지(Page)**라는 고정된 크기의 바구니 단위로 한꺼번에 메모리 버퍼로 퍼 올린다.
이때 "이 바구니(블록) 안에 과연 몇 개의 레코드를 눌러 담을 수 있는가?"를 산출한 값이 바로 **블로킹 팩터 (Blocking Factor)**다. 블록 크기가 4KB이고 레코드 하나가 100바이트라면, 블로킹 팩터는 40이다. 만약 데이터베이스가 40,000건의 데이터를 검색해야 할 때, 블로킹 팩터가 40이라면 디스크 I/O는 1,000번만 발생한다. 하지만 블로킹 팩터가 4라면 I/O는 무려 10,000번으로 폭증한다.
이 도식은 데이터 읽기 과정에서 블로킹 팩터의 크기가 디스크 I/O 횟수에 어떻게 치명적인 영향을 미치는지를 보여주는 큐/병목 시각화다.
[블로킹 팩터(BF) 수치에 따른 디스크 I/O 병목 비교]
(상황) 12건의 레코드를 읽어야 함
A 시스템 (BF = 2, 바구니가 작음)
[디스크] => (I/O 1회) [R1,R2] => (I/O 2회) [R3,R4] ... => (총 6회 I/O 병목 발생) => [Memory]
B 시스템 (BF = 6, 바구니가 큼)
[디스크] => (I/O 1회) [R1~R6] => (I/O 2회) [R7~R12] ====> (총 2회 I/O로 초고속 완료) => [Memory]
이 흐름의 핵심은 물리적인 디스크 기계팔(Arm)이 한 번 움직여서 데이터를 퍼 올릴 때, 덤으로 가져오는 레코드의 밀도가 전체 TPS 성능을 좌우한다는 점이다. 따라서 실무에서 DBA나 아키텍트는 스키마를 설계할 때 불필요한 컬럼 길이를 줄여 레코드 사이즈를 다이어트함으로써, 결과적으로 이 블로킹 팩터 수치를 극대화하려는 처절한 싸움을 벌이게 된다.
📢 섹션 요약 비유: 엘리베이터(디스크 I/O)가 1층에서 꼭대기 층까지 한 번 올라가는데 시간이 엄청나게 걸릴 때, 엘리베이터 정원(블로킹 팩터)이 5명인 것과 20명인 것은 건물 전체의 출근 시간(응답 지연)을 완전히 뒤바꿔버리는 것과 같습니다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
블로킹 팩터를 정확히 계산하기 위해서는 블록 내부의 저장 아키텍처를 이해해야 한다. 레코드를 블록에 담을 때, 레코드의 길이가 블록의 남은 공간보다 크면 어떻게 처리할 것인지에 따라 두 가지 전략적 구조(Spanned vs Unspanned)로 나뉜다.
| 할당 구조 | 원리 및 특징 | 내부 동작 및 파편화 | 블로킹 팩터 수식 (B: 블록 크기, R: 레코드 크기) |
|---|---|---|---|
| 비걸침 레코드 (Unspanned) | 하나의 레코드는 반드시 단일 블록 안에 온전히 들어가야 함 | 남은 공간에 레코드가 들어갈 수 없으면 빈 공간(내부 단편화)으로 버림 | BF = floor(B / R) (버림 연산) |
| 걸침 레코드 (Spanned) | 레코드가 블록 경계를 넘어가면 잘라서 다음 블록에 연결(포인터 유지) | 공간 낭비는 없으나, 읽을 때 2개 블록을 호출해야 하는 추가 I/O 발생 | BF = B / R (소수점 포함 효율) |
실제 환경에서는 가변 길이 데이터를 다루거나, 레코드 크기가 블록 크기보다 큰 경우(예: BLOB, 텍스트) 어쩔 수 없이 Spanned 방식을 혼용한다.
이 구조도는 레코드가 블록에 배치될 때 빈 공간(단편화)이 생기거나 블록 경계를 넘어 걸쳐지는(Spanning) 메커니즘을 명확히 대조하여 보여준다.
[블록 스토리지 할당 구조: Unspanned vs Spanned]
블록 크기: 100 바이트 / 레코드 크기: 60 바이트
1. 비걸침 (Unspanned) - 공간 버림, 속도 최우선
┌────── Block 1 (100B) ──────┐ ┌────── Block 2 (100B) ──────┐
│ [Record 1 (60B)] │ │ [Record 2 (60B)] │
│ [40B 낭비 (단편화)] │ │ [40B 낭비 (단편화)] │
└────────────────────────────┘ └────────────────────────────┘
=> BF는 1. (블록당 1개만 저장 가능)
2. 걸침 (Spanned) - 공간 절약, 디스크 추가 읽기 위험
┌────── Block 1 (100B) ──────┐ ┌────── Block 2 (100B) ──────┐
│ [Record 1 (60B)] │ │ [Rec 2 후반부 (20B)] │
│ [Record 2 전반부(40B)] ─(포인터)─> │ [Record 3 (60B)] │
└────────────────────────────┘ └────────────────────────────┘
=> 빈틈없이 저장. 하지만 Record 2를 읽으려면 Block 1, 2를 모두 I/O 해야 함
이 도식의 배치가 가진 핵심은 공간 효율과 탐색 지연 시간의 트레이드오프다. 비걸침(Unspanned) 방식은 공간을 낭비하더라도 한 번의 블록 I/O로 완벽한 레코드를 획득하겠다는 성능 우선주의이며, 걸침(Spanned) 구조는 포인터 추적으로 인해 추가적인 암(Arm) 이동과 I/O를 감수하고 스토리지를 극한으로 아끼겠다는 전략이다. 따라서 일반적인 관계형 레코드는 가급적 Unspanned 상태를 유지하도록 설계하는 것이 DBMS 내부 동작의 철칙이다.
📢 섹션 요약 비유: 택배 상자(블록)에 긴 우산(레코드)을 넣을 때, 상자가 안 닫히면 공간이 조금 남아도 다음 상자를 쓰는 것(비걸침)과, 우산을 반으로 잘라서 두 상자에 나눠 담고 끈으로 묶어두는 것(걸침)의 구조적 차이입니다.
Ⅲ. 융합 비교 및 다각도 분석 (Comparison & Synergy)
블로킹 팩터는 단순히 DB만의 개념이 아니라, 하드웨어 디스크 섹터 크기와 OS 파일 시스템의 클러스터 크기와 완벽하게 동기화(Alignment)되어야 시너지를 낼 수 있다.
| 컴포넌트 계층 | 관리 단위 및 크기 (일반적) | 최적화를 위한 정렬(Alignment) 연관성 |
|---|---|---|
| 하드웨어 (Disk) | 섹터 (Sector) / 512B ~ 4KB | 가장 밑단의 물리적 한 번의 읽기 크기 |
| 운영체제 (OS File Sys) | 클러스터, 페이지 / 4KB ~ 8KB | 하드웨어 섹터의 배수로 설정됨 |
| 데이터베이스 (DBMS) | 블록 (Block), 페이지 / 8KB ~ 16KB | OS 페이지 크기의 배수로 설정되어야 I/O 경계가 일치함 |
이 계층 비교 표에서 판단해야 할 포인트는 "경계의 불일치"다. 만약 DB 블록 크기를 10KB로 임의 설정했는데 OS 페이지 크기가 4KB라면, DB가 10KB 블록 1개를 요청할 때 OS는 4KB를 3번(12KB) 읽어와야 하는 'I/O 경계 불일치(Boundary Misalignment)' 오버헤드가 발생한다. 이 때문에 실무에서는 반드시 DB 블록 사이즈를 4K, 8K, 16K 등 2의 승수이자 OS 블록의 배수로 설정한다.
블로킹 팩터를 극대화하기 위한 또 다른 비교 대상은 컬럼 데이터 타입이다. VARCHAR 등 가변 길이를 남용하여 레코드 헤더가 길어지면 오히려 블로킹 팩터 수치가 떨어져 버퍼 캐시의 효율성이 무너진다. 반대로 테이블을 수직 분할(Vertical Partitioning)하여 자주 읽는 컬럼만 모아 레코드 크기를 줄이면 블로킹 팩터가 기하급수적으로 늘어나 대량 범위 검색 속도가 압도적으로 빨라진다.
📢 섹션 요약 비유: 마트에서 물건(레코드)을 카트(DB 블록)에 담았는데, 그 카트가 배송 트럭(OS 페이지) 문턱 규격에 딱 맞게 제작되어 있어야 한 번에 밀어 넣을 수 있지, 카트가 조금이라도 더 크면 짐을 빼서 옮겨 실어야 하는 낭비가 발생하는 원리입니다.
Ⅳ. 실무 적용 및 기술사적 판단 (Strategy & Decision)
실무에서 데이터베이스의 병목 현상을 튜닝할 때 블로킹 팩터를 중심으로 한 의사결정은 시스템의 명운을 가른다.
- 테이블 수직 분할(Vertical Partitioning) 설계: 직원의 인사 정보 테이블에
자기소개서(TEXT, 2KB)컬럼이 포함되어 있다고 가정해 보자. 이 상태에서는 블록(8KB) 하나에 고작 3~4명의 직원 레코드만 들어간다(블로킹 팩터 폭락). 결국 '사원 번호'나 '이름'만 조회하는 가벼운 쿼리조차 쓸데없는 자기소개서 문자열을 함께 메모리로 퍼 올려 버퍼 풀(Buffer Pool)을 낭비하게 만든다. 실무에서는 이러한 크고 빈번히 읽지 않는 컬럼을 1:1 관계의 별도 테이블로 쪼개어(수직 분할), 본 테이블의 레코드 크기를 수십 바이트로 줄이고 블로킹 팩터를 100 이상으로 펌핑하는 전략이 필수적이다. - 블록 사이즈 동적 튜닝 안티패턴: 대용량 배치(DW) 환경에서는 블록 크기를 32KB 이상으로 크게 잡아 한 번에 대량으로 읽는 것이 유리하다. 반면, OLTP(단건 갱신) 환경에서 블록 크기를 무턱대고 32KB로 키우면, 특정 1건의 데이터를 갱신할 때 해당 블록 전체에 락(Lock)이 걸리면서 수백 건의 다른 레코드까지 경합(Contention)에 휘말리는 '핫 블록(Hot Block)' 치명타가 발생한다.
[블록 크기 증가에 따른 Hot Block 동시성 경합 시각화]
거대 블록 (32KB, 블로킹 팩터 1000)
┌────────────────────────────────────────────────────────┐
│ [Rec 1] [Rec 2] ... [Rec 500] ... [Rec 1000] │
└────────────────────────────────────────────────────────┘
▲ 사용자 A가 Rec 1 수정 위해 블록 전체 배타적 락(X-Lock) 획득
▲ 사용자 B가 Rec 500 수정 시도 => 대기(Block 락으로 인한 무한 Wait)
이 시각화의 핵심은 블록 안에 너무 많은 레코드를 구겨 넣으면(과도한 블로킹 팩터 확보), 조회 성능은 좋아지지만 동시 수정 작업에서는 재앙적인 병목을 일으킨다는 점이다. 이런 구조는 트랜잭션의 고립성을 떨어뜨리기 때문이며, 따라서 OLTP 환경에서는 적절한 타협점(보통 8KB)을 유지하여 동시성 제어 한계를 방어해야 한다.
📢 섹션 요약 비유: 대형 버스(큰 블록, 높은 블로킹 팩터)는 수십 명을 한 번에 실어 나르는 데 최고지만, 승객 한 명이 내리려 할 때마다 수십 명이 다 같이 정차해서 기다려야 하는 치명적 지연(락 경합)을 초래하는 현상과 같습니다.
Ⅴ. 기대효과 및 결론 (Future & Standard)
데이터베이스 아키텍처에서 레코드 크기를 통제하여 블로킹 팩터를 최적화하는 전략은, 비싼 스토리지 H/W를 교체하지 않고도 논리적 구조 변경만으로 극적인 성능 혁신을 이끌어내는 고도의 기술이다.
| 튜닝 접근법 | 블로킹 팩터 변화 | 정량적 성능 향상 기대효과 |
|---|---|---|
| 거대 문자열 컬럼(BLOB 등) 외부 분리 | BF 5 → BF 150 상승 | 범위 스캔(Full Scan) 시 디스크 I/O 횟수 96% 절감 |
| OS 디스크 클러스터와 블록 크기 동기화 | 경계 일치율 100% 확보 | 더블 리드(Double Read) 오버헤드 소멸, 처리량 30% 증가 |
| OLTP 환경에서 과도한 블록 크기 하향(32K->8K) | 동시성 경합 밀집도 분산 | 레코드 단위 Lock 경합 해소 및 트랜잭션 타임아웃 방지 |
디스크 기반의 RDBMS를 넘어서, 최근 인메모리(In-Memory) 기반의 데이터베이스나 컬럼형(Columnar) 데이터 웨어하우스 시대로 진입하면서 블로킹 팩터의 개념은 'CPU 캐시 라인(Cache Line) 히트율'로 그 무대를 옮기며 한 단계 더 진화하고 있다. 결국 데이터를 어떤 단위의 묶음(블록)으로 이동시킬 것인가에 대한 철학은, 스토리지 매체와 관계없이 영원히 지속될 핵심 표준 성능 지표가 될 것이다.
📢 섹션 요약 비유: 벽돌(레코드)을 맨손으로 한 장씩 나르던 공사장에서, 손수레(블록)의 크기를 직원 체력(OS/디스크)에 딱 맞게 제작하고 꽉 채워(블로킹 팩터) 나르게 함으로써, 공사 기간을 획기적으로 단축한 시스템 최적화의 교과서입니다.
📌 관련 개념 맵 (Knowledge Graph)
- 페이지/블록 (Page/Block) | 디스크 보조기억장치와 메인 메모리(버퍼 캐시) 사이의 고정 크기 데이터 전송 기본 단위
- 수직적 테이블 분할 (Vertical Partitioning) | 레코드 크기를 다이어트하여 블로킹 팩터를 획기적으로 높이기 위한 DB 논리 설계 기법
- 버퍼 풀 (Buffer Pool) | 디스크에서 읽어온 블록을 메모리에 캐싱하여 재접근 시 I/O 비용을 제로화하는 핵심 아키텍처
- 블록 락 경합 (Hot Block) | 하나의 블록에 너무 많은 갱신 트랜잭션이 몰리면서 동시성이 현저히 저하되는 병목 현상
- 내부 단편화 (Internal Fragmentation) | 레코드 포맷을 비걸침(Unspanned)으로 설정할 때 발생하는 블록 내부의 쓸모없는 잉여 여백
👶 어린이를 위한 3줄 비유 설명
- 컴퓨터가 데이터를 찾을 때 창고(디스크)에서 하나씩 꺼내오면 너무 힘드니까, 한 번에 '상자(블록)' 단위로 퍼서 책상(메모리)으로 가져와요.
- 이때 한 상자 안에 물건(레코드)을 5개 넣을 수 있는지 100개 넣을 수 있는지 계산한 숫자가 바로 '블로킹 팩터'랍니다.
- 이 숫자가 클수록 똑같은 상자 수로 더 많은 물건을 빨리 나를 수 있어서, 데이터베이스가 엄청나게 똑똑하고 빨라지게 돼요!