3단계
pgvector + HNSW 설정
30 분
pgvector + HNSW 설정
임베딩을 저장할 곳이 필요합니다. 전용 벡터 DB (Pinecone · Qdrant · Weaviate) 도 훌륭하지만, 이미 PostgreSQL 을 쓰고 있다면 pgvector 가 가장 단순.
1. 설치
# Docker 이미지 (권장)
docker run -d --name pgvector \
-e POSTGRES_PASSWORD=postgres \
-p 5432:5432 \
pgvector/pgvector:pg16
또는 기존 PG 에 확장만:
# PostgreSQL 서버가 pgvector 설치되어 있어야 함
CREATE EXTENSION IF NOT EXISTS vector;
2. 테이블 스키마
CREATE TABLE IF NOT EXISTS document_chunks (
id BIGSERIAL PRIMARY KEY,
document_id BIGINT NOT NULL,
chunk_index INT NOT NULL,
content TEXT NOT NULL,
embedding vector(768), -- Gemini 004 차원
created_at TIMESTAMPTZ DEFAULT now()
);
vector(N) 의 N 은 임베딩 모델 차원. 변경 시 인덱스 재빌드 필요.
3. HNSW vs IVFFlat
| 방식 | 빌드 속도 | 쿼리 속도 | 정확도 | 적합 |
|---|---|---|---|---|
| HNSW | 느림 | 빠름 | 매우 높음 | 읽기 많은 RAG · 검색 |
| IVFFlat | 빠름 | 보통 | 튜닝 필요 | 대량 적재 · 주기적 재빌드 |
대부분의 RAG 에서는 HNSW 가 기본값.
4. 인덱스 생성
CREATE INDEX ON document_chunks
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
m— 이웃 그래프 크기 (기본 16). 높이면 정확 · 메모리 증가ef_construction— 빌드 시 탐색 폭 (기본 64). 높이면 빌드 느리지만 정확 ↑
운영 데이터 전체 적재 후 한 번에 인덱스 생성하는 편이 빠름.
5. 검색 쿼리
SELECT id, content, 1 - (embedding <=> $1::vector) AS similarity
FROM document_chunks
ORDER BY embedding <=> $1::vector
LIMIT 10;
<=>— 코사인 거리 (0 = 동일, 2 = 반대)<->— L2 거리<#>— 음수 내적
반드시 ORDER BY distance ASC · LIMIT k 형태로 작성. HNSW 인덱스가 동작하려면 이 패턴.
6. ef_search 런타임 튜닝
SET hnsw.ef_search = 100; -- 기본 40, 높이면 정확 · 느림
세션 단위 설정. k · 정확도 요구에 맞춰 조정.
7. 자주 걸리는 자리
vector타입 없음 오류 —CREATE EXTENSION vector;누락ORDER BY similarity DESC— HNSW 인덱스 미사용. 거리 기반 ASC 로- 차원 불일치 — 모델 바꿨는데 컬럼
vector(768)그대로 - 인덱스 없이 전체 테이블 스캔 —
EXPLAIN으로Index Scan확인
8. 백업 특이점
pg_dump 가 벡터 컬럼을 텍스트로 덤프 (정상). 복원 시에도 인덱스 재빌드 필요. 대량이면 pg_restore --jobs 병렬.
하고픈 말
pgvector 가 "전용 벡터 DB 의 80% 기능을 20% 노력으로" 제공합니다. 100M 벡터까지는 단일 PostgreSQL 로 충분. 그 이상은 Qdrant · Milvus 검토.
Next
- 04-rag-pipeline