한양과학기술고등학교

에듀테크 프로젝트 대시보드

데이터베이스 샤딩

데이터베이스 샤딩 (Sharding)

테이블 하나가 한 서버에 다 안 들어갈 만큼 커지면? 행(row)을 규칙에 따라 여러 서버에 나눠 담는다. 각 조각이 샤드(shard)다. 도서관 장서를 건물 여러 채에 분산 보관하는 것과 같다 — 문제는 "어떤 책을 어느 건물에?"를 정하는 규칙이다.

1. 복제 · 수직 분할 · 수평 분할(샤딩)

방식무엇을 나누나목적 / 한계
복제 (Replication)같은 데이터를 여러 서버에 복사읽기 부하 분산·가용성 ↑ / 쓰기·용량은 그대로
수직 분할테이블을 컬럼 기준으로 분리 (자주 쓰는 컬럼 / 큰 컬럼)단순하지만 한 테이블이 계속 크면 결국 한계
수평 분할 = 샤딩테이블을 행 기준으로 여러 서버에 분배용량·쓰기까지 분산 / 라우팅·조인·트랜잭션이 복잡해짐

파티셔닝 vs 샤딩: 한 DB 서버 안에서 테이블을 물리적으로 쪼개면 파티셔닝, 그 조각들을 서로 다른 머신에 흩으면 샤딩이라고 부른다. 규칙(범위·해시)은 똑같다.

2. 직접 돌려보기 — 학생 레코드를 샤드에 분배

샤드 키는 student_id(가입 순서대로 1씩 증가). 전략을 바꿔가며 레코드를 넣어보고, 샤드를 추가했을 때 기존 데이터가 얼마나 이사(재배치)해야 하는지 관찰하자.

총 레코드 0 샤드 수 4 불균형(최대/평균) 1.0× 마지막 작업 재배치 0
조회:
전략을 고르고 레코드를 넣어보세요.
범위 분할 — id 구간을 샤드에 배정. 조회 라우팅이 쉽지만, id가 계속 커지면 항상 마지막 샤드에만 쓰기가 몰린다(쓰기 핫스팟).
해시 %N — shard = id % N. 분포는 고르지만 N이 바뀌면 거의 모든 행이 새 샤드로 이사해야 한다.
일관된 해시 — 해시 링 위에 샤드를 배치. 샤드를 추가해도 약 1/N만 이동한다 (/consistent-hashing 참고).
초록 칩=방금 삽입, 주황 칩=이번 작업으로 이사한 레코드.

3. 쿼리 라우팅 — 샤드 키가 있느냐 없느냐

4. 샤드 키를 잘 고르는 법

5. 라우팅 코드

# 애플리케이션(또는 프록시)이 쿼리 전에 샤드를 계산한다
SHARDS = [db0, db1, db2, db3]

def route(student_id):
    # 해시 샤딩: 분포는 고르지만 len(SHARDS)가 바뀌면 대이동
    return SHARDS[hash(student_id) % len(SHARDS)]

def get_student(student_id):
    return route(student_id).query(
        "SELECT * FROM students WHERE id = %s", student_id)

def search_by_name(prefix):
    # 샤드 키가 없다 → 모든 샤드에 흩뿌리고(scatter) 모은다(gather)
    rows = []
    for s in SHARDS:
        rows += s.query("SELECT * FROM students WHERE name LIKE %s", prefix + "%")
    return sorted(rows, key=lambda r: r.name)   # 앱에서 병합·정렬

6. 자주 하는 오해