임의 근사 이웃 (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;
실무 적용을 위한 튜닝 가이드라인
- 초기 설정은 기본값 (
m=16,ef=128) 으로 시작하여 현재 성능을 측정하세요. - 만약 Recall@10 이 0.95 미만을 기록한다면,
ef값을 256 또는 512 로 단계별로 증가시키세요. - 높은
ef를 적용해도 목표치를 달성하지 못할 경우, 인덱스를 재건하면서m값을 24 이상으로 늘려보십시오. - 최종 목표는 요구되는 정확도 (예: 98%) 를 보장하면서 대기 시간이 최소화되는 지점을 찾는 것입니다.
일반적인 추천 시스템의 경우 높은 처리량이 중요하므로 ef 값을 낮게 유지하되, RAG(Retrieval-Augmented Generation) 나 지식 베이스 검색과 같은 경우 정밀도가 핵심이므로 충분히 큰 ef 값을 권장합니다.