도입 배경
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 확장 모듈로 파티션 관리 자동화 가능 (대규모에만 추천)
요약
•
채팅 데이터는 빠르게 쌓이지만, 주로 최근 채팅만 조회됨
•
월별 파티셔닝으로 성능 저하 없이 데이터 장기 보관 + 유연한 삭제 가능
•
복잡도는 최소화하고, 확장성은 확보함