20230305

pgvector 실전 — IVFFlat vs HNSW

pgvector 0.4.0이 얼마 전 나왔고 HNSW 인덱스가 추가됐다 (정확히는 곧 0.5.0 예정). IVFFlat만 쓰다가 비교해볼 기회가 생겨서 같은 데이터셋 170만 row × 1536 dim(ada-002)로 돌려봤다.

인덱스 빌드

-- IVFFlat
CREATE INDEX ON docs USING ivfflat (embedding vector_cosine_ops)
  WITH (lists = 1300);   -- sqrt(N) 근처

-- HNSW
CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);
지표IVFFlatHNSW
빌드 시간4분 20초38분
인덱스 크기1.1 GB3.4 GB
p50 query (k=10)28 ms6 ms
recall@100.91 (probes=10)0.98 (ef_search=40)

HNSW가 쿼리는 4배 이상 빠른데 빌드가 훨씬 느리고 메모리 + 디스크를 많이 먹는다. 그리고 insert가 들어올 때마다 graph를 재구성하는 비용이 있어서 write 많은 테이블엔 조심해야 함.

IVFFlat은 lists 값에 엄청 민감한데, 일반적으로 rows/1000 ~ sqrt(rows) 사이에서 튜닝한다. probes를 올리면 recall이 올라가는데 latency가 선형 증가. 우리 케이스는 probes=10 근처가 accuracy-speed 절충점.

결론(지금 시점)

  • read-heavy, static data → HNSW
  • write가 계속 들어오는 테이블 → IVFFlat (혹은 HNSW에 create partial index)
  • 수백만~수천만 row면 Qdrant나 Milvus 고려 시작해야 할 듯. 아직 우리는 안 감.

pgvector 0.5 안정화되면 HNSW가 거의 기본이 될 것 같다는 생각.