PostgreSQL 단일 스택으로 구성하는 pgvector·pgvectorscale RAG 검색
pgvector와 pgvectorscale을 활용해 PostgreSQL에서 벡터·전문·관계형 검색을 통합하는 RAG 아키텍처와 인덱스 선택 기준을 다룬다.
2026-08-14 · 최초 발행 2026-05-05
벡터 검색을 PostgreSQL 안으로 가져오는 선택지
Timescale이 공개한 AWS EC2 벤치마크는 5,000만 개 Cohere 임베딩(768차원)을 대상으로 했다. PostgreSQL과 pgvector, pgvectorscale 조합은 99% 리콜 ANN(근사 최근접 이웃) 검색에서 Pinecone 스토리지 최적화 인덱스(s1)보다 p95 레이턴시를 28배 단축하고 쿼리 처리량을 16배 높였다.
비용 비교도 같은 방향을 가리킨다. AWS EC2 자체 호스팅은 월 $835, Pinecone s1은 월 $3,241로 약 75% 절감이 가능하다. 성능 최적화 인덱스(p2)와 비교하면 p95 레이턴시는 1.4배 단축되고 처리량은 1.5배 향상된다. Pinecone p2의 월 비용은 $3,889다. Qdrant 비교에서는 99% 리콜에서 pgvectorscale이 471 QPS, Qdrant가 41 QPS를 기록해 11.4배 차이가 났다.
이 비교에서 중요한 점은 벡터 검색만의 성능이 아니다. 이미 운영 중인 PostgreSQL 위에서 관계형 데이터와 벡터 데이터를 같은 트랜잭션 컨텍스트로 처리할 수 있다는 점이 단일 스택의 핵심이다.
워크로드에 맞춰 고르는 pgvector 인덱스
pgvector의 ANN 인덱스는 HNSW와 IVFFlat이다. 데이터 양, 메모리 여유, 레이턴시 우선순위에 따라 선택이 달라진다.
HNSW(Hierarchical Navigable Small World)는 계층형 그래프를 이용한다. 인덱스를 메모리에 유지하므로 쿼리 레이턴시가 낮고, m은 레이어당 최대 연결 수, ef_construction은 인덱스 생성 때의 탐색 폭을 조정한다. 대신 메모리 사용량이 크고 인덱스 구축 시간이 길어진다.
-- HNSW 인덱스 생성
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- 검색 시 ef_search 파라미터 조정
SET hnsw.ef_search = 100;
SELECT id, content, embedding <=> '[0.1, 0.2, ...]' AS distance
FROM documents
ORDER BY distance
LIMIT 10;
IVFFlat(Inverted File with Flat Quantization)은 벡터 공간을 클러스터로 나누고, 검색 시 가까운 클러스터를 탐색한다. lists는 클러스터 수, probes는 검색할 클러스터 수다. 메모리 효율과 인덱스 생성 속도는 좋지만, 클러스터 경계에 있는 벡터를 놓칠 수 있다.
-- IVFFlat 인덱스 생성 (데이터 삽입 후 생성 권장)
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- 검색 시 probes 파라미터로 정밀도 조절
SET ivfflat.probes = 10;
SELECT id, content, embedding <=> '[0.1, 0.2, ...]' AS distance
FROM documents
ORDER BY distance
LIMIT 10;
pgvector v0.8.0부터는 필터 성능이 크게 개선됐다. WHERE 절과 ANN 인덱스를 함께 사용할 때 PostgreSQL 옵티마이저는 B-tree 인덱스와 ANN 인덱스 가운데 더 효율적인 경로를 선택한다. 반복적 인덱스 스캔(iterative index scan)도 추가되어 필터 조건을 만족하는 결과가 부족하면 탐색 범위를 자동으로 넓힌다.
-- 반복적 인덱스 스캔 활성화 (v0.8.0+)
SET hnsw.iterative_scan = relaxed_order;
SET hnsw.max_scan_tuples = 20000;
-- 필터와 벡터 검색 결합
SELECT id, content
FROM documents
WHERE category = 'tech' AND created_at > '2025-01-01'
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 10;
StreamingDiskANN이 메모리 제약을 다루는 방식
pgvectorscale은 Microsoft Research의 DiskANN 알고리즘을 PostgreSQL 환경에 맞게 다시 구현한 StreamingDiskANN 인덱스를 제공한다. HNSW가 전체 인덱스를 메모리에 올려두는 방식이라면, StreamingDiskANN은 인덱스를 디스크에 저장하고 필요한 부분만 읽는다.
디스크 기반 인덱싱은 수억 개 벡터를 단일 머신에서 처리할 수 있게 한다. HNSW는 대규모 데이터셋에서 인덱스 전체를 RAM에 올려야 해 수백 GB의 메모리가 필요할 수 있지만, StreamingDiskANN은 SSD를 활용한다.
Statistical Binary Quantization(SBQ)은 Timescale 연구팀이 개발한 압축 기법이다. 표준 Binary Quantization보다 정확도 손실을 줄이면서 메모리와 I/O를 절감하며, 데이터의 통계적 분포에 맞춰 차원별 양자화 임계값을 조정한다.
레이블 기반 필터 검색도 StreamingDiskANN의 특징이다. Microsoft의 Filtered DiskANN 연구를 바탕으로 메타데이터 필터와 벡터 유사도 검색을 함께 최적화한다. 필터 결과를 먼저 구한 뒤 벡터 검색을 하는 post-filtering보다 훨씬 효율적이다.
-- pgvectorscale 설치 및 StreamingDiskANN 인덱스 생성
CREATE EXTENSION IF NOT EXISTS vectorscale CASCADE;
CREATE INDEX ON documents
USING diskann (embedding)
WITH (num_neighbors = 50, search_list_size = 100);
-- 레이블 기반 필터 검색
SELECT id, content
FROM documents
WHERE tenant_id = 'acme-corp'
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 10;
OLTP·벡터·전문 검색을 한 인스턴스에 배치할 때
단일 PostgreSQL 인스턴스에서 OLTP, 벡터 검색, 전문 검색을 함께 처리하면 운영 경로를 줄이면서 데이터 일관성을 확보할 수 있다.
스키마는 동일 레코드와 벡터가 1:1로 대응하는지에 따라 달라진다. 이 경우 벡터를 같은 테이블의 컬럼으로 둘 수 있다. 하나의 레코드에서 여러 청크 벡터가 나온다면 별도 테이블로 분리하는 편이 맞다.
-- 통합 RAG 스키마 예시
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
tenant_id TEXT NOT NULL,
title TEXT NOT NULL,
content TEXT NOT NULL,
-- 전문 검색용
search_vector TSVECTOR GENERATED ALWAYS AS (
to_tsvector('korean', title || ' ' || content)
) STORED,
created_at TIMESTAMPTZ DEFAULT NOW()
) PARTITION BY LIST (tenant_id);
CREATE TABLE document_chunks (
id BIGSERIAL PRIMARY KEY,
document_id BIGINT REFERENCES documents(id),
chunk_index INT NOT NULL,
chunk_text TEXT NOT NULL,
embedding VECTOR(1536),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- 멀티-모달 검색: 벡터 + 전문 검색 결합
SELECT
d.id,
d.title,
dc.chunk_text,
dc.embedding <=> $1 AS vector_distance,
ts_rank(d.search_vector, query) AS text_rank
FROM document_chunks dc
JOIN documents d ON dc.document_id = d.id,
to_tsquery('korean', $2) query
WHERE d.tenant_id = $3
AND d.search_vector @@ query
ORDER BY vector_distance
LIMIT 20;
테넌트별 또는 날짜별 파티셔닝은 벡터 검색 범위를 직접 줄인다. 검색 대상 파티션이 감소하고, 각 파티션에 HNSW 또는 DiskANN 인덱스를 두면 파티션 단위 병렬 검색도 가능하다.
RAG 파이프라인에서 분리할 것과 함께 묶을 것
임베딩 생성은 외부 API(OpenAI, Cohere 등)나 로컬 모델이 담당하고, PostgreSQL은 저장과 검색을 맡는다. pgvector 자체는 임베딩을 생성하지 않는다.
청크가 작아질수록 벡터 수와 인덱스 크기는 증가한다. 1M 벡터 미만에는 HNSW, 그 이상에는 StreamingDiskANN을 쓰는 것이 일반적인 가이드라인이다. 전문 검색은 BM25/TF-IDF 기반 검색과 벡터 유사도 검색을 결합하는 방식으로 구성할 수 있으며, PostgreSQL에서는 pg_trgm과 tsvector가 이 역할을 한다. 이 조합은 단독 사용보다 재현율이 높다.
문서 삽입과 벡터 생성을 하나의 트랜잭션으로 묶을 수 있다는 점도 다르다. 전용 벡터 DB에서는 관계형 DB와 벡터 DB 사이의 이중 커밋 문제가 발생하지만, PostgreSQL 단일 스택에서는 이 문제가 없다.
-- 트랜잭션 내 문서 삽입 + 청크 벡터 저장
BEGIN;
INSERT INTO documents (tenant_id, title, content)
VALUES ('acme', '분기 보고서', :content)
RETURNING id INTO v_doc_id;
INSERT INTO document_chunks (document_id, chunk_index, chunk_text, embedding)
SELECT v_doc_id, chunk_index, chunk_text, embedding::vector
FROM json_to_recordset(:chunks_json) AS t(
chunk_index INT,
chunk_text TEXT,
embedding FLOAT[]
);
COMMIT;
전용 벡터 DB와 PostgreSQL의 경계
단일 스택이 모든 워크로드의 답은 아니다. 전용 벡터 DB와 PostgreSQL은 관리 방식, 비용, 확장성, 쿼리 특성에서 다른 선택지를 제공한다.
| 기준 | 전용 벡터 DB (Pinecone 등) | PostgreSQL + pgvector/pgvectorscale |
|---|---|---|
| 초기 성능 | 관리형 서비스로 즉시 고성능 | 튜닝 필요, 학습 곡선 존재 |
| 비용 (대규모) | 높음 ($3,000+/월) | 낮음 ($800+/월, 자체 호스팅) |
| 운영 복잡도 | 낮음 (완전 관리형) | 중간 (PostgreSQL 운영 경험 필요) |
| 데이터 일관성 | 별도 동기화 필요 | 트랜잭션 보장 |
| 수평 확장 | 용이 (관리형) | 제한적 (Citus, 읽기 복제본) |
| 실시간 업데이트 | 즉시 | 인덱스 재구축 오버헤드 |
| 멀티테넌트 | 네임스페이스 지원 | 파티셔닝 + RLS |
| 쿼리 유연성 | 벡터 검색에 특화 | SQL 전체 기능 활용 가능 |
수십억 벡터 이상의 초대규모 환경, 완전 관리형 서비스가 필요한 소규모 팀, 실시간 인덱스 업데이트가 핵심인 상황에서는 전용 벡터 DB가 유리하다. 기존 PostgreSQL 인프라가 있고 벡터 검색과 관계형 쿼리를 자주 결합하거나, 운영 비용과 복잡도를 줄이는 것이 우선이라면 PostgreSQL 단일 스택이 더 적합하다.
2025년 이후 Snowflake의 Crunchy Data 인수($250M), Databricks의 Neon 인수($1B), Supabase의 $100M Series E 투자는 PostgreSQL 생태계에 대한 대규모 베팅이다. 벡터는 특정 데이터베이스 타입이 아니라 기존 멀티모델 데이터베이스에 통합할 수 있는 하나의 데이터 타입이라는 인식도 산업 전반에 자리잡고 있다.
단일 스택을 검토할 시점
pgvector와 pgvectorscale은 PostgreSQL의 부가 기능을 넘어 데이터 아키텍처 선택지를 바꾼다. p95 레이턴시 28배 단축이라는 수치는 전용 벡터 데이터베이스의 성능 우위가 더 이상 자명하지 않다는 점을 보여준다.
StreamingDiskANN은 디스크 기반 인덱싱으로 수억 개 벡터를 처리하고, Statistical Binary Quantization은 정밀도 손실 없이 압축 효율을 높인다. OLTP, 벡터 검색, 전문 검색을 한 스택에서 처리해야 하는 새 AI/RAG 파이프라인이라면, 전용 벡터 DB를 도입하기 전에 PostgreSQL 단일 스택의 조건부터 비교할 만하다.
Sources
- Pgvector Is Now Faster than Pinecone at 75% Less Cost | Tiger Data
- pgvector vs Pinecone: cost and performance | Supabase
- GitHub - timescale/pgvectorscale: Postgres extension for vector search (DiskANN)
- Vector Database Comparison 2026: Pinecone vs pgvector vs Chroma vs Weaviate | Groovy Web
- PostgreSQL pgvector 0.8.0 Released! | PostgreSQL
- pgvector vs Pinecone: Which Vector Database to Choose in 2026 | Encore
- 6 data predictions for 2026: RAG is dead, what's old is new again | VentureBeat
- PostgreSQL Vector Search: VectorChord vs. pgvector vs. pgvectorscale | VectorChord Blog
- Vector Database Performance Compared: pgvector vs Pinecone vs Qdrant vs Weaviate | Vecstore
- PostgreSQL Vector Search Complete Guide 2026 | Calmops