PostgreSQL 자동 VACUUM과 테이블 블로트 해결법
PostgreSQL 자동 VACUUM의 동작 원리, 테이블 블로트 발생 원인과 진단 방법, vacuum 튜닝 postgres 예시 및 모니터링 절차 모음집
목차
소개
PostgreSQL에서 자동 VACUUM은 공간 회수와 MVCC 유지에 핵심적이다. 그러나 기본 설정만으로는 대규모 변경이 잦은 워크로드에서 테이블 블로트(bloat)가 쌓일 수 있다. 이 글은 postgres autovacuum 튜닝의 핵심 개념과 테이블 블로트 해결 postgres를 위한 실무 절차를 정리한다. 처음 접하는 사람도 이해하기 쉽도록 원리, 진단, 설정, 모니터링 순으로 설명한다.
자동 VACUUM의 기본 원리
MVCC와 죽은 튜플
PostgreSQL은 MVCC(Multi-Version Concurrency Control)를 사용해 트랜잭션간 일관성을 제공한다. UPDATE나 DELETE가 발생하면 기존 튜플은 그대로 남고 새로운 버전이 생성된다. 이 과정에서 더 이상 참조되지 않는 죽은 튜플(dead tuple)은 파일 내에 남아 디스크 공간을 차지한다.
VACUUM의 역할
VACUUM은 죽은 튜플을 마크하거나 제거해 재사용 가능한 공간으로 표시한다. AUTOVACUUM는 이를 자동화하되, 트랜잭션 가시성과 통계를 고려해 동작한다. 그러나 빈번한 수정이나 대량 삭제가 있으면 자동 동작만으로는 충분치 않을 수 있다.
테이블 블로트가 발생하는 이유
- 대량 DELETE/UPDATE로 인해 죽은 튜플이 급증
- 긴 트랜잭션이나 장기 실행 쿼리로 인해 VACUUM이 죽은 튜플을 회수하지 못함
- Autovacuum 임계치 설정이 보수적으로 되어 있음
- 인덱스 블로트: 데이터만이 아니라 인덱스도 확장되어 성능 저하 유발
진단 방법
테이블 수준 통계 확인
pg_stat_user_tables와 pgstattuple을 이용하면 블로트 수준을 파악할 수 있다. 다음 쿼리로 dead tuples와 table size를 확인한다.
SELECT schemaname, relname, n_live_tup, n_dead_tup, pg_total_relation_size(relid) AS total_bytes
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 20;
정밀 진단: pgstattuple
pgstattuple 확장으로 실제 블로트 비율을 확인한다. 설치가 필요하면 CREATE EXTENSION 사용.
CREATE EXTENSION IF NOT EXISTS pgstattuple;
SELECT * FROM pgstattuple('schema.table_name');
vacuum 튜닝 postgres: 설정 포인트
아래 파라미터는 일반적으로 조정 대상이다. 워크로드에 맞춰 단계적으로 변경하면서 위험을 최소화하는 것이 권장 방식이다.
- autovacuum_vacuum_threshold / autovacuum_vacuum_scale_factor: 개별 테이블의 임계치 조절
- autovacuum_analyze_threshold / autovacuum_analyze_scale_factor: 통계 수집 임계치
- autovacuum_max_workers: 동시 작업자 수
- autovacuum_vacuum_cost_limit / autovacuum_vacuum_cost_delay: I/O 영향 제어
- vacuum_cost_page_hit 등: 전체 VACUUM 행동 제어
예시로, 자주 변경되는 대형 테이블에는 scale_factor를 낮춰 자주 트리거되게 한다.
# postgresql.conf 예시
autovacuum_vacuum_scale_factor = 0.01
autovacuum_vacuum_threshold = 50
autovacuum_max_workers = 6
autovacuum_vacuum_cost_delay = 20ms
테이블별 설정
ALTER TABLE로 특정 테이블만 조절할 수 있다. 중요한 테이블에만 aggressive한 값 적용으로 전체 영향 최소화가 가능하다.
ALTER TABLE schema.table_name SET (autovacuum_vacuum_scale_factor = 0.005, autovacuum_vacuum_threshold = 100);
ALTER TABLE schema.table_name SET (autovacuum_vacuum_cost_delay = '10ms');
수동 관리 및 리빌드
수동 VACUUM과 VACUUM FULL
단기간에 큰 공간 회수가 필요하면 VACUUM FULL이나 REINDEX를 사용한다. 다만 VACUUM FULL은 테이블 잠금으로 인한 영향이 크므로 유지보수 창에서 실행하는 것이 안전하다.
VACUUM (VERBOSE, ANALYZE) schema.table_name;
-- 테이블 잠금이 허용될 때
VACUUM FULL schema.table_name;
REINDEX TABLE schema.table_name;
대체 전략: pg_repack
pg_repack은 테이블 잠금 없이 물리적 재정렬을 지원해 프로덕션 환경에서 유용하다. 설치와 테스트 후 운영에 적용하는 방식이 일반적이다.
모니터링과 운영 체크리스트
- 주기적으로 pg_stat_user_tables와 pgstattuple로 블로트 추적
- autovacuum 로그(VERBOSE)로 실제 동작과 지연 원인 확인
- 긴 트랜잭션을 방지하도록 애플리케이션 쿼리 타임아웃 검토
- 백업/복원 및 유지보수 시간에 VACUUM FULL이나 REINDEX 계획
마무리
테이블 블로트는 방치하면 디스크 사용량 증가와 쿼리 성능 저하로 이어진다. postgres autovacuum 튜닝은 단순값 변경이 아니라 워크로드 분석과 단계적 적용이 핵심이다. 위 절차를 따라 진단하고, 테이블별 설정과 모니터링을 병행하면 안정적인 공간 관리와 성능 유지가 가능하다.