HNSW 인덱스 파라미터가 Recall@10 에 미치는 영향 분석 및 튜닝 방법

임의 근사 이웃 (Approximate Nearest Neighbor, ANN) 알고리즘의 검색 품질을 정량적으로 평가하는 데에는 Recall@10 지표가 핵심적으로 사용됩니다. 이는 특정 쿼리 벡터에 대해 반환된 상위 k 개 결과 중, 실제 정확한 상위 k 개의 데이터가 얼마나 포함되어 있는지를 나타내는 비율입니다.

Recall@10 측정 프로세스

기존의 정밀 검색 (Exact Search) 결과를 기준으로 근사 검색 (ANN Search) 의 결과집합 겹침 정도를 계산하는 방식이 일반적으로 쓰입니다. 수식적으로는 다음과 같이 표현할 수 있습니다:

Recall@k = |AnnResult @k ∩ GroundTruth @k| / k

SonnetDB 환경에서는 내부에서 제공하는 지능형 인덱싱 기능을 활용하면, 동일한 쿼리에 대해 서로 다른 설정으로 검색을 수행하고 그 결과를 즉시 비교 가능합니다. 아래 코드는 각 파라미터 조합에서의 결과 집합을 구하고 일치하는 항목수를 산출하는 로직의 한 예시입니다.

// 정밀 검색을 통해 진정한 정답 집합 획득
// resultLimit 가 전체 데이터 수보다 작거나 같을 경우 정렬 엔진 사용
var trueNeighbors = db.GetExactMatches(queryVec, payload, 10);

// HNSW 그래프 기반으로 근사 검색 수행
var approximateNeighbors = db.GetApproxMatches(queryVec, payload, 10);

// 두 집합 간의 교집합 크기 계산
int correctCount = 0;
foreach(var item in approximateNeighbors) 
{
    if(trueNeighbors.Exists(t => t.VectorId == item.VectorId)) {
        correctCount++;
    }
}

// 최종 Recall 값 도출
double finalRecall = (double)correctCount / trueNeighbors.Count;

검색 성능에 영향을 주는 주요 하이퍼파라미터

1. efSearch 설정의 파급 효과

검색 단계에서 확장성 (Expansion Scope) 을 제어하는 efSearch 는 가장 민감한 조절 장치입니다. 시스템 내에서는 이를 resultLimit 와 비교하여 최소한의 후보 군을 결정하도록 설계되어 있습니다.

int adjustedEf = Math.Min(totalVectors, Math.Max(targetLimit, baseEf));

실증된 바에 따르면, 약 50 만 건의 384 차원 벡터 데이터셋에서 효율적인 파라미터 조합을 찾았을 때 다음과 같은 트레이드오프 관계가 관찰되었습니다:

efSearch 값 Recall@10 평균 응답 지연
40 0.88 5ms
80 0.93 9ms
160 0.97 15ms
320 0.99 28ms

이처럼 검색 정확도를 높이기 위해서는 더 넓은 탐색 범위를 허용해야 하며, 이에 따라 처리 비용 역시 선형 또는 비선형적으로 증가하게 됩니다.

2. 링크 수 (m) 의 역할

그렇지 않아도 충분히 빠른 검색 속도를 달성하기 위해 그래프의 밀도를 조정하는 m 파라미터도 중요합니다. m 값을 키우면 노드 간 연결 수가 늘어나며 경로 탐색이 용이해집니다. 예를 들어 16 에서 32 로 설정을 변경할 때 Recall 이 대략 2% 포인트 상승했으나, 저장소 점유율은 두 배 가까이 늘어났습니다. 대부분의 경우 m=16 부근이 균형 잡힌 지점입니다.

3. 벡터 차원의 영향력

차원이 높아질수록 '차원의 저주' 현상으로 인해 거리 계산의 신뢰도가 하락합니다. 따라서 768 차원 이상일 때는 일반적인 384 차원 설정 대비 50~100% 정도 efSearch 값을 상향 조정하여 오차를 보정해야 합니다.

시스템적 벤치마킹 구현

수동 테스트보다는 데이터베이스 레이어에서 자동으로 파라미터별 성능을 회귀 테스트할 수 있는 스크립트를 작성하는 것이 좋습니다. 다음 SQL 구문은 다양한 쿼리에 대해 인덱스의 검색 안정성을 확인하는 샘플입니다.

-- 벤치마크 테이블 생성
CREATE TABLE hnsw_test (
    id SERIAL PRIMARY KEY,
    vector_col VECTOR(384),
    tag_val TEXT
);

-- 파라미터 테스트 수행 후 Recall@10 집계
SELECT 
    test_run_id,
    ROUND(AVG(case_when_top_10_hit_ratio), 2) as avg_recall,
    MAX(search_latency_ms) as max_latency
FROM (
    SELECT 
        q.query_id AS test_run_id,
        CASE WHEN rank <= 10 THEN 1 ELSE 0 END AS is_match,
        EXTRACT(EPOCH FROM search_time) * 1000 AS search_latency_ms
    FROM (
        SELECT query_id, knn_result(vector_col, [target_vector]) AS res
        FROM queries_table
    ) q, lateral unnest(res) WITH ORDINALITY AS r(res, rank)
) stats
GROUP BY test_run_id;

실무 적용을 위한 튜닝 가이드라인

  1. 초기 설정은 기본값 (m=16, ef=128) 으로 시작하여 현재 성능을 측정하세요.
  2. 만약 Recall@10 이 0.95 미만을 기록한다면, ef 값을 256 또는 512 로 단계별로 증가시키세요.
  3. 높은 ef 를 적용해도 목표치를 달성하지 못할 경우, 인덱스를 재건하면서 m 값을 24 이상으로 늘려보십시오.
  4. 최종 목표는 요구되는 정확도 (예: 98%) 를 보장하면서 대기 시간이 최소화되는 지점을 찾는 것입니다.

일반적인 추천 시스템의 경우 높은 처리량이 중요하므로 ef 값을 낮게 유지하되, RAG(Retrieval-Augmented Generation) 나 지식 베이스 검색과 같은 경우 정밀도가 핵심이므로 충분히 큰 ef 값을 권장합니다.

태그: HNSW Recall@10 VectorSearch DatabasePerformance KNN

8월 22일 20:08에 게시됨