데이터베이스 따라잡기

파티셔닝과 샤딩

meellon 2026. 7. 2. 05:30

학습 목표

파티셔닝샤딩의 차이 — 한 DBMS 내부 분할 vs 여러 DB 분산 — 를 설명할 수 있다.

수평·수직 분할과 range·hash·list 파티션 전략을 비교할 수 있다.

샤드 키 선택이 균등 분산·핫스팟·조인에 미치는 영향을 설명할 수 있다.

Partition pruning·co-located shard 개념을 설명할 수 있다.

재샤딩·resharding 비용과 운영 시 주의점을 설명할 수 있다.

문제 상황

  • orders 테이블 8억 행 — 인덱스·VACUUM·백업 한 테이블이 병목
    • DELETE WHERE created_at < '2020'전체 lock·WAL
  • 월별 아카이브만 버리고 싶은데 DROP TABLE만 가능
    • 2020년 데이터만 통째로 제거하고 싶음
  • user_id 순차로 샤딩 — 신규 가입 폭주 shard 과부하
  • tenant_id 없이 샤드 — cross-shard JOIN · 2PC 지옥
  • PostgreSQL 파티션 추가했는데 planner가 전 파티션 scan
    • WHERE파티션 키 없음

앞서 복제같은 데이터 사본 — 이번 편은 데이터를 쪼개 크기·쓰기분산한다.

1. 파티셔닝 vs 샤딩

  파티셔닝 샤딩
범위 한 DBMS · 한 catalog 여러 DB · 여러 노드
SQL SELECT 한 connection (대부분) 샤드 라우터 · fan-out
트랜잭션 로컬 ACID (파티션 간 제약) cross-shard 어려움
목적 관리·pruning·I/O 국소화 수평 확장 (write scale-out)
PG PARTITION BY RANGE Vitess, Citus, app-level shard
Partition:  one PostgreSQL  →  orders_2024, orders_2025  (logical tables)
Sharding:   shard A, B, C   →  separate instances
  • 파티셔닝수평 분할이지만 엔진이 routing·pruning 일부 담당
  • 샤딩앱·미들웨어가 키→shard 매핑 (Citus는 DBMS 내장 샤딩)

2. 수평 vs 수직

  수평 (Horizontal) 수직 (Vertical)
나눔 — 같은 스키마 — 컬럼 분리
월별 orders 파티션 users + user_profiles 테이블
동기 range·hash·list 정규화·wide row 분리
쿼리 pruning · shard key JOIN 필요
Horizontal:  orders WHERE 2025-03  →  partition orders_2025_03 only
Vertical:    users(id, name)  +  user_prefs(user_id, json)  — different tables
  • 수평대용량·time-series·tenant 분리에 흔함
  • 수직LOB·cold column 별도 — 파티션병행 가능

3. 파티션 전략

전략 장점 단점
Range 날짜·ID 구간 pruning·아카이브 DROP hot latest range
List region·tenant enum 명시 구역 폭증 시 관리
Hash hash(user_id) % N 균등 분산 range 쿼리 전 shard
Composite (tenant, date) SaaS + time DDL 복잡
-- PostgreSQL RANGE (code/partition-ddl.sql)
CREATE TABLE orders (
    id          bigint,
    created_at  timestamptz NOT NULL,
    amount      numeric(12,2)
) PARTITION BY RANGE (created_at);

CREATE TABLE orders_2025_01 PARTITION OF orders
    FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');

CREATE TABLE orders_2025_02 PARTITION OF orders
    FOR VALUES FROM ('2025-02-01') TO ('2025-03-01');
-- HASH partition
CREATE TABLE events (
    id bigint,
    user_id bigint NOT NULL,
    payload jsonb
) PARTITION BY HASH (user_id);

CREATE TABLE events_p0 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE events_p1 PARTITION OF events FOR VALUES WITH (MODULUS 4, REMAINDER 1);
Partition pruning planner가 불필요 파티션 제외
조건 WHERE파티션 키created_at BETWEEN ...
실패 WHERE extract(year FROM created_at)=2025함수 on key
EXPLAIN SELECT * FROM orders
WHERE created_at >= '2025-02-01' AND created_at < '2025-03-01';
-- Append -> Seq Scan on orders_2025_02 only (ideal)
  • Global unique — PK가 파티션 키 포함 필요 (PG) — (created_at, id)
  • FK across partition — 제약 제한 — 설계 선행

4. 샤딩과 샤드 키

샤딩샤드 키물리 DB에 배치.

키 후보 분산 조인·쿼리
user_id hash 시 양호 user 로컬 데이터 co-locate
tenant_id SaaS 자연 tenant 격리
auto increment id hot latest shard ❌ 단조 증가
geo region list cross-region join 비용
composite (tenant, user) tenant 균등 multi-tenant 표준
# code/shard-routing.example
def shard_for_user(user_id: int, num_shards: int = 16) -> int:
    return user_id % num_shards

def get_connection(user_id: int):
    shard = shard_for_user(user_id)
    return pools[shard]
패턴  
Co-locate orders·order_items 같은 shard key
Lookup table email → shard directory
Vitess/Citus Vindex·distribution column
  • 핫스팟 — celebrity user·promotion — hash만으로 부족sub-shard·cache
  • Cross-shard — scatter-gather · 비용 큼 — avoid 설계

5. 재샤딩

Resharding — shard 개수·경계 변경 (N2N).

Before:  hash(k) % 4  →  shards 0..3
After:   hash(k) % 8  →  shards 0..7  (rebalance data)
단계  
Dual write old + new shard 동시
Backfill copy historical
Cutover read new mapping
Drain old remove duplicate
비용  
네트워크 TB 이동
일관성 cutover window
routing 버전
  • 미리 shard slot 여유 (1024 virtual → 16 physical) — consistent hashing
  • 파티션 detach (PG) — 한 달 테이블 이동재샤딩보다 가벼움

6. 파티션 vs 복제

  복제 파티션/샤드
데이터 동일 전체 조각
목적 read scale·HA size·write 분할
조합 shard마다 replica 흔함  
Shard 0 Primary + Replicas
Shard 1 Primary + Replicas

7. 체크리스트

항목 확인
쿼리 90%파티션/샤드 키 포함?
Pruning EXPLAINAppend child
PK/UK 파티션 키 포함
Hotspot monotonic id·latest range
Cross-shard TX saga·avoid (분산 트랜잭션 편)
Ops detach/drop old partition · monitor size

8. 정리

  • 파티션한 DB 내 논리 분할 — pruning·아카이브
  • 샤딩여러 DB — write scale-out — routing 필수
  • Range — time 아카이브 · Hash균등 · List — enum
  • 샤드 키co-locate · cross-shard 최소화
  • 재샤딩비용 큼 — virtual shard·파티션 선설계

다음에 다룰 것

  • 분산 트랜잭션 개요
  • 2PC, saga, outbox

해당 내용은 Database System Concepts, 7/E (Avraham Silberschatz, Henry F. Korth, S. Sudarshan), Designing Data-Intensive Applications (Martin Kleppmann) 의 내용을 기반으로 합니다.

'데이터베이스 따라잡기' 카테고리의 다른 글

NoSQL 개요  (0) 2026.07.04
분산 트랜잭션 개요  (0) 2026.07.03
복제  (0) 2026.07.01
MVCC  (0) 2026.06.30
로깅과 복구  (0) 2026.06.29