본문 바로가기
기술 트렌드 & 새로운 학습

IVFFlat

by DoRightting 2024. 11. 17.

**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 인덱스를 선택한 이유

  1. 성능과 정확성의 균형
    • 근사 최근접 이웃(ANN) 검색 지원
    • 적절한 검색 속도와 정확도 제공
  2. CREATE INDEX prompt_vector_idx ON prompts USING ivfflat (embedding_vector vector_l2_ops) WITH (lists = 100);
  3. 프로젝트 특성에 적합
    • 1536차원의 OpenAI 임베딩 벡터 처리
    • 실시간 유사도 검색 요구사항 충족
    • 중간 규모의 데이터셋에 적합

IVFFlat의 lists 파라미터

  1. 데이터 특성 분석
    • 전체 데이터 크기 고려
    • 검색 성능 요구사항 반영
  2. -- 데이터 규모에 따른 lists 값 설정 WITH (lists = 100) -- 약 10,000개의 벡터 데이터 기준

IVFFlat 인덱스의 성능 모니터링

  1. 쿼리 성능 추적
    • 검색 시간 모니터링
    • 성능 병목 식별
  2. 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; }
  3. 인덱스 상태 확인
    • 인덱스 크기 모니터링
    • 인덱스 효율성 검사
  4. -- 인덱스 상태 확인 쿼리 SELECT * FROM pg_indexes WHERE indexname = 'prompt_vector_idx';

벡터 검색의 정확도와 성능 사이의 균형 전략

  1. 검색 최적화
    • 캐싱 전략 적용
    • 반복 검색 최적화
  2. // 검색 결과 캐싱 구현 @Cacheable(value = "similarPrompts", key = "#vector") public List<Prompt> findSimilarPromptsWithCache(double[] vector) { return findSimilarPrompts(vector, 0.8, 10); }

IVFFlat 인덱스 생성 시 고려 사항

  1. 초기 설정
    • 벡터 확장 활성화 확인
    • 적절한 테이블 구조 설정
  2. private void initializeDatabase() { enableVectorExtension(); createTablesIfNotExist(); createIndexesIfNotExist(); }
  3. 리소스 관리
    • 메모리 사용량 관리
    • 병렬 처리 최적화
  4. -- 인덱스 생성 시 리소스 설정 SET maintenance_work_mem = '1GB'; SET max_parallel_maintenance_workers = 4;

IVFFlat 인덱스의 유지보수

  1. 정기적인 관리
    • 정기적인 VACUUM ANALYZE
    • 인덱스 효율성 유지
  2. @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