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);
| 지표 | IVFFlat | HNSW |
|---|---|---|
| 빌드 시간 | 4분 20초 | 38분 |
| 인덱스 크기 | 1.1 GB | 3.4 GB |
| p50 query (k=10) | 28 ms | 6 ms |
| recall@10 | 0.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가 거의 기본이 될 것 같다는 생각.
댓글 없음:
댓글 쓰기