50M 벡터에서 인덱스 빌드가 11시간 걸리면, 그건 이미 늦은 신호인가?
늦은 신호다. 5천만 벡터·768차원·99% recall 조건에서 PostgreSQL 계열(pgvector/pgvectorscale)의 인덱스 빌드는 약 11.1시간, 같은 조건의 Qdrant는 약 3.3시간이 걸렸다는 결과가 있다. 쿼리 지연 자체는 두 시스템 모두 sub-100ms로 큰 차이가 없었지만, 문제는 서비스가 돌아가는 동안이 아니라 인덱스를 다시 만들어야 하는 순간에 터진다.
핵심 정리
- 5천만 벡터·768차원·99% recall 조건에서 PostgreSQL+pgvectorscale 인덱스 빌드는 약 11.1시간, Qdrant는 약 3.3시간.
- 쿼리 지연만 보면 두 시스템 모두 sub-100ms라 전환 판단 근거로 부족하다 — 판단은 인덱스 빌드·메모리·k값·동시 부하를 함께 봐야 한다.
- 1천만 벡터·M=64 HNSW 기준 메모리 소요는 약 49GB로 64GB RAM 단일 노드에 들어가지만, 이 여유는 규모가 커지면 빠르게 사라진다.
- 1억 벡터대에서는 k값과 지연 허용치가 전용 엔진 선택의 핵심 조건이 된다 — k=10일 때 25만 QPS, k=100일 때 6만 QPS(같은 클러스터, p99 10ms 미만 유지).
- "벡터 수"는 이전 판단의 시작점일 뿐, 실제 트리거는 인덱스 재빌드 시간과 운영 중 재색인 빈도다.
벡터가 늘어난 게 원인이었을까?
아니다. 벡터 수 자체는 인덱스 빌드 시간 차이를 설명하지 못한다. 같은 5천만 벡터, 같은 768차원, 같은 99% recall 목표를 두 시스템에 동일하게 걸었는데도 빌드 시간은 3배 이상 벌어졌다. 벡터 수가 원인이라면 두 시스템 모두 비슷하게 느려져야 했다. 실제로는 HNSW 인덱스를 단일 프로세스·단일 노드 구조로 순차에 가깝게 쌓아 올리는 방식과, 처음부터 분산·병렬 빌드를 전제로 설계된 구조의 차이가 갈랐다. 즉 "몇 개부터 전용 엔진이 필요한가"라는 질문 자체가 틀렸다. 같은 벡터 수에서도 인덱스 구축 아키텍처에 따라 결과가 갈리기 때문에, 벡터 수는 전환을 검토해야 하는 시점을 알리는 신호일 뿐 원인은 아니다.
메모리만 늘리면 버틸 수 있었을까?
아니다. 1천만 벡터, 768차원, HNSW M=64 설정에서 메모리 계산은 약 49GB로 나오고, 이는 64GB RAM을 가진 단일 r7g.2xlarge 노드에 들어간다는 계산이 있다. 실제로 ScyllaDB Vector Search 벤치마크는 AWS Graviton 5노드(스토리지 노드 3대·검색 노드 2대) 구성에서 1만2840 QPS, serial P99 5.5ms를 기록했다. 문제는 이 계산이 1천만 벡터 기준이라는 점이다. 5천만, 1억으로 늘어나면 M=64 기준 메모리 요구량은 선형에 가깝게 증가하고, 단일 노드 RAM 한계를 곧 넘어선다. 메모리를 늘리는 방향의 대응은 특정 규모까지만 유효하고, 그 이상에서는 클러스터형 구조로 전환하는 것 외에 대안이 없다. 즉 메모리 증설은 임계점을 늦출 뿐 없애지 못한다.
recall 목표를 낮추면 해결됐을까?
아니다. recall 99%는 워크로드가 요구하는 조건이지 조정 가능한 여유값이 아니다. TigerData 벤치마크와 ScyllaDB 비교 모두 recall 목표를 고정한 채 빌드 시간·지연·QPS를 비교했다. recall을 낮추면 빌드 시간은 줄어들 수 있지만, 그건 검색 품질을 낮춰 문제를 우회하는 것이지 인프라 문제를 해결하는 게 아니다. 1억 벡터·96차원 조건에서 ScyllaDB가 기록한 p99 1.7ms, 최대 25만2000 QPS 역시 k=10 기준이었고, k=100으로 올리면 QPS는 6만 수준으로 떨어지면서도 p99는 10ms 미만을 유지했다. 여기서 보이는 건 recall이나 k값은 워크로드 요구사항이며, 이를 낮춰 벤치마크를 유리하게 만드는 건 회고에서 배제해야 할 방향이라는 점이다.
그렇다면 진짜 갈아탈 지점을 가른 원인은 무엇인가?
원인은 벡터 수가 아니라 "적재·인덱싱·검색이 동시에 걸리는 구조"였다. PostgreSQL 계열은 단일 인스턴스 안에서 인덱스 빌드와 쿼리 서빙이 같은 자원을 공유한다. 5천만 벡터 규모에서 인덱스를 11시간 동안 다시 쌓는 동안, 그 인스턴스는 다른 부하를 감당할 여유가 크게 줄어든다. 반면 Qdrant나 ScyllaDB Vector Search 같은 구조는 스토리지 노드와 검색 노드를 분리하거나(스토리지 3대·검색 2대), 빌드 자체를 병렬 분산 처리하도록 만들어져 있다. VAST Data가 500억 벡터 규모에서 8개 CNode로 안정적인 처리량을 유지했다고 보고한 사례나, 10억 벡터·128차원에서 Milvus의 디스크 기반 백엔드 대비 약 11배 높은 QPS(89 QPS 대 1000 QPS)를 기록했다고 밝힌 사례도 같은 방향을 가리킨다. 인덱싱과 검색을 같은 자원 풀 위에서 처리하느냐, 분리해서 처리하느냐가 수천만 벡터 임계 이후 체감 차이를 만든 근본 원인이다.
무엇을 바꿨나?
전환 판단을 "벡터 수" 단일 지표에서 네 가지 체크리스트로 바꿨다. 첫째, 인덱스 재빌드 시간이 운영 SLA(예: 야간 배치 창 내 완료)를 넘는지. 둘째, HNSW 메모리 계산치(M값·차원·벡터 수 기준)가 단일 노드 RAM을 넘는지 — 1천만 벡터·M=64 기준 약 49GB라는 계산을 기준선으로 삼았다. 셋째, 요구되는 k값과 p99 지연 허용치가 함께 감당 가능한지 — k=10과 k=100은 같은 클러스터에서도 QPS가 4배 이상 차이 난다. 넷째, 인덱싱과 검색이 같은 시간대에 동시에 걸리는 워크로드인지. 이 네 조건 중 두 개 이상이 걸리면 전용 벡터 엔진 검토를 시작하고, 하나도 안 걸리면 RDB 확장(pgvectorscale 등)으로 버티는 쪽을 우선한다.
이 판단, 벡터 DB 밖에서도 쓸 수 있나?
쓸 수 있다. "데이터 종류가 늘었으니 전용 스토어로 옮긴다"는 판단은 늘 틀리기 쉽다. 옮겨야 하는 진짜 이유는 거의 항상 특정 자원(메모리, 빌드 시간, 동시 부하)이 단일 구조의 한계선에 닿았기 때문이다. Elastic이 3노드 GCP·3노드 AWS를 같은 조건으로 맞춰 Elasticsearch가 Qdrant와 동급이라고 주장한 사례, 그리고 이에 대한 반박이 함께 존재한다는 사실도 같은 교훈을 준다 — 전용 엔진이 항상 압도적이라는 단정은 벤치마크 조건을 얼마나 맞췄는지에 따라 뒤집힐 수 있다. OpenSearch가 벡터 검색 워크로드 문서에서 인덱싱과 검색을 함께 벤치마크 대상으로 정의한 것도 같은 이유다. 규모가 아니라 "어느 자원이 먼저 한계에 닿는가"를 먼저 확인하는 것, 이것이 2026년 기준 데이터 저장소 선택에서 반복적으로 쓸 수 있는 기준이다.
자주 묻는 질문
pgvectorscale과 Qdrant 중 어느 쪽이 항상 유리한가?
항상 유리한 쪽은 없다. 인덱스 빌드 시간은 Qdrant가 짧았지만 쿼리 지연 자체는 두 시스템 모두 sub-100ms로 비슷했다. 재색인 빈도가 낮고 빌드 시간 여유가 있는 워크로드라면 RDB 확장으로 충분할 수 있다.
k값이 QPS에 이렇게 큰 영향을 주는 이유는?
k가 커지면 한 번의 질의에서 후보군을 더 넓게 탐색하고 정렬해야 하므로 노드당 처리 비용이 늘어난다. 1억 벡터 조건에서 k=10일 때 25만 QPS였던 것이 k=100에서는 6만 QPS로 떨어진 사례가 이를 보여준다.
RDB에서 전용 엔진으로 옮길 때 데이터 마이그레이션 자체의 위험은 무엇인가?
가장 큰 위험은 이관 중 재색인이 이중으로 걸리는 구간이다. 기존 인덱스를 유지한 채 새 클러스터에 재빌드를 걸면 두 시스템 모두에 부하가 겹치므로, 트래픽을 분리하거나 배치 창을 넉넉히 잡아야 한다.
벡터 수가 수백만 단위면 전용 엔진을 고려할 필요가 없는가?
그 규모에서는 대부분 RDB 확장만으로 해결된다. 이 글에서 다룬 임계는 수천만~수억 벡터대에서 인덱스 빌드 시간과 메모리 계산이 단일 노드 한계에 닿기 시작하는 지점을 기준으로 한다.
더 알아보기
데이터베이스 선택의 실체: 워크로드로 읽는 판단 기준 — 이 주제의 종합 가이드