VACUUM 간단 정리

2025. 2. 16. 01:13Database/PostgreSQL

1. 개요

  • PostgreSQL은 MVCC(Multi-Version Concurrency Control)을 사용하여 데이터를 관리
  • MVCC는 트랜잭션 격리성과 동시성을 보장하는 대신, 불필요한 데이터(Dead Tuples)가 쌓이는 문제 유발
  • 이를 해결하기 위해 VACUUM을 실행해야함

2. VACUUM이 필요한 이유

1. MVCC로 인해 삭제된 데이터(Dead Tuples)가 계속 남아 있음

  • PostgreSQL은 데이터를 즉시 삭제하지 않고, 기존 데이터를 ‘Dead Tuple’로 유지
  • 이는 트랜잭션 격리성과 동시성을 보장하기 위한 메커니즘

예시

DELETE FROM users WHERE id = 1;
  • 이때 id = 1 데이터를 즉시 삭제하는 것이 아니라, 삭제되었다고 표시된 Dead Tuple로 남아 있음
  • 트랜잭션이 롤백될 경우, 다시 복구될 수 있도록 보장하기 때문
  • 하지만 이 Dead Tuple이 쌓이면?
    • SELECT 성능 저하 → 불필요한 데이터까지 스캔해야 하므로 속도가 느려짐
    • INSERT, UPDATE 성능 저하 → 새로운 데이터를 저장할 공간이 부족해지고, 디스크 사용량 증가

2. Dead Tuples가 인덱스에도 영향을 미침

  • 테이블에 DELETE/UPDATE가 반복될 경우, 인덱스 내에서도 Dead Tuples가 포함
  • 결과적으로 인덱스 크기가 불필요하게 증가하고, Index Scan 성능이 저하될 수 있음

예시

CREATE INDEX idx_users_email ON users(email);
SELECT * FROM users WHERE email = 'test@example.com';
  • Dead Tuples가 많으면 불필요한 데이터까지 검색해야 하므로 속도가 느려짐

3. 디스크 공간 증가

  • PostgreSQL은 UPDATE, DELETE 시 기존 데이터를 삭제하지 않고 새로운 데이터 버전을 생성
  • VACUUM을 실행하지 않으면 불필요한 공간이 계속 증가하여 디스크를 낭비

예시

UPDATE users SET email = 'new@example.com' WHERE id = 1;
  • email 값이 변경될 때, PostgreSQL은 기존 데이터를 삭제하지 않고 새로운 버전의 데이터를 생성
  • 결과적으로 디스크 공간이 불필요하게 사용됨

3. VACUUM의 역할

  • VACUUM은 Dead Tuples를 정리하고, PostgreSQL 성능을 유지하는 중요한 작업

기본적인 VACUUM

VACUUM users;
  • Dead Tuples를 정리하지만, 디스크 공간은 회수하지 않음
  • Autovacuum이 활성화되어 있으면 자동 실행됨

VACUUM FULL

VACUUM FULL users;
  • Dead Tuples 정리 + 디스크 공간까지 반환
  • 단점: 테이블이 완전히 잠김 (LOCK 발생) → 실행 중에는 해당 테이블에 대한 읽기/쓰기 작업 불가능
  • 디스크 공간이 부족할 경우 필수 실행

ANALYZE (통계 업데이트)

VACUUM ANALYZE users;
  • VACUUM과 함께 실행하면 쿼리 플래너가 최신 통계를 반영할 수 있도록 도움
  • SELECT 쿼리 최적화에 필수적
  • 인덱스 활용도를 높일 수 있음

4. VACUUM 실행 효과

항목 VACUUM 전 VACUUM 후 설명
SELECT 속도 느림 빨라짐 Dead Tuples 제거로 검색 범위 축소
INSERT / UPDATE 성능 저하됨 최적화됨 사용되지 않는 공간을 정리
디스크 사용량 증가 감소 불필요한 데이터 정리
인덱스 크기 커짐 줄어듦 인덱스 내 불필요한 Dead Tuples 제거

5. PostgreSQL의 Autovacuum 동작 방식

  • Autovacuum : 자동으로 VACUUM을 실행하는 프로세스
  • 하지만 Autovacuum이 즉시 실행되지 않을 수도 있기 때문에, 특정 상황에서는 수동 실행 필요

Autovacuum 관련 설정 (postgresql.conf)

autovacuum = on
autovacuum_naptime = 30s   # 기본값: 1분 (너무 긴 경우 줄여줌)
autovacuum_vacuum_cost_limit = 2000  # 기본값: 200 (더 많은 테이블을 처리 가능)

Autovacuum이 작동하는 원리

  1. DELETE, UPDATE 등의 작업이 일정량 발생하면 Autovacuum 트리거됨
  2. VACUUM을 실행하여 Dead Tuples 제거
  3. 필요하면 ANALYZE도 자동 실행하여 통계 업데이트

Autovacuum이 작동 중인지 확인

SELECT * FROM pg_stat_activity WHERE query LIKE 'autovacuum%';

6. 언제 VACUUM을 실행해야 하는가?

  • 대량의 DELETE 또는 UPDATE를 실행한 경우
  • 디스크 사용량이 갑자기 증가한 경우
  • SELECT 쿼리 성능이 느려진 경우
  • Autovacuum이 너무 늦게 실행되는 경우

VACUUM을 직접 실행해야 할 때

VACUUM ANALYZE;
VACUUM FULL;
  • (주의) VACUUM FULL은 테이블을 잠그기 때문에 트래픽이 적은 시간대에 실행하는 것이 좋음

결론

  • PostgreSQL의 MVCC 특성상, Dead Tuples가 지속적으로 발생하므로 정기적인 VACUUM 실행이 필수
  • Autovacuum이 작동하지 않는 경우, 성능 저하가 발생할 수 있으므로 수동으로 VACUUM 실행이 필요
  • ANALYZE와 함께 실행하면 쿼리 플래너가 최신 정보를 반영하여 성능 최적화 가능
  • 디스크 사용량이 많아지면 VACUUM FULL을 고려해야 하지만, 실행 중에는 테이블이 잠기므로 주의가 필요