two-thirteen
벡터 검색에 조건을 붙이면 결과가 모자라는 이유
벡터 검색에 조건을 붙이면 결과가 모자라는 이유
2026-11-09 Databases

벡터 검색에 조건을 붙이면 결과가 모자라는 이유

HorizonDB의 DiskANN 필터링 발표를 이해하려고 pgvector 문서로 정리한 메모입니다. HNSW와 IVFFlat의 차이, 근사 검색, 그리고 WHERE 조건을 붙이면 결과가 덜 나오는 이유와 해결책(ef_search, 반복 인덱스 스캔, 부분 인덱스)을 다룹니다.

HorizonDB 글에서 "DiskANN 고급 필터링이 질의 조건을 벡터 검색 안으로 밀어 넣는다"는 발표를 옮겼습니다. 그런데 필터가 왜 문제인지를 먼저 이해해야 이 발표의 의미가 보입니다. pgvector 문서가 이 문제를 가장 솔직하게 설명하고 있어서 정리해 둡니다.

정확 검색과 근사 검색

pgvector는 기본으로 정확 검색을 합니다. 모든 벡터와 거리를 계산하니 재현율이 완벽합니다. 대신 데이터가 많으면 느립니다.

근사 인덱스는 재현율을 조금 내주고 속도를 얻습니다. 문서는 근사 인덱스를 붙이면 같은 쿼리의 결과가 달라질 수 있다고 미리 경고합니다.

인덱스 방식 특징
HNSW 다층 그래프 속도·재현율 균형이 좋음, 만들기 느리고 메모리 많이 씀, 빈 테이블에도 생성 가능
IVFFlat 벡터를 목록으로 나누고 가까운 목록만 탐색 만들기 빠르고 메모리 적게 씀, 데이터를 넣은 뒤 만들어야 재현율이 좋음

조건을 붙이면 생기는 일

문제는 여기서 생깁니다. pgvector에서 근사 인덱스를 쓰면 필터링은 인덱스 스캔이 끝난 뒤 적용됩니다.

HNSW는 후보 목록 크기(hnsw.ef_search)만큼만 가져옵니다. 기본값은 40입니다. 문서의 예가 명확합니다. 조건이 전체 행의 10%에만 맞는다면, 후보 40개 중 조건을 통과하는 건 평균 4개뿐입니다.

"비슷한 상품 10개, 단 재고 있는 것만"을 물었는데 4개만 돌아오는 상황입니다. 에러도 없이 조용히 모자랍니다.

pgvector가 제시하는 해결책

  • ef_search 올리기: 후보를 더 많이 가져옵니다. 재현율은 오르고 속도는 떨어집니다.
  • 반복 인덱스 스캔: 결과가 모자라면 인덱스를 자동으로 더 훑습니다. SET hnsw.iterative_scan = strict_order;로 켭니다.
  • 부분 인덱스: 조건 값이 몇 개 안 되면 값마다 인덱스를 따로 만듭니다.
  • 파티셔닝: 조건 값이 많으면 테이블을 나눕니다.

발표가 다르게 들린다

이걸 알고 나니 HorizonDB 발표가 다르게 읽힙니다. "조건을 벡터 검색 안으로 밀어 넣는다"는 건, 먼저 찾고 나중에 거르는 대신 거르면서 찾는다는 뜻입니다. 결과가 모자라는 문제를 구조에서 풀겠다는 주장입니다.

실무에서 RAG에 권한 필터나 날짜 필터를 붙인다면, 쓰는 벡터 저장소가 어느 쪽 방식인지 먼저 확인해 볼 만합니다. 결과 개수를 로그로 남겨 두면 조용히 모자라는 문제를 일찍 잡을 수 있습니다.