데이터베이스 & 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가 필요한 이유
- 데이터 갱신 특성
- 벡터 데이터 빈번한 업데이트
- Dead tuple 정리 필요
- @Entity public class Prompt { // 벡터 데이터 자주 업데이트 @Column(columnDefinition = "vector(1536)") private double[] embeddingVector; }
- 인덱스 성능
- -- 벡터 인덱스 성능 최적화 CREATE INDEX prompt_vector_idx ON prompts USING ivfflat (embedding_vector vector_l2_ops);
VACUUM ANALYZE 스케줄링 구현
- 실행 시점
- 시스템 부하가 적은 시간대 선택
- 데이터 변경량 고려
- @Scheduled(cron = "0 0 2 * * *") // 매일 새벽 2시 public void maintainVectorIndex() { jdbcTemplate.execute("VACUUM ANALYZE prompts"); }
- 모니터링 기반
- public void checkMaintenanceNeeded() { // Dead tuple 비율 체크 String sql = "SELECT n_dead_tup, n_live_tup FROM pg_stat_user_tables"; // 필요시 VACUUM ANALYZE 실행 }
VACUUM ANALYZE 실행 시 주의사항
- 리소스 관리
- -- 작업 메모리 설정 SET maintenance_work_mem = '1GB'; -- 자동 vacuum 설정 ALTER TABLE prompts SET ( autovacuum_vacuum_threshold = 1000, autovacuum_analyze_threshold = 1000 );
- 트랜잭션 관리
- @Transactional(readOnly = true) public void safeVacuumAnalyze() { // 활성 트랜잭션 확인 후 실행 jdbcTemplate.execute("VACUUM ANALYZE prompts"); }
VACUUM ANALYZE의 효과 모니터링
- 성능 지표 수집
- 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' """; // 메트릭 수집 및 로깅 }
- 로그 분석
- log.info("VACUUM ANALYZE completed. Before/After sizes: {}/{} MB", beforeSize, afterSize);
VACUUM ANALYZE와 자동 VACUUM의 차이 관리
- 자동 VACUUM 설정
- 기본 자동 VACUUM 활성화
- 테이블별 임계값 조정
- -- 테이블별 자동 VACUUM 설정 ALTER TABLE prompts SET ( autovacuum_vacuum_scale_factor = 0.1, autovacuum_analyze_scale_factor = 0.05 );
- 수동 VACUUM ANALYZE
- @Scheduled(cron = "0 0 2 * * *") public void performFullMaintenance() { // 전체 VACUUM ANALYZE 수행 jdbcTemplate.execute("VACUUM ANALYZE prompts"); }
대용량 데이터에서의 VACUUM ANALYZE 전략
- 단계적 실행
- public void performProgressiveVacuum() { // 파티션별 순차적 실행 for (String partition : getTablePartitions()) { jdbcTemplate.execute( "VACUUM ANALYZE prompts_" + partition); } }
- 실행 최적화
- -- 병렬 처리 설정 SET max_parallel_maintenance_workers = 4; -- 작업 메모리 설정 SET maintenance_work_mem = '2GB';