268. 수평 분할 (Horizontal Fragmentation)
핵심 인사이트 (3줄 요약)
- 본질: 수평 분할은 테이블의 행(Tuple) 단위로 데이터를 물리적으로 분할하여, 각 분할이 원래 테이블의 일부 행만을 포함하는 분할 기법이다.
- 가치: 필요한 행만 접근하여 조회 성능을 향상시키고, 데이터 관리 편의성을 높이며, 장애 시 영향 범위를 제한한다.
- 융합: 수직 분할, 분할 정합성, 분산 데이터베이스, 파티셔닝, 분할 프루닝과 밀접하게 연관된다.
Ⅰ. 개요 및 필요성 (Context & Necessity)
개념 정의
수평 분할(Horizontal Fragmentation)은 테이블의 행(Tuple) 단위로 데이터를 물리적으로 분할하는 기법이다. 각 분할(Fragment)은 원래 테이블의 일부 행만을 포함하며, 일반적으로 WHERE 절 조건에 의해 분할이 결정된다. 예를 들어 지역별 고객 테이블을 서울, 부산, 인천 지역별로 분할하는 것이 수평 분할에 해당한다.
필요성
대규모 테이블에서 전체 스캔은 성능 저하의 주요 원인이다. 또한 특정 조건에 맞는 데이터만 조회하는 경우에도 전체 테이블을 읽어야 하는 overhead가 있다. 수평 분할을 통해 필요한 분할만 접근하면 성능을 크게 향상시킬 수 있다.
배경
수평 분할은 1980년대 분산 데이터베이스 연구에서 비롯되었으며, 이후 Oracle, PostgreSQL, MySQL, MongoDB, Cassandra 등 대부분의 관계형 및 분산 데이터베이스에서 구현되고 있다.
비유
수평 분할은大型도서관의 도서 분류와 같다. 모든 책을 한 곳에 쌓아두면 찾기 어렵지만, 분야별로,年代별로 나누어 두면 필요한 책을 빠르게 찾을 수 있다.
📢 섹션 요약: 수평 분할은 행 단위로 데이터를 물리적 분할하여, 필요한 분할만 접근함으로써 조회 성능을 향상시키는 기법이다.
Ⅱ. 아키텍처 및 핵심 원리 (Deep Dive)
수평 분할 동작
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수평 분할 동작 구조 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ [원래 테이블: customers] │
│ ┌──────┬──────────┬──────────┬──────────┐ │
│ │ ID │ Name │ Region │ Balance │ │
│ ├──────┼──────────┼──────────┼──────────┤ │
│ │ C001 │ Kim │ SEOUL │ 1000 │ │
│ │ C002 │ Lee │ BUSAN │ 2000 │ │
│ │ C003 │ Park │ SEOUL │ 1500 │ │
│ │ C004 │ Choi │ INCHEON │ 3000 │ │
│ │ C005 │ Jung │ BUSAN │ 2500 │ │
│ │ C006 │ Moon │ SEOUL │ 1800 │ │
│ │ C007 │ Son │ INCHEON │ 2200 │ │
│ │ C008 │ Jang │ BUSAN │ 2700 │ │
│ └──────┴──────────┴──────────┴──────────┘ │
│ │
│ [수평 분할 결과] │
│ │
│ customers_seoul (region = 'SEOUL'): │
│ ┌──────┬──────────┬──────────┬──────────┐ │
│ │ C001 │ Kim │ SEOUL │ 1000 │ │
│ │ C003 │ Park │ SEOUL │ 1500 │ │
│ │ C006 │ Moon │ SEOUL │ 1800 │ │
│ └──────┴──────────┴──────────┴──────────┘ │
│ │
│ customers_busan (region = 'BUSAN'): │
│ ┌──────┬──────────┬──────────┬──────────┐ │
│ │ C002 │ Lee │ BUSAN │ 2000 │ │
│ │ C005 │ Jung │ BUSAN │ 2500 │ │
│ │ C008 │ Jang │ BUSAN │ 2700 │ │
│ └──────┴──────────┴──────────┴──────────┘ │
│ │
│ customers_incheon (region = 'INCHEON'): │
│ ┌──────┬──────────┬──────────┬──────────┐ │
│ │ C004 │ Choi │ INCHEON │ 3000 │ │
│ │ C007 │ Son │ INCHEON │ 2200 │ │
│ └──────┴──────────┴──────────┴──────────┘ │
│ │
│ [재구성: UNION] │
│ SELECT * FROM customers_seoul │
│ UNION ALL │
│ SELECT * FROM customers_busan │
│ UNION ALL │
│ SELECT * FROM customers_incheon; │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
수평 분할 방법
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수평 분할 방법 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 유도적 분할 (Derived Horizontal Fragmentation) │
│ ──────────────────────────────────────────── │
│ • 상관 관계(Relationship)에 의해 분할 │
│ • 예: orders 테이블이 customers 테이블와 조인되어 있으면, │
│ customers 분할에 따라 orders도 분할 │
│ │
│ 2. 조건 분할 (Predicate-based Fragmentation) │
│ ───────────────────────────────────────────── │
│ • 분할 조건(Predicate)을 명시적으로 정의 │
│ • 예: region = 'SEOUL', region = 'BUSAN' 등 │
│ │
│ 3. 해시 분할 (Hash-based / Hash Partitioning) │
│ ────────────────────────────────────────── │
│ • 해시 함수 결과에 따라 분할 │
│ • 분포 균일, 하지만 특정 행이 어느 분할에 있는지 예측 어려움 │
│ • 예: HASH(customer_id) MOD 4 = 0, 1, 2, 3 │
│ │
│ 4. 범위 분할 (Range-based Fragmentation) │
│ ────────────────────────────────────────── │
│ • 특정 컬럼의 값 범위로 분할 │
│ • 예: order_date 기반 (2024-Q1, 2024-Q2, 등) │
│ • 범위 查询에 효율적 │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ 범위 분할 vs 해시 분할 비교 │ │
│ │ │ │
│ │ ┌────────────────┬─────────────────┬─────────────────┐ │ │
│ │ │ 항목 │ 범위 분할 │ 해시 분할 │ │ │
│ │ ├────────────────┼─────────────────┼─────────────────┤ │ │
│ │ │ 분포 균일성 │ 불균일할 수 있음 │ 비교적 균일 │ │ │
│ │ ├────────────────┼─────────────────┼─────────────────┤ │ │
│ │ │ 범위 查询 효율 │ 높음 │ 낮음 │ │ │
│ │ ├────────────────┼─────────────────┼─────────────────┤ │ │
│ │ │ 특정 查询 효율 │ 해당 범위만 접근 │ 전체 분할 스캔 │ │ │
│ │ ├────────────────┼─────────────────┼─────────────────┤ │ │
│ │ │ 핫스팟 가능성 │ 높음 (크기 차이) │ 낮음 (균등 분배) │ │ │
│ │ └────────────────┴─────────────────┴─────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
분할 정합성과 수평 분할
┌─────────────────────────────────────────────────────────────────────────────┐
│ 수평 분할 정합성 규칙 │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. 완전성 (Completeness) │
│ ───────────────────── │
│ • 원래 테이블의 모든 행이 분할에 포함 │
│ • customers (8행) = customers_seoul (3행) + │
│ customers_busan (3행) + │
│ customers_incheon (2행) = 8행 ✓ │
│ │
│ 2. 재구성 가능성 (Reconstruction) │
│ ───────────────────────── │
│ • UNION ALL로 원래 테이블 재구성 가능 │
│ • customers_seoul UNION ALL customers_busan UNION ALL │
│ customers_incheon = customers ✓ │
│ │
│ 3. 중복 없음 (Disjointness) │
│ ──────────────────── │
│ • 각 행이 하나의 분할에만 존재 │
│ • 중복: customer C001이 두 분할에 동시에 존재 X │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
[다이어그램 해설] 수평 분할의 핵심은 분할 정합성 규칙을 만족하는 것이다. 완전성은 모든 행이 분할에 포함되어야 함을, 재구성 가능성은 UNION으로 원래 테이블을 복원할 수 있어야 함을, 중복 없음은 각 행이 하나의 분할에만 존재해야 함을 의미한다.
📢 섹션 요약: 수평 분할은 분할 정합성 규칙(완전성, 재구성 가능성, 중복 없음)을 만족해야 하며, 범위 분할, 해시 분할 등의 방법이 있다.
Ⅲ. 구현 및 실무 응용 (Implementation & Practice)
PostgreSQL 수평 분할
-- PostgreSQL: 범위 기반 수평 분할
CREATE TABLE orders (
order_id BIGSERIAL,
customer_id INTEGER,
order_date DATE NOT NULL,
total DECIMAL
) PARTITION BY RANGE (order_date);
-- 분할 테이블 생성
CREATE TABLE orders_2023 PARTITION OF orders
FOR VALUES FROM ('2023-01-01') TO ('2024-01-01');
CREATE TABLE orders_2024_q1 PARTITION OF orders
FOR VALUES FROM ('2024-01-01') TO ('2024-04-01');
CREATE TABLE orders_2024_q2 PARTITION OF orders
FOR VALUES FROM ('2024-04-01') TO ('2024-07-01');
CREATE TABLE orders_2024_q3 PARTITION OF orders
FOR VALUES FROM ('2024-07-01') TO ('2024-10-01');
CREATE TABLE orders_2024_q4 PARTITION OF orders
FOR VALUES FROM ('2024-10-01') TO ('2025-01-01');
-- 쿼리: 분할 프루닝 확인
EXPLAIN SELECT * FROM orders WHERE order_date >= '2024-07-01';
-- → Append on orders_2024_q3, orders_2024_q4
-- → 불필요한 분할 스캔 회피
MongoDB 수평 분할
// MongoDB: 컬렉션 샤딩 (수평 분할)
// 범위 기반 샤딩
sh.shardCollection("mydb.orders", {order_date: 1})
// 해시 기반 샤딩
sh.shardCollection("mydb.customers", {customer_id: "hashed"})
// 분할 상태 확인
db.adminCommand({getShardDistribution: 1})
// 쿼리: 분할 프루닝
db.orders.find({order_date: {$gte: ISODate("2024-07-01")}})
db.customers.find({customer_id: "C001"})
// → 해당 샤드만 접근
MySQL 수평 분할
-- MySQL: 파티셔닝
CREATE TABLE orders (
order_id INT,
customer_id INT,
order_date DATE,
total DECIMAL
)
PARTITION BY RANGE (YEAR(order_date)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024_q1 VALUES LESS THAN (2024*4+1), -- 관대한 값
PARTITION p2024_q2 VALUES LESS THAN (2024*4+4),
PARTITION p2024_q3 VALUES LESS THAN (2024*4+7),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
-- 쿼리
SELECT * FROM orders WHERE order_date >= '2024-07-01';
-- → p2024_q3, p_future만 스캔 (분할 프루닝)
📢 섹션 요약: PostgreSQL, MongoDB, MySQL 등 주요 DB에서 수평 분할/파티셔닝을 지원하며, 분할 프루닝으로 불필요한 분할 접근을 회피한다.
Ⅳ. 결론
수평 분할은 행 단위로 데이터를 물리적 분할하여 조회 성능을 향상시키는 기법이다. 범위 분할, 해시 분할 등의 방법이 있으며, 분할 정합성 규칙을 만족해야 한다. 분할 키 선택이 성능에 큰 영향을 미치므로, 자주 查询 조건으로 사용되는 컬럼을 기준으로 분할하는 것이 중요하다.
📢 섹션 요약: 수평 분할은 행 단위 분할로 조회 성능을 향상시키지만, 분할 키 선택과 분할 정합성 고려가 핵심 설계 요소이다.
핵심 인사이트 ASCII 다이어그램 (Concept Map)
┌─────────────────────────────────────────────────────────────────────────────┐
│ Horizontal Fragmentation Concept Map │
│ │
│ ┌───────────────────────────┐ │
│ │ Horizontal Fragmentation │ │
│ │ (수평 분할) │ │
│ └───────────┬───────────────┘ │
│ │ │
│ ┌──────────────────┼──────────────────┐ │
│ ▼ ▼ ▼ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Range │ │ Hash │ │Derived │ │
│ │(범위분할)│ │(해시분할)│ │(유도분할)│ │
│ └────┬────┘ └────┬────┘ └────┬────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ 분할 정합성: 완전성 | 재구성 | 중복없음 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
참고
- 수평 분할은 행(Tuple) 단위로 데이터를 물리적 분할한다.
- 분할 정합성 규칙(완전성, 재구성 가능성, 중복 없음)을 만족해야 한다.
- 범위 분할, 해시 분할, 유도적 분할 등의 방법이 있다.
- 분할 프루닝으로 불필요한 분할 접근을 회피하여 성능을 향상시킨다.