데이터베이스 최적화 FAQ
데이터베이스 최적화 FAQ (faq-database-optimization)
Qdrant를 실제 운영에서 쓰다 보면 메모리가 왜 이렇게 높지, 검색이 왜 느려지지 같은 질문이 꼭 나와요. 이 페이지에서는 자주 묻는 질문들을 실제 상황과 연결해서 하나씩 풀어볼게요. 각 질문은 '어떤 문제를 겪고 있는지'를 먼저 보여드리고, 그 다음에 해결 방법을 설명하는 구성으로 가요.
출처: Qdrant 공식문서
메모리 사용량을 어떻게 줄이나요?
메모리를 가장 많이 차지하는 주범은 바로 벡터 데이터예요. 이를 다루는 방법은 크게 두 가지가 있는데요.
- 양자화(Quantization)를 설정해 벡터의 메모리 사용량을 줄인다.
- 벡터를 디스크에 저장하는(on-disk vector storage) 방식을 설정한다.
어느 쪽을 택할지는 여러분의 요구사항에 따라 달라져요. Qdrant를 가장 최적으로 활용하는 방법에 대해 더 자세히 알고 싶다면 최적 구성 문서를 읽어보시면 좋아요.
머신(서버) 사양은 어떻게 고르나요?
리소스 소비 관점에서 Qdrant를 쓰는 방식은 크게 두 가지 시나리오로 나뉘어요.
- 성능 최적화형(Performance-optimized) – 벡터 검색을 가능한 한 빠르게(많이) 서빙해야 할 때예요. 이 경우 벡터 데이터를 최대한 RAM에 올려두어야 해요. 필요한 RAM을 예상하려면 계산기를 이용해 보세요.
- 저장 최적화형(Storage-optimized) – 많은 벡터를 저장하면서 검색 속도를 어느 정도 희생해 비용을 줄이고 싶을 때예요. 이 경우에는 디스크 속도에 더 주목해야 해요. 자세한 내용은 메모리 소비(Memory Consumption) 문서에서 다루고 있어요.
on-disk 벡터 저장을 설정했는데도 메모리 사용량이 여전히 높아요. 왜 그런가요?
먼저, top이나 htop이 보여주는 메모리 사용량 수치는 오해를 부를 수 있어요. 그 수치는 서비스가 실행되기 위해 필요한 '최소' 메모리량을 보여주는 게 아니거든요. RSS 메모리 사용량이 10GB라고 해서, 8GB RAM의 머신에서는 실행되지 못한다는 뜻은 아니에요.
Qdrant는 검색 지연 시간(latency)을 줄이기 위해 여러 기법을 사용하는데, 디스크 데이터를 RAM에 캐싱하거나 디스크에서 RAM으로 데이터를 미리 로드하는 방식이 여기에 해당해요. 그 결과 Qdrant 프로세스가 서비스 실행에 필요한 최소량보다 더 많은 메모리를 쓰는 일이 생길 수 있어요.
사용하지 않는 RAM은 낭비되는 RAM이에요 (Unused RAM is wasted RAM)
서비스의 메모리 사용량을 제한하고 싶다면 Docker의 메모리 제한이나 Kubernetes의 리소스 제한을 사용하는 걸 권장해요.
쓰기 부하가 큰 상황에서 검색 지연 시간이 늘어나요. 어떻게 해야 하나요?
Qdrant의 백그라운드 최적화 프로그램(optimizer)은 HNSW 인덱스를 만들고, 세그먼트를 병합하고, 양자화를 적용하는 작업을 계속 수행하면서 동시에 검색 쿼리도 처리해요. 쓰기 부하가 심해지면 최적화 프로그램과 쿼리가 같은 CPU, 메모리, I/O를 두고 경쟁하게 돼요. 이 경쟁을 줄이는 주요 방법을 효과가 큰 순서대로 정리하면 다음과 같아요.
- 큰 인덱스되지 않은 세그먼트에서 읽기가 발생하지 않게 한다.
prevent_unoptimized를 켜면 아직 인덱싱되지 않은 데이터에 대한 검색을 차단해요. 이때 모든 쓰기 요청에wait=false도 함께 설정해야 head-of-line blocking을 피할 수 있어요. - 더 작은 배치 크기를 시도한다. 배치가 작을수록 각 쓰기 트랜잭션이 짧아져서, 읽기와 경쟁하는 시간 범위가 좁아져요.
- 최적화 프로그램의 CPU 예산을 낮춘다.
optimizer_cpu_budget을 사용해 최적화 프로그램이 쓸 수 있는 코어 수를 제한하면 쿼리 처리에 더 많은 여유를 남겨줘요. 좋은 시작점은 사용 가능한 vCPU의 50% 정도예요. - 최적화 스레드를 조정한다. 샤드당
max_optimization_threads를1로 설정하면 최적화 작업이 직렬화되어 CPU 스파이크가 완만해져요. - 지연 fan-out을 사용한다. 컬렉션에 레플리카가 있다면
read_fan_out_delay_ms를 p95 읽기 지연 시간으로 설정하면, 느린 레플리카의 요청이 자동으로 더 빠른 레플리카에 재시도돼요. - 스케일 아웃한다. 노드별 튜닝으로 한계에 도달했다면 레플리카를 추가하거나 RAM이 더 많은 노드로 업그레이드해서(벡터가 메모리에 들어가도록) 경쟁 원인 자체를 제거할 수 있어요.
단계별 전체 해결 과정은 읽기-쓰기 경쟁 문제 해결(Troubleshoot Read-Write Contention) 문서에서 확인하실 수 있어요.
요청이 아주 느리거나 타임아웃이 나요. 어떻게 해야 하나요?
몇 가지 가능한 원인이 있는데요.
- 페이로드 인덱스 없는 필터 사용 – 필터로 검색을 하는데 페이로드 인덱스가 없다면, Qdrant는 필터 조건을 확인하기 위해 페이로드 데이터 전체를 디스크에서 읽어와야 해요. 페이로드 인덱스가 제대로 설정되어 있는지 확인해 보세요.
- 느린 디스크에서 on-disk 벡터 저장 사용 – on-disk 벡터 저장을 사용한다면 디스크가 충분히 빠른지 확인해야 해요. 최소 50k IOPS 이상의 로컬 SSD를 권장해요. 디스크 속도가 검색 지연 시간에 미치는 영향은 메모리 소비(Memory Consumption) 문서에서 더 자세히 다루고 있어요.
- 지나치게 큰 limit 또는 비최적 쿼리 파라미터 – limit이나 offset이 크면 성능이 크게 저하될 수 있어요. 기본값에서 크게 벗어난 쿼리/컬렉션 파라미터를 꼼꼼히 살펴보세요. 그게 성능 문제의 원인일 수 있어요.
더 알아보기 (Learn more)
- 양자화(Quantization) – 벡터 메모리 줄이기
- 최적 구성(Optimize) – Qdrant 활용법 전반
- 읽기-쓰기 경쟁 문제 해결
- 메모리 소비 문서