Database/RDBMS

Postgres Auto vacuum 의 중요성

귀찮은 개발자 2025. 2. 17. 19:53

 

PostgreSQL 를 사용하다 보면 어느 순간 디스크가 기하급수적으로 늘어난다.
DELETE / UPDATE 가 지속적으로 발생하면서 디스크는 크게 줄지 않고, 비용은 점점 올라간다.
뿐만 아니라 쿼리 성능 저하, 인덱스 비대화의 문제로 데이터베이스의 성능이 점차 떨어진다.

Auto vacuum이 안 돌면 생기는 성능 이슈

1. 쿼리 성능 저하

UPDATE, DELETE가 많아지면 dead tuples 이 쌓인다.
PostgreSQL은 MVCC 방식이라, 삭제된 데이터도 실제로는 지워지지 않고 남아 있는데 이걸 지워주는 게 vacuum이다.

vacuum 은 백그라운드에서 autovacuum 이 실행되며, 쿼리로 명령어를 작성할 수 도 있다.

이것이 제대로 돌지 않으면 테이블이 점점 무거워진다.

 

이 과정으로 전체 테이블 스캔 비용 증가, 인덱스가 비효율적으로 커진다.

2. 인덱스 비대화

인덱스도 dead tuple을 포함한 상태가 계속 유지된다. 
Auto vacuum은 인덱스를 정리하지 않기 때문에 REINDEX 가 필요하다. 
인덱스가 커지면 쿼리 플래너가 잘못된 판단을 하기도하며 아주 가끔 REINDEX을 할 필요가 있다. 

 

REINDEX 를 진행할 경우 테이블에 락이 걸려 운영중인 서비스에 문제가 발생한다. 

3. 트랜잭션 ID wraparound 위험

PostgreSQL 은 트랜잭션 ID를 32bit로 관리하며 일정 수준을 지나면 기존 데이터가 무효화될 수 있다. 
Auto vacuum은 이를 방지하기 위해 freeze 작업을 수행하기도 한다.
만약 이 작업도 안 되면 PostgreSQL는 전체 읽기/쓰기를 중단시키며 강제로 vacuum을 시도하기도 한다.

이때 호러물마냥 메시지 나온다. 

4. 디스크 계속 증가

Auto vacuum이 안 돌면 dead tuple 이 지워지지 않기 때문에 디스크 사용량이 증가한다. 
AWS 의 Aurora를 사용할 경우 디스크가 자동 확장되므로 불필요한 요금을 내야할 수 도 있다. 

Auto vacuum 대응 

죽은 튜플을 보는 방법

SELECT relname, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 10;

죽은 튜플 수동 정리 방법

- 죽은 튜플을 정리하지만 디스크 공간은 줄어들지 않음 (reuse만 가능)

VACUUM tablename;

 

- ANALYZE 같이 정리하길 원할 경우

VACUUM ANALYZE tablename;

 

- 테이블을 깔끔하게 정리해서 디스크 공간을 회수. (단점: 테이블 락 걸림, 서비스 중에는 서비스 중단하고 하던가 해야함)

VACUUM FULL tablename;

Autovacuum 환경 설정 수정 방법

파라미터설명예시 값 (postgresql.conf)

autovacuum Autovacuum 기능 활성화 여부 on (기본값)
autovacuum_naptime autovacuum이 실행되는 최소 대기 시간 (초) 1min
autovacuum_vacuum_scale_factor 테이블에서 일정 비율 이상 데이터가 변경되면 vacuum 실행 0.2
autovacuum_vacuum_threshold autovacuum이 작동하기 위한 최소 튜플 변경 수 50
autovacuum_analyze_scale_factor 통계를 갱신하기 위한 변경 비율 0.1
autovacuum_freeze_max_age 트랜잭션 ID가 freeze를 해야 할 최대 나이 (트랜잭션 wraparound 방지) 200000000
log_autovacuum_min_duration autovacuum 작업 로그를 기록할 최소 실행 시간 0 (모든 실행 기록)