Qdrant에서의 유사도 검색(Similarity Search)은 벡터 유사도 기반 검색의 핵심 기능이다.
신경망 기반 임베딩 모델이 입력 데이터를 벡터로 변환한 뒤, 해당 벡터 간의 유사도를 비교하여 가장 가까운 객체를 찾아낸다.
Qdrant는 이 과정을 고속으로 처리하기 위한 다양한 API와 최적화 기법을 제공한다.
유사도 검색의 개요
벡터 기반 유사도 검색은 k-최근접 이웃(k-NN) 방식에 기반하며, 실제 유사한 객체(텍스트, 이미지, 오디오 등)는 벡터 공간상에서도 서로 가까운 위치에 있게 된다. Qdrant는 이러한 유사도 기반 검색을 단일 API(Query API)로 통합하여 제공한다.
Query API
/points/query 엔드포인트는 Qdrant에서 다양한 검색 기능을 수행하는 핵심 인터페이스이다. 주요 지원 기능은 다음과 같다.
-
Nearest Neighbors Search: 일반적인 벡터 유사도 검색 (k-NN)
-
Search by ID: 기존에 저장된 포인트의 벡터를 기준으로 검색
-
Recommendations: 긍정/부정 예시를 활용한 추천
-
Discovery Search: 컨텍스트 기반 1회성 학습 검색
-
Scroll: 모든 포인트를 조건 기반으로 페이징 조회
-
Grouping: 특정 필드를 기준으로 결과를 그룹화
-
Hybrid Search: 다양한 검색 조건을 결합한 하이브리드 검색
-
Random Sampling: 임의 샘플링
-
Multi-Stage Search: 대규모 임베딩을 위한 검색 최적화
기본 유사도 검색
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.7]
}
ID 기반 검색
POST /collections/{collection_name}/points/query
{
"query": "43cf51e2-8777-4f52-bc74-c2cbde0c8b04"
}
해당 ID에 저장된 벡터를 기준으로 유사도 검색을 수행한다.
using 파라미터를 지정하면 Named Vector 사용이 가능하다.
검색 메트릭(Metric)
Qdrant는 다음과 같은 유사도 메트릭을 지원한다.
-
Dot Product
-
Cosine Similarity (기본값)
-
Euclidean Distance
-
Manhattan Distance (v1.7부터 지원)
Cosine 메트릭은 벡터를 정규화한 후 Dot Product 방식으로 계산되며, 이는 SIMD 최적화를 통해 빠르게 수행된다.
필터링을 포함한 검색 예시
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.79],
"filter": {
"must": [
{ "key": "city", "match": { "value": "London" } }
]
},
"params": {
"hnsw_ef": 128,
"exact": false
},
"limit": 3
}
-
limit: 결과 수 제한 -
hnsw_ef: HNSW 탐색 깊이 -
exact: true로 설정 시 전체 스캔을 수행하여 정확한 결과를 반환
Named Vector 검색
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.7],
"using": "image",
"limit": 3
}
여러 개의 Named Vector가 존재할 경우 using으로 명시적으로 지정해야 한다.
Sparse Vector 검색
POST /collections/{collection_name}/points/query
{
"query": {
"indices": [1, 3, 5, 7],
"values": [0.1, 0.2, 0.3, 0.4]
},
"using": "text"
}
희소 벡터 검색은 항상 정확한 매칭을 수행하며, Dot Product만을 사용한다. 유사도 계산 속도는 쿼리 벡터의 비제로 값 개수에 비례한다.
유사도 점수 필터링
{
"score_threshold": 0.75
}
검색 결과에서 유사도 점수가 기준 이하인 결과는 제외된다. 메트릭에 따라 의미는 달라지며, 예를 들어 유클리드 거리의 경우 값이 클수록 멀다고 판단하여 제거된다.
벡터 및 페이로드 반환
기본적으로 검색 결과는 ID와 점수만을 반환한다. 벡터 및 페이로드도 함께 가져오려면 다음과 같이 설정한다.
{
"with_vectors": true,
"with_payload": true
}
특정 페이로드만 포함하거나 제외할 수도 있다.
"with_payload": ["city", "town"]
또는
"with_payload": {
"exclude": ["city"]
}
배치 검색
다수의 검색 쿼리를 한 번에 수행할 수 있다.
POST /collections/{collection_name}/points/query/batch
{
"searches": [
{ "query": [...], "filter": {...}, "limit": 3 },
{ "query": [...], "filter": {...}, "limit": 3 }
]
}
필터가 동일한 경우 내부적으로 공유 최적화를 통해 처리 속도를 향상시킬 수 있다.
검색 결과 페이지네이션
{
"limit": 10,
"offset": 100
}
해당 설정은 11페이지(101번째)부터 10개 결과를 반환한다. 다만 HNSW 기반 검색의 특성상 큰 offset은 성능 저하를 초래할 수 있다.
그룹 기반 검색
document_id 등 특정 필드를 기준으로 결과를 그룹화할 수 있다.
POST /collections/{collection_name}/points/query/groups
{
"query": [1.1],
"group_by": "document_id",
"limit": 4,
"group_size": 2
}
-
limit: 최대 그룹 수 -
group_size: 각 그룹 내 포인트 수
배열 필드를 기준으로 그룹화할 경우, 해당 포인트는 여러 그룹에 중복 포함될 수 있다.
그룹화 + 룩업
중복 페이로드를 줄이기 위해, 문서 수준 메타데이터를 별도 컬렉션에 저장하고 그룹별로 lookup을 통해 참조할 수 있다.
"with_lookup": {
"collection": "documents",
"with_payload": ["title", "text"],
"with_vectors": false
}
결과는 그룹 내부에 lookup 필드로 포함된다.
랜덤 샘플링
v1.11.0부터는 무작위 포인트 샘플링이 가능하다.
POST /collections/{collection_name}/points/query
{
"query": { "sample": "random" }
}
디버깅, 테스트, 탐색 초기화 등에 유용하게 사용할 수 있다.
쿼리 계획(Query Planning)
Qdrant는 검색 시 쿼리 조건과 인덱스 상태에 따라 자동으로 실행 전략을 결정한다. 이 과정은 Query Planner에 의해 수행된다. 주요 원칙은 다음과 같다.
-
세그먼트(segment) 단위로 독립적으로 계획 수립
-
포인트 수가 적으면 전체 스캔 사용
-
필터 조건의 cardinality(결과 수 예측값)에 따라 적절한 인덱스 선택
-
가능한 경우 Payload Index 우선 사용
이 전략은 설정 파일을 통해 조정 가능하며, 컬렉션별로 개별 설정도 가능하다.
결론
Qdrant의 Similarity Search는 단순한 k-NN 검색을 넘어서, 필터링, 정렬, 그룹화, 배치 처리 등 다양한 기능을 포함하고 있다.
정확성과 속도 간의 균형을 고려하여 필요한 검색 기능을 조합할 수 있으며, 벡터 기반 검색 시스템을 설계할 때 Qdrant의 Query API는 매우 강력한 도구가 될 수 있다.