13. [최적화10] PostgreSQL에서 VACUUM이 필요한 이유 및 역할

2025. 2. 16. 01:37Test/Artillery

VACUUM 설명

1. VACUUM의 필요성

PostgreSQL에서는 DELETE, UPDATE 후 데이터가 즉시 삭제되지 않음.

이로 인해 Dead Tuples가 누적되면서 쿼리 성능이 저하됩니다.

이를 해결하기 위해 정기적인 VACUUM 및 ANALYZE가 필요합니다.

VACUUM의 역할

  • Dead Tuples 정리 → 디스크 공간 절약
  • 쿼리 실행 속도 향상 → 불필요한 데이터를 읽지 않도록 최적화
  • Autovacuum보다 적극적인 성능 최적화 가능
VACUUM ANALYZE "user";
  • 인덱스 활용 최적화 → SET enable_seqscan = OFF; 설정 후 실행
EXPLAIN ANALYZE SELECT * FROM "user" WHERE email = 'a@a.com';
  • Index Scan 적용 확인

2. VACUUM 적용 후 성능 비교

항목 VACUUM 전 (인덱스 적용 후) VACUUM 후 변화

WebSocket 에러 19 26 🔺 증가 (+7)
완료된 사용자 수 858 849 🔽 감소 (-9)
평균 응답 시간(ms) 0.5 0.3 🔽 감소 (-0.2)
최대 응답 시간(ms) 27.3 2.7 🔽 감소 (-24.6)
P95 응답 시간(ms) 1.0 0.7 🔽 감소 (-0.3)
P99 응답 시간(ms) 2.7 1.3 🔽 감소 (-1.4)
테스트 총 실행 시간 3분 9초 3분 11초 🔼 증가 (+2초)

결론

  • VACUUM을 실행하면 Dead Tuples가 정리되어 SELECT 쿼리의 성능이 안정화됨
  • 테스트 결과 WebSocket 요청 에러는 약간 증가했지만, 응답 시간 및 최대 응답 시간은 큰 폭으로 감소
    • WebSocket 에러가 14 → 26으로 증가, 실패한 사용자 수도 소폭 증가함
    • 평균 응답 시간 0.5ms → 0.3ms로 감소
    • 최대 응답 시간 27.3ms → 2.7ms로 크게 감소
    • P95, P99 응답 시간도 크게 단축됨
    • 최적화 과정에서 CPU 사용량 및 디스크 I/O 증가로 인한 일시적인 부하 증가 때문일 가능성이 큼
  • ACUUM 실행 후 최대 응답 시간이 크게 감소하여 평균 응답 속도가 빨라졌음
  • PostgreSQL 운영에서는 정기적인 VACUUM과 인덱스 최적화가 필수적
  • 최적의 성능을 유지하려면, 아래와 같은 유지보수 전략이 필요
    • 주기적인 VACUUM ANALYZE 실행
    • Autovacuum 설정 조정
    • 쿼리 성능 분석 후 필요한 경우 인덱스 추가
    • EXPLAIN ANALYZE로 최적화된 실행 계획 확인

3. PostgreSQL 최적화 후 실패율 증가 원인 분석

1. 최적화 후 실패율이 증가한 이유

PostgreSQL 인덱싱과 VACUUM 최적화를 통해 쿼리 성능이 개선되었음에도 불구하고, WebSocket 요청의 실패율(WebSocket errors, failed users)이 증가


2. 성능 최적화 이후 실패율 증가 원인 분석

요소 설명 실패율 증가 기여도

CPU 사용량 증가 VACUUM과 ANALYZE는 CPU 집약적인 작업이므로, CPU 사용량이 순간적으로 증가하면서 WebSocket 요청을 처리하는 서버 응답 속도에 영향을 줄 가능성이 있음 🔼 높음
동시 접속 처리 한계 VACUUM 수행 중 PostgreSQL이 많은 리소스를 사용하여, 동시에 발생하는 다수의 WebSocket 요청을 빠르게 처리하지 못했을 가능성 🔼 중간
PgBouncer의 영향 최적화 과정에서 PgBouncer를 도입했으며, 이로 인해 커넥션 풀링 전략이 바뀌면서 트랜잭션 지연이 발생할 가능성이 있음 🔼 낮음
디스크 I/O 증가 VACUUM은 디스크 정리를 수행하는 작업이므로, SSD 성능이 제한적인 환경에서 응답 지연이 발생했을 가능성 🔼 중간
Autovacuum과 충돌 수동 VACUUM 실행과 Autovacuum이 동시에 실행되면서, 예상보다 더 많은 리소스를 사용하게 되었을 가능성 🔼 높음

4. 실패율 증가 원인에 대한 상세 분석

1) CPU 사용량 증가로 인한 서버 부하

  • VACUUM ANALYZE 실행 시 PostgreSQL이 기존 데이터 정리를 수행하면서 CPU를 점유
  • 서버 CPU가 100% 가까이 사용되면 WebSocket 요청을 처리하는 애플리케이션 응답 속도가 느려질 가능성이 높음
  • 특히 t2.micro (1 vCPU, 1GB RAM, 8GB SSD)와 같은 리소스 제한이 있는 환경에서는 CPU 스파이크가 WebSocket 에러 증가로 이어질 수 있음

해결책

  • VACUUM ANALYZE는 트래픽이 적은 시간대에 실행하도록 스케줄링 (cronjob 설정)
  • pg_stat_progress_vacuum을 활용하여 진행률을 모니터링하고 적절한 시점에 실행
SELECT * FROM pg_stat_progress_vacuum;

2) 동시 접속 증가로 인한 커넥션 대기 시간 증가

  • 최적화 후 WebSocket 요청이 더 빠르게 처리되면서, 더 많은 동시 요청이 발생할 가능성이 있음
  • PgBouncer가 동시 커넥션을 제한하여 일부 요청이 대기 상태로 전환되었을 가능성

해결책

  • pgbouncer.ini 설정에서 max_client_conn 및 default_pool_size 값을 조정하여 병목 해결
max_client_conn = 150
default_pool_size = 20

3) VACUUM과 Autovacuum의 충돌

  • Autovacuum이 자동으로 실행 중일 때 수동 VACUUM이 실행되면, PostgreSQL이 예상보다 더 많은 리소스를 소모할 수 있음
  • pg_stat_activity에서 autovacuum이 실행 중인지 확인 가능
SELECT * FROM pg_stat_activity WHERE query LIKE '%autovacuum%';

해결책

  • Autovacuum 설정을 조정하여 과도한 리소스 사용을 방지
  • autovacuum_vacuum_cost_limit 및 autovacuum_vacuum_scale_factor 값을 줄여 VACUUM을더 자주 실행하면서도 부하를 줄이는 전략 사용
ALTER SYSTEM SET autovacuum_vacuum_cost_limit = 1000;
ALTER SYSTEM SET autovacuum_vacuum_scale_factor = 0.05;

5. 결론 및 최적화 전략

  1. VACUUM 및 ANALYZE 실행 후 성능 개선을 확인했지만, CPU 사용량 증가로 인해 WebSocket 요청 실패율도 증가
  2. Autovacuum과 수동 VACUUM이 충돌하여 리소스를 과소비했을 가능성이 크므로, Autovacuum 설정 최적화 필요
  3. PostgreSQL 서버 리소스가 부족한 환경(t2.micro)에서는 CPU 및 메모리 사용량을 지속적으로 모니터링하는 것이 중요