Search

PostgreSQL 월별 파티셔닝 전략 정리

생성일
2025/04/29 07:53
태그
AI 요약
날짜
상위 항목
하위 항목

도입 배경

1. 데이터 증가 문제

하루 약 400MB 수준의 채팅 데이터가 지속적으로 쌓임
단일 테이블에 모든 데이터를 저장할 경우:
인덱스 사이즈 급증
조회 성능 저하 (Full Table Scan 위험)
백업/복구 시간 증가
디스크 IO 부담 가중

2. 조회 패턴 최적화 필요

채팅 데이터는 대부분 최근 기간을 기준으로 조회
오래된 데이터는 조회 빈도가 급격히 낮음
특정 기간(1일~10일 등) 범위로 조회하는 경우가 많음
전체 데이터가 아니라 "필요한 기간 데이터"만 빠르게 조회해야 했다

3. 운영 및 유지보수 편의성 확보

오래된 데이터는 쉽게 삭제하거나 백업하고 싶었음
월별로 데이터 관리 단위를 나누면:
백업/삭제 대상 명확
운영 비용 예측 쉬움
서버 부하 관리 용이

4. 대안 검토 결과

대안
결과
단일 테이블 유지
데이터가 커지면서 성능 하락 우려
NoSQL 전환
트래픽 규모 대비 과잉 설계
Object Storage 아카이빙
운영 복잡도 증가, 실익 적음
월별 파티셔닝
성능, 운영, 확장성 균형 잡힌 최적 솔루션

5. 최종 결정

PostgreSQL 월별 파티셔닝을 적용하여 데이터 증가에 유연하게 대응하고, 조회 성능을 안정적으로 유지한다.

파티셔닝 개요

cannelLiveLog 메인 테이블을 createdAt 기준으로 월별 파티셔닝
새로운 월이 되면 자동으로 새 파티션 생성
쿼리 성능 최적화 (Partition Pruning 사용)
데이터 운영 및 보관 관리 용이

ChannelLiveLog 테이블 생성

CREATE TABLE public."channelLiveLog" ( id serial4 NOT NULL, "createdAt" timestamptz DEFAULT now() NOT NULL, "updatedAt" timestamptz DEFAULT now() NOT NULL, "liveTitle" varchar(100) NOT NULL, "concurrentUserCount" int4 NOT NULL, "accumulateCount" int4 NOT NULL, "minFollowerMinute" int4 NOT NULL, "channelLiveId" int4 NULL, "liveCategoryId" int4 NULL, CONSTRAINT "PK_ccc5b2a4c5ef7818610442945ef" PRIMARY KEY (id) ) PARTITION BY RANGE (timestamp);
SQL
복사

월별 파티션 생성 SQL

다음 달 파티션을 미리 만들어두는 SQL 스크립트
DO $$ DECLARE next_month_start date := date_trunc('month', now()) + interval '1 month'; next_month_end date := next_month_start + interval '1 month'; partition_name text; BEGIN partition_name := 'channelLiveLog' || to_char(next_month_start, 'YYYYMM'); EXECUTE format(' CREATE TABLE IF NOT EXISTS %I PARTITION OF chat_index FOR VALUES FROM (%L) TO (%L); ', partition_name, next_month_start, next_month_end); END $$;
SQL
복사
매달 25일 경에 실행 권장
cron 스케줄러로 자동화 가능

오래된 파티션 삭제 SQL

6개월 이전 파티션을 자동으로 삭제하는 SQL 스크립트
sql 복사편집 DO $$ DECLARE old_month date := date_trunc('month', now()) - interval '6 months'; partition_name text; BEGIN partition_name := 'chat_index_' || to_char(old_month, 'YYYYMM'); EXECUTE format('DROP TABLE IF EXISTS %I CASCADE;', partition_name); END $$;
SQL
복사
매달 1일 경에 실행 권장
cron 스케줄러로 자동화 가능

주의할 점

WHERE timestamp BETWEEN ... 쿼리를 반드시 사용할 것
timestamp에 직접 조건을 걸어야 Partition Pruning이 작동
함수(date(timestamp))를 적용하면 Pruning이 깨질 수 있음

추가 운영 팁

파티션별 별도 인덱스 생성 추천
백업 시 파티션별로 따로 백업 가능
필요시 pg_partman 확장 모듈로 파티션 관리 자동화 가능 (대규모에만 추천)

요약

채팅 데이터는 빠르게 쌓이지만, 주로 최근 채팅만 조회됨
월별 파티셔닝으로 성능 저하 없이 데이터 장기 보관 + 유연한 삭제 가능
복잡도는 최소화하고, 확장성은 확보함