날짜: 2025-08-23
아래는 초당 ~1,000건 sort_key 업데이트를 전제로, 단일 테이블 유지 vs 파티셔닝/캐시 분산 선택 기준과 실무 체크리스트입니다. (Django/DRF+AWS, Celery/Redis 전제)
UNIQUE (list_id, sort_key)
sort_key BIGINT
(끼워넣기 중간값)item
(정적) / item_dyn
(정렬, 상태 등) 수직 분할A. 단일 테이블로 계속 간다 (튜닝으로 충분)
wal_buffers
/checkpoint 안정, WAL 생성량 ≤ 20–40MB/s 수준(list_id, sort_key)
유니크 + 조회 커버 1개 정도)B. 해시 파티셔닝으로 스케일아웃(DB 내 분산)
위 지표를 넘어 기류가 생김:
조치: HASH(list_id) 파티션 8~32개 → VACUUM/인덱스 관리 병렬화, 핫스팟 분산
C. 캐시(예: Redis Sorted Set) + 비동기 동기화(읽기/쓰기 분리)
item_dyn(item_id PK, list_id, sort_key, is_active, updated_at)
유니크 & 정렬:
CREATE UNIQUE INDEX uidx_dyn__list__sort ON item_dyn(list_id, sort_key);
CREATE INDEX idx_dyn__list__sort__cover ON item_dyn(list_id, sort_key DESC, item_id);
fillfactor
: 테이블 80, 인덱스 85~90autovacuum per table:
ALTER TABLE item_dyn SET (
autovacuum_vacuum_scale_factor = 0.05,
autovacuum_analyze_scale_factor = 0.02,
autovacuum_vacuum_cost_limit = 2000
);
max_wal_size
넉넉히, checkpoint_completion_target ~ 0.9
INSERT ... ON CONFLICT (list_id, sort_key) DO UPDATE
+ 미세 조정 재시도pg_stat_statements
mean/rowsbloated %
(pgstattuple), autovacuum age/lag위 조건 충족 시 초당 1,000 업데이트도 단일 테이블로 충분히 소화 가능합니다. 병목은 보통 “인덱스 과다”와 “autovacuum/체크포인트 튜닝 부재”에서 옵니다.
언제?
어떻게?
CREATE TABLE item_dyn_p (
item_id BIGINT,
list_id BIGINT,
sort_key BIGINT,
is_active BOOLEAN,
updated_at TIMESTAMPTZ
) PARTITION BY HASH (list_id);
-- 16분할 예 (8~32 권장, 핫스팟/QPS에 맞춰 조절)
CREATE TABLE item_dyn_p0 PARTITION OF item_dyn_p FOR VALUES WITH (MODULUS 16, REMAINDER 0);
-- p1..p15 생략
-- 전파용 제약/인덱스
ALTER TABLE item_dyn_p ADD CONSTRAINT pk_item_dyn PRIMARY KEY (item_id);
CREATE UNIQUE INDEX ON item_dyn_p (list_id, sort_key);
CREATE INDEX ON item_dyn_p (list_id, sort_key DESC, item_id);
패턴: “사용자 인터랙션성 재정렬이 많고, 읽기는 즉시 최신, DB는 최종적 일치(수초 지연 허용)”
ZADD key score member
(Redis Sorted Set)ZREVRANGE key 0 49 WITHSCORES
→ 목록 API 즉시 응답장점: DB 부하 급감(특히 Sort/Top-N), 지연시간 안정 주의: 최종적 일관성 모델 설명 필요, 운영 복잡도↑
항목 | 단일 테이블 유지 | 해시 파티셔닝 | 캐시+비동기 동기화 |
---|---|---|---|
p95 update 지연 | ≤15–25ms | 15–40ms | 읽기 5–20ms(캐시), DB는 배치 |
DB CPU | ≤60% | 60–80% | 40–60%(DB), 캐시에 이전 |
WAL rate | ≤20–40MB/s | 40–80MB/s | DB는 완만, 캐시 I/O↑ |
운용 복잡도 | 낮음 | 중간 | 높음 |
일관성 | 강한 | 강한 | 최종적(수초) |
확장성 한계 | 중간 | 높음 | 매우 높음 |
개선된 질문:
“현재 p95 지연, DB CPU, WAL 속도, bloat, 재시도율(유니크 충돌) 지표를 기반으로 우리 트래픽에 맞는 ‘단일/파티셔닝/캐시’ 권고안을 수치로 제시해줄 수 있나요? pg_stat_statements
/CloudWatch 지표 일부를 공유하겠습니다.”
추가로 할 수 있는 유용한 질문 2개: