본문 바로가기
데이터베이스 & ORM

VACUUM ANALYZE

by DoRightting 2024. 11. 11.

VACUUM ANALYZE 구현 예제

1.1 Vector 데이터베이스 관리

@Component
@RequiredArgsConstructor
public class CustomVectorRepository {
    private final JdbcTemplate jdbcTemplate;

    @Scheduled(cron = "0 0 2 * * *")  // 매일 새벽 2시
    public void maintainVectorIndex() {
        try {
            // VACUUM ANALYZE 실행
            jdbcTemplate.execute("VACUUM ANALYZE prompts");
            log.info("Successfully completed VACUUM ANALYZE on prompts table");
        } catch (Exception e) {
            log.error("Failed to perform VACUUM ANALYZE: {}", e.getMessage());
        }
    }
}

1.2 초기 설정

-- init.sql에서 구현된 설정
-- Vector 인덱스 생성 전 VACUUM ANALYZE 수행
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE prompts (
    -- 테이블 정의
);

VACUUM ANALYZE prompts;

CREATE INDEX prompt_vector_idx ON prompts
    USING ivfflat (embedding_vector vector_l2_ops)
WITH (lists = 100);

1.3 성능 모니터링 구현

@Service
@Slf4j
public class DatabaseMaintenanceService {
    private final JdbcTemplate jdbcTemplate;

    public void checkTableStatistics() {
        String sql = """
            SELECT schemaname, tablename, last_vacuum, last_analyze,
                   n_dead_tup, n_live_tup, n_mod_since_analyze
            FROM pg_stat_user_tables
            WHERE tablename = 'prompts'
            """;

        jdbcTemplate.query(sql, rs -> {
            log.info("Dead tuples: {}, Live tuples: {}, Modified since analyze: {}",
                rs.getInt("n_dead_tup"),
                rs.getInt("n_live_tup"),
                rs.getInt("n_mod_since_analyze")
            );
        });
    }
}

VACUUM ANALYZE가 필요한 이유

  1. 데이터 갱신 특성
    • 벡터 데이터 빈번한 업데이트
    • Dead tuple 정리 필요
  2. @Entity public class Prompt { // 벡터 데이터 자주 업데이트 @Column(columnDefinition = "vector(1536)") private double[] embeddingVector; }
  3. 인덱스 성능
    • 통계 정보 최신화
    • 쿼리 플래너 최적화
  4. -- 벡터 인덱스 성능 최적화 CREATE INDEX prompt_vector_idx ON prompts USING ivfflat (embedding_vector vector_l2_ops);

VACUUM ANALYZE 스케줄링 구현

  1. 실행 시점
    • 시스템 부하가 적은 시간대 선택
    • 데이터 변경량 고려
  2. @Scheduled(cron = "0 0 2 * * *") // 매일 새벽 2시 public void maintainVectorIndex() { jdbcTemplate.execute("VACUUM ANALYZE prompts"); }
  3. 모니터링 기반
    • 테이블 상태 모니터링
    • 동적 실행 결정
  4. public void checkMaintenanceNeeded() { // Dead tuple 비율 체크 String sql = "SELECT n_dead_tup, n_live_tup FROM pg_stat_user_tables"; // 필요시 VACUUM ANALYZE 실행 }

VACUUM ANALYZE 실행 시 주의사항

  1. 리소스 관리
    • 적절한 메모리 할당
    • 시스템 부하 고려
  2. -- 작업 메모리 설정 SET maintenance_work_mem = '1GB'; -- 자동 vacuum 설정 ALTER TABLE prompts SET ( autovacuum_vacuum_threshold = 1000, autovacuum_analyze_threshold = 1000 );
  3. 트랜잭션 관리
    • 실행 중 트랜잭션 고려
    • 락 경합 방지
  4. @Transactional(readOnly = true) public void safeVacuumAnalyze() { // 활성 트랜잭션 확인 후 실행 jdbcTemplate.execute("VACUUM ANALYZE prompts"); }

VACUUM ANALYZE의 효과 모니터링

  1. 성능 지표 수집
    • 테이블 통계 추적
    • 쿼리 성능 모니터링
  2. public void collectVacuumMetrics() { String sql = """ SELECT last_vacuum, last_analyze, n_dead_tup, n_live_tup, n_mod_since_analyze FROM pg_stat_user_tables WHERE tablename = 'prompts' """; // 메트릭 수집 및 로깅 }
  3. 로그 분석
    • 공간 회수량 측정
    • 실행 시간 분석
  4. log.info("VACUUM ANALYZE completed. Before/After sizes: {}/{} MB", beforeSize, afterSize);

VACUUM ANALYZE와 자동 VACUUM의 차이 관리

  1. 자동 VACUUM 설정
    • 기본 자동 VACUUM 활성화
    • 테이블별 임계값 조정
  2. -- 테이블별 자동 VACUUM 설정 ALTER TABLE prompts SET ( autovacuum_vacuum_scale_factor = 0.1, autovacuum_analyze_scale_factor = 0.05 );
  3. 수동 VACUUM ANALYZE
    • 정기적인 전체 유지보수
    • 특수 상황 대응
  4. @Scheduled(cron = "0 0 2 * * *") public void performFullMaintenance() { // 전체 VACUUM ANALYZE 수행 jdbcTemplate.execute("VACUUM ANALYZE prompts"); }

대용량 데이터에서의 VACUUM ANALYZE 전략

  1. 단계적 실행
    • 파티션별 처리
    • 부하 분산
  2. public void performProgressiveVacuum() { // 파티션별 순차적 실행 for (String partition : getTablePartitions()) { jdbcTemplate.execute( "VACUUM ANALYZE prompts_" + partition); } }
  3. 실행 최적화
    • 리소스 최적화
    • 병렬 처리 활용
  4. -- 병렬 처리 설정 SET max_parallel_maintenance_workers = 4; -- 작업 메모리 설정 SET maintenance_work_mem = '2GB';

'데이터베이스 & ORM' 카테고리의 다른 글

REPEATABLE READ  (0) 2024.11.15
Row-Level Lock  (1) 2024.11.12
PostgreSQL GIN  (5) 2024.11.10
QueryDSL 개요  (0) 2024.07.25
JPA에서의 엔티티 참조 조회 방식  (1) 2024.07.24