메모리 티어
메모리 티어 (ops-configuration-memory-tiers)
Qdrant는 모든 컬렉션 데이터를 디스크에 영구 저장해요. 검색을 더 빠르게 하려면 개별 구조를 RAM에 로드할 수도 있는데, 모든 것을 메모리에 두는 게 항상 비용 효율적이지는 않습니다. 구조별 memory 파라미터는 각 구조가 RAM에 어떻게 캐시되는지 제어합니다: 영구 고정(pinned), 시작 시 디스크 캐시로 워밍(cached), 아니면 처음 접근할 때까지 디스크에 남겨두기(cold).
출처: Qdrant 공식문서
이 페이지에서는 메모리 티어를 설정하는 방법, 사용 가능한 배치(placement) 티어, 디스크 기반 검색에 최적화하는 방법을 다룹니다.
메모리 티어 설정
이 페이지는 Qdrant v1.19에서 도입된 memory 파라미터를 다룹니다. 이전 버전을 쓰고 있다면, 새 파라미터를 이전 것으로 어떻게 매핑하는지 Legacy Settings 섹션을 참고하세요.
Qdrant의 각 컬렉션은 여러 개의 독립된 구조로 뒷받침됩니다.
- Dense vectors는 컬렉션 또는 named vector의 원본 부동소수점 벡터를 담아요.
- HNSW 벡터 인덱스는 dense 벡터 위에 만들어진 그래프 구조로, 근사 최근접 이웃 검색을 빠르게 만듭니다.
- Quantized vectors는 원본 벡터의 압축된 복사본으로, 검색을 빠르게 하고 메모리 사용을 줄이는 데 쓰입니다.
- Sparse vector index는 sparse 벡터 위에 만들어진 정확한 인버티드-인덱스 방식 구조예요.
- Payloads는 각 포인트에 붙은 JSON 문서입니다.
- Payload indexes는 필터링을 빠르게 하는 필드별 인덱스입니다.
이 구조 각각은 RAM에 어떻게 캐시할지를 제어하는 memory 파라미터를 받아요: 영구 고정하거나, 시작 시 디스크 캐시로 워밍하거나, 처음 접근할 때까지 디스크에 두는 것. 사용 가능한 티어는 다음과 같습니다.
pinned: Qdrant는 데이터를 힙(heap)에 로드하고 절대 내보내지(evict) 않아요. 요청은 항상 빠르지만, 구조가 항상 RAM에 맞아야 합니다. 힙에 데이터를 할당하기 때문에, 힙 기반 인메모리 표현을 지원하는 구조에서만 사용할 수 있어요.cached: Qdrant는 시작할 때 데이터를 디스크 캐시에 미리 로드해서 첫 요청이 빠릅니다. 메모리 압력이 생기면 운영체제가 다른 구성 요소의 데이터가 더 자주 쓰인다고 판단하면 이 데이터를 내보낼 수 있어요.cold: Qdrant는 데이터를 RAM에 미리 로드하지 않아요. 시작은 더 빠르고 메모리도 덜 쓰지만, OS가 캐시하기 전까지는 어떤 페이지든 첫 접근에 디스크 읽기가 필요합니다.
cold와 cached는 모두 데이터를 메모리 매핑된 파일(memory-mapped file)로 뒷받침합니다. 유일한 차이는 Qdrant가 로드 시 OS 페이지 캐시를 적극적으로 워밍하느냐 여부예요. OS는 두 티어를 같은 기준으로 내보내므로, 메모리 압력이 있을 때 cached 데이터가 cold 데이터보다 우선 순위를 받지 않습니다. I/O 부하가 심할 때 어느 티어에서든 내보내진 페이지는 다시 로드하려면 디스크 읽기가 필요해서 지연 시간이 늘어납니다.
제한 사항
- Qdrant는 dense 벡터와 페이로드에 대해
pinned를 거부해요. 두 구조 모두 메모리 매핑된 인메모리 표현(cached또는cold)만 지원하기 때문입니다. - sparse 벡터의 경우, sparse 벡터 인덱스만
memory파라미터를 가집니다. Qdrant는 sparse 벡터용 RAM 캐시를 제공하지 않아요. 그 값들은 인덱스 검색 단계에서 읽히지 않고 포인트를 가져올 때만 읽히기 때문입니다.
기본 티어
구조에 memory를 명시적으로 설정하지 않으면 Qdrant는 다음 티어를 기본값으로 사용합니다.
| 데이터 구조 | 기본 티어 |
|---|---|
| Dense vectors | cached |
| HNSW vector index | cached |
| Quantized vectors | 원본 dense 벡터의 배치에 따라 다름: 원본 벡터가 cached면 pinned, 원본 벡터가 cold면 cold |
| Sparse vector index | pinned |
| Payloads | cold |
| Payload indexes | pinned |
Low Memory Mode는 메모리 제약 하에서 시작 시 이 기본값을 낮출 수 있습니다. 단, 지속된 컬렉션 설정은 바꾸지 않아요.
예제
이 예제는 벡터는 RAM에 캐시되고, HNSW 벡터 인덱스는 cold, 양자화 벡터는 pinned, 페이로드는 cached가 되도록 컬렉션을 구성합니다.
PUT /collections/{collection_name}
{
"vectors": {
"size": 768,
"distance": "Cosine",
"memory": "cached"
},
"hnsw_config": {
"memory": "cold"
},
"quantization_config": {
"scalar": {
"type": "int8",
"memory": "pinned"
}
},
"payload": {
"memory": "cached"
}
}
디스크 기반 검색 최적화
구조가 cold 티어에 있으면 검색할 때 디스크에서 읽을 수 있어요. 추가 디스크 I/O에도 불구하고 검색 지연 시간을 줄이는 기법들을 소개합니다.
양자화 (Quantization)
양자화는 벡터를 더 작은 표현으로 압축합니다. 양자화된 복사본은 원본 벡터가 cold여도 RAM에 넉넉히 들어맞아요. 이를 통해 Qdrant는 대부분의 후보를 양자화된 복사본으로 점수 매기고, top 결과만 정확히 리스코어하기 위해 원본 벡터를 디스크에서 읽을 수 있습니다. 양자화는 검색 중 디스크에서 가져올 데이터 양을 줄여주는 대신, 약간의 정확도 손실을 도입해요.
quantization_config에서 memory: "pinned"로 설정해 양자화 벡터를 RAM에 유지하세요. 핀닝이 없으면 메모리 압력에서 양자화 복사본이 내보내져서, Qdrant가 양자화와 원본 벡터를 모두 디스크에서 읽어야 할 수 있어요.
정확도 손실이 수용 가능하다면, 쿼리의 검색 파라미터에서 rescore: false로 설정해 원본 벡터에 대한 리스코어링을 끌 수 있습니다. 그러면 검색 중 디스크 읽기가 완전히 없어지고, 원본 벡터의 메모리 티어가 더는 검색 지연 시간에 영향을 주지 않아요. rescore는 쿼리별 파라미터이므로 정확도가 필요한 쿼리에는 켜둘 수 있습니다.
POST /collections/{collection_name}/points/query
{
"query": [0.2, 0.1, 0.9, 0.7],
"params": {
"quantization": {
"rescore": false
}
},
"limit": 10
}
비동기 I/O (Async I/O)
비동기 I/O를 쓰면 Qdrant가 디스크 읽기를 한 번에 하나씩이 아니라 동시에 발행해서, 구조가 cold일 때 쿼리가 디스크를 기다리는 시간을 줄여줍니다. 이는 Linux 커널의 비동기 I/O 인터페이스인 io_uring을 사용하며, 이를 지원하는 커널이 필요해요. 비동기 I/O는 벡터 리스코어링에 가장 도움이 되는데, 원본 벡터가 cold이고 양자화가 켜져 있을 때(top 후보를 디스크에 있는 원본과 리스코어하는 것이 순차 디스크 읽기가 쌓이는 지점) 유용합니다. 페이로드 저장에도 적용되므로 cold 페이로드를 디스크에서 읽을 때마다 도움이 됩니다.
io_uring 설정
v1.19.0부터 사용 가능
저장 설정에서 io_uring을 auto로 설정하면 cold인 어떤 구조에도 비동기 I/O를 적용합니다. 설정 파일에서 활성화할 수 있어요.
storage:
performance:
io_uring: auto
또는 환경 변수로:
QDRANT__STORAGE__PERFORMANCE__IO_URING=auto
async_scorer 설정
v1.3.0부터 사용 가능
벡터 리스코어링에만 비동기 I/O를 적용하는 이전 설정입니다. 1.19보다 오래된 버전에 있다면 io_uring보다 이걸 선호하세요. 설정 파일에서 활성화할 수 있어요.
storage:
performance:
async_scorer: true
또는 환경 변수로:
QDRANT__STORAGE__PERFORMANCE__ASYNC_SCORER=true
로컬 NVMe/SSD 저장소
디스크 기반 검색은 빠른 로컬 저장소의 이점을 누립니다. Qdrant를 셀프 호스팅한다면 머신에 직접 연결된 NVMe 또는 SSD 드라이브를 사용하세요. 네트워크 연결 저장소는 피하세요. 벡터 검색에 필요한 순차 읽기에는 너무 느립니다.
인라인 저장소 (Inline Storage)
v1.16.0부터 사용 가능
HNSW 벡터 인덱스를 cold 티어에 두는 것은 피하세요. 디스크에 저장해야 하고 양자화를 쓴다면 인라인 저장소(inline storage) 활성화를 고려해 보세요. 이는 디스크 사용량을 3~4배 늘리는 대신 I/O 연산을 줄여줍니다.
마이그레이션
pre-1.19 버전에서 더 새 버전으로 마이그레이션할 때, Qdrant는 메모리 배치를 제어하는 레거시 설정을 새 memory 설정으로 자동 변환하지 않아요. 레거시 설정은 제거되지 않고 deprecated만 되어서, 기존 설정은 계속 동작합니다. 레거시 설정을 가진 pre-1.19 컬렉션은 설정을 바꾸지 않아도 새 버전에서 계속 동작해요.
레거시 설정 (Legacy Settings)
1.19 이전에는 메모리 배치가 다른 파라미터 집합으로 제어됐습니다. 이 파라미터들은 deprecated되었어요. 다음 표로 새 memory 파라미터를 레거시 파라미터에 매핑하세요.
Dense Vectors
레거시 파라미터는 on_disk입니다.
| memory | 레거시 값 |
|---|---|
| cached | on_disk: false |
| cold | on_disk: true |
HNSW Vector Index
레거시 파라미터는 hnsw_config에 설정된 on_disk입니다.
| memory | 레거시 값 |
|---|---|
| pinned | 레거시 동등 항목 없음 |
| cached | on_disk: false |
| cold | on_disk: true |
Quantized Vectors
레거시 파라미터는 always_ram입니다. always_ram: true는 항상 pinned로 해석됩니다. 그렇지 않으면 양자화 벡터는 원본 벡터의 배치를 상속합니다: 벡터가 RAM에 있으면 pinned, 디스크에 있으면 cold.
| memory | 레거시 값 |
|---|---|
| pinned | always_ram: true, 또는 원본 벡터에서 상속 |
| cached | 레거시 동등 항목 없음 |
| cold | 원본 벡터에서 상속 |
Sparse Vector Index
레거시 파라미터는 on_disk입니다.
| memory | 레거시 값 |
|---|---|
| pinned | on_disk: false |
| cached | 레거시 동등 항목 없음 |
| cold | on_disk: true |
Payloads
레거시 파라미터는 컬렉션에 설정된 on_disk_payload입니다.
| memory | 레거시 값 |
|---|---|
| cached | on_disk_payload: false |
| cold | on_disk_payload: true |
Payload Indexes
레거시 파라미터는 각 필드 인덱스에 설정된 on_disk입니다.
| memory | 레거시 값 |
|---|---|
| pinned | on_disk: false |
| cached | 레거시 동등 항목 없음 |
| cold | on_disk: true |