**IVFFlat(Inverted File Flat)**은 ANN(Approximate Nearest Neighbor) 검색을 위한 인덱스 방식
1. 프로젝트 내 IVFFlat 구현
1.1 인덱스 생성
-- init.sql에서 구현된 IVFFlat 인덱스 설정
CREATE INDEX prompt_vector_idx ON prompts
USING ivfflat (embedding_vector vector_l2_ops)
WITH (lists = 100);
1.2 CustomVectorRepository에서의 활용
@Repository
@RequiredArgsConstructor
public class CustomVectorRepository {
public List<Prompt> findSimilarPrompts(double[] vector, double threshold, int limit) {
String sql = """
SELECT * FROM prompts
WHERE embedding_vector IS NOT NULL
AND 1 - (embedding_vector <=> cast(? as vector(1536))) > ?
ORDER BY 1 - (embedding_vector <=> cast(? as vector(1536))) DESC
LIMIT ?
""";
String vectorStr = vectorToString(vector);
return jdbcTemplate.query(sql, promptRowMapper,
vectorStr, threshold, vectorStr, limit);
}
private void createIndexesIfNotExist() {
if (!indexExists("prompt_vector_idx")) {
try {
jdbcTemplate.execute("""
CREATE INDEX prompt_vector_idx
ON prompts USING ivfflat (embedding_vector vector_l2_ops)
WITH (lists = 100)
""");
log.info("Created vector similarity index");
} catch (Exception e) {
log.warn("Failed to create vector index - will be created when data is available", e);
}
}
}
}
1.3 벡터 유사도 검색 구현
@Service
public class PromptService {
public List<PromptResponse> findSimilarPrompts(String promptText) {
double[] embedding = openAiApi.embeddings(promptText);
List<Prompt> similarPrompts = customVectorRepository
.findSimilarPrompts(embedding, 0.8, 10);
return similarPrompts.stream()
.map(this::buildPromptResponse)
.collect(Collectors.toList());
}
}
2. 프로젝트에서 IVFFlat 인덱스를 선택한 이유
- 성능과 정확성의 균형
- 근사 최근접 이웃(ANN) 검색 지원
- 적절한 검색 속도와 정확도 제공
- CREATE INDEX prompt_vector_idx ON prompts USING ivfflat (embedding_vector vector_l2_ops) WITH (lists = 100);
- 프로젝트 특성에 적합
- 1536차원의 OpenAI 임베딩 벡터 처리
- 실시간 유사도 검색 요구사항 충족
- 중간 규모의 데이터셋에 적합
IVFFlat의 lists 파라미터
- 데이터 특성 분석
- 전체 데이터 크기 고려
- 검색 성능 요구사항 반영
- -- 데이터 규모에 따른 lists 값 설정 WITH (lists = 100) -- 약 10,000개의 벡터 데이터 기준
IVFFlat 인덱스의 성능 모니터링
- 쿼리 성능 추적
- 검색 시간 모니터링
- 성능 병목 식별
- public List<Prompt> findSimilarPrompts(double[] vector, double threshold, int limit) { long startTime = System.currentTimeMillis(); List<Prompt> results = // 검색 로직 long duration = System.currentTimeMillis() - startTime; log.debug("Vector search completed in {}ms", duration); return results; }
- 인덱스 상태 확인
- 인덱스 크기 모니터링
- 인덱스 효율성 검사
- -- 인덱스 상태 확인 쿼리 SELECT * FROM pg_indexes WHERE indexname = 'prompt_vector_idx';
벡터 검색의 정확도와 성능 사이의 균형 전략
- 검색 최적화
- 캐싱 전략 적용
- 반복 검색 최적화
- // 검색 결과 캐싱 구현 @Cacheable(value = "similarPrompts", key = "#vector") public List<Prompt> findSimilarPromptsWithCache(double[] vector) { return findSimilarPrompts(vector, 0.8, 10); }
IVFFlat 인덱스 생성 시 고려 사항
- 초기 설정
- 벡터 확장 활성화 확인
- 적절한 테이블 구조 설정
- private void initializeDatabase() { enableVectorExtension(); createTablesIfNotExist(); createIndexesIfNotExist(); }
- 리소스 관리
- 메모리 사용량 관리
- 병렬 처리 최적화
- -- 인덱스 생성 시 리소스 설정 SET maintenance_work_mem = '1GB'; SET max_parallel_maintenance_workers = 4;
IVFFlat 인덱스의 유지보수
- 정기적인 관리
- 정기적인 VACUUM ANALYZE
- 인덱스 효율성 유지
- @Scheduled(cron = "0 0 2 * * *") // 매일 새벽 2시 public void maintainVectorIndex() { jdbcTemplate.execute("VACUUM ANALYZE prompts"); }
'기술 트렌드 & 새로운 학습' 카테고리의 다른 글
코사인 유사도 검색 (1) | 2024.11.18 |
---|---|
CompletableFuture (0) | 2024.11.14 |
Rate Limiting (0) | 2024.11.13 |