pgVector: PostgreSQL을 벡터 데이터베이스로 전환
2026년에는 커뮤니티의 모토가 명확해졌습니다. "그냥 Postgres를 사용하세요". Snowflake가 Crunchy Data를 2억 5천만 달러에 인수, Databricks가 투자 네온은 10억 달러, 수파베이스는 50억 달러의 가치를 달성했습니다. PostgreSQL 아님 그리고 더 단순한 관계형 데이터베이스: pg벡터, 벡터 데이터베이스가 됩니다 추가하지 않고도 임베딩, 유사성 검색 및 AI 작업을 완벽하게 관리할 수 있습니다. 스택에 대한 단일 서비스.
이미 PostgreSQL을 사용하고 있다면(통계적으로도) Pinecone이 필요하지 않습니다. 벡터 검색을 시작하려면 Qdrant 또는 Weaviate를 이용하세요. 이 기사에서 우리는 처음부터 시작하는 완전한 벡터 검색 시스템: pgVector 설치부터 임베딩 생성 및 통합을 통한 최적화된 인덱스 생성 랭체인과 함께.
시리즈 개요
| # | Articolo | 집중하다 |
|---|---|---|
| 1 | 현재 위치 - pgVector | 설치, 운영자, 인덱싱 |
| 2 | 심층적인 임베딩 | 모델, 청킹, 차원 |
| 3 | PostgreSQL을 사용한 RAG | 엔드투엔드 RAG 파이프라인 |
| 4 | 하이브리드 검색 | 벡터 + 전체 텍스트 검색 |
| 5 | pgVector 스케일링 | 파티셔닝, 샤딩, 성능 |
| 6 | 프로덕션 중인 pg벡터 | 모니터링, 백업, CI/CD |
무엇을 배울 것인가
- pgVector는 무엇이며 2026년 가장 중요한 PostgreSQL 확장인 이유는 무엇입니까?
- Linux, Docker 및 관리형 서비스(Supabase, Neon, AWS RDS)에 pgVector를 설치하는 방법
- 벡터 열이 있는 테이블을 만들고 임베딩을 삽입하는 방법
- 세 가지 거리 연산자: 코사인, L2 및 내적
- 효과적인 유사성 검색 쿼리를 실행하는 방법
- Python으로 임베딩을 생성하는 방법(OpenAI 및 Sentence Transformers)
- HNSW vs IVFFlat: 선택할 인덱스 및 구성 방법
- 벤치마크 pgVector와 전용 벡터 데이터베이스
- Python을 사용한 완전한 엔드투엔드 예제
- RAG 시스템을 위한 LangChain과 통합
1. 2026년 "그냥 Postgres 사용" 트렌드
수년 동안 AI 세계는 Pinecone, Weaviate, Qdrant, Milvus. 각 RAG 프로젝트에는 관리, 모니터링 및 비용 지불을 위해 새로운 서비스가 필요한 것 같았습니다. 하지만 2025~2026년에는 뭔가가 급격하게 변했습니다.
커뮤니티는 내가 벡터는 데이터베이스 유형이 아닙니다, 하지만 데이터 유형. PostgreSQL이 JSON, 배열, 기하학 및 텍스트를 관리하는 것과 마찬가지로 전체 텍스트 검색을 사용하면 고차원 벡터도 처리할 수 있습니다. 확장자는 이 모든 것을 가능하게 해준다고 합니다 pg벡터.
2026년에 "그냥 Postgres를 사용"해야 하는 이유
| 요인 | 전용 벡터 데이터베이스 | PostgreSQL + pg벡터 |
|---|---|---|
| 하부 구조 | 관리할 수 있는 새로운 서비스 | 기존 DB로 확장 |
| 비용 | 별도 요금제(솔방울 월 $70부터) | PostgreSQL 비용에 포함됨 |
| 데이터 일관성 | DB 간 동기화 필요 | 네이티브 ACID 트랜잭션 |
| 쿼리 | 독점 API | 표준 SQL + JOIN, WHERE, GROUP BY |
| 백업 | 별도의 시스템 | pg_dump에는 모든 것이 포함되어 있습니다. |
| Team | 필요한 특정 기술 | SQL을 아시는 분 |
주요 장점은 운영 단순성. pgVector를 사용하면 임베딩이 가능합니다. 관계형 데이터와 동일한 테이블에 있습니다. 벡터와 메타데이터를 JOIN할 수 있습니다. 필터링을 위해 WHERE 절을 사용하고 트랜잭션 일관성을 유지합니다. 외부 서비스 없음 동기화, 배울 다른 API가 없습니다.
2. pg벡터란 무엇입니까?
pg벡터 지원을 추가하는 PostgreSQL용 오픈 소스 확장 고차원 벡터 및 유사성 검색에 기본입니다. 만든 사람 Andrew Kane 2021년에는 AI/ML 사용 사례를 위해 가장 많이 다운로드된 PostgreSQL 확장 프로그램이 되었습니다.
pgVector를 사용하면 다음을 수행할 수 있습니다.
- 벡터(임베딩)를 테이블 열의 기본 데이터 유형으로 저장
- 세 가지 다른 거리 측정법을 사용하여 유사성 검색 수행
- 빠른 검색을 위해 특수 인덱스(HNSW 및 IVFFlat) 생성
- PostgreSQL이 제공하는 모든 것(JOIN, 트랜잭션, 트리거, 구체화된 뷰)과 벡터 검색을 결합합니다.
숫자의 pg벡터(2026)
| 미터법 | Valore |
|---|---|
| 현재 버전 | 0.8.0+(반복 인덱스 스캔 포함) |
| 최대. 캐리어 크기 | 16,000 |
| 인덱스 유형 | HNSW, IVFF플랫 |
| 벡터 유형 | 벡터, halfvec, sparsevec, 비트 |
| 거리 측정법 | 코사인, L2(유클리드), 내적 |
| 지원 대상 | AWS RDS, Supabase, Neon, Google Cloud SQL, Azure |
| 특허 | PostgreSQL 라이선스(오픈 소스) |
2025년에 출시된 버전 0.8.0에는 핵심 기능인 gli가 도입되었습니다. 반복 인덱스 스캔. 이 기능은 과잉 필터링 문제를 해결합니다. 즉, 벡터 인덱스가 대부분의 이유로 충분한 결과를 반환하지 않는 경우입니다. WHERE 필터에 의해 삭제됩니다. 반복 스캔을 통해 pgVector는 계속해서 인덱스를 탐색합니다. 필터와 일치하는 충분한 결과를 찾을 때까지 필터링된 쿼리의 품질.
3. pg벡터 설치
pgVector는 환경에 따라 다른 방식으로 설치됩니다. 세 가지 접근 방식을 살펴보겠습니다. 주요 항목: Linux, Docker 및 관리형 서비스의 기본 설치.
3.1 우분투/데비안에 설치
# Prerequisiti: PostgreSQL 14+ già installato
sudo apt-get update
sudo apt-get install -y postgresql-server-dev-16
# Clona e compila pgvector
git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git
cd pgvector
make
sudo make install
# Abilita l'estensione nel tuo database
sudo -u postgres psql -d il_tuo_database -c "CREATE EXTENSION vector;"
PostgreSQL 17의 경우 교체 postgresql-server-dev-16 ~와 함께
postgresql-server-dev-17. pgVector는 버전 13부터 PostgreSQL을 지원합니다.
오후 5시에.
3.2 도커를 이용한 설치
시작하는 가장 빠른 방법. 공식 이미지 pgvector/pgvector
pgVector가 사전 설치된 PostgreSQL을 포함합니다.
# docker-compose.yml
version: '3.8'
services:
postgres:
image: pgvector/pgvector:pg17
environment:
POSTGRES_DB: vectordb
POSTGRES_USER: admin
POSTGRES_PASSWORD: secret_password
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
pgdata:
-- init.sql: eseguito automaticamente al primo avvio
CREATE EXTENSION IF NOT EXISTS vector;
# Avvio rapido senza docker-compose
docker run -d \
--name pgvector-db \
-e POSTGRES_DB=vectordb \
-e POSTGRES_PASSWORD=secret \
-p 5432:5432 \
pgvector/pgvector:pg17
# Connetti e abilita pgvector
docker exec -it pgvector-db psql -U postgres -d vectordb \
-c "CREATE EXTENSION vector;"
3.3 매니지드 서비스(제로 셋업)
인프라를 관리하고 싶지 않은 경우 여러 클라우드 서비스에서 PostgreSQL을 제공합니다. pgVector가 이미 활성화되었습니다. 이는 생산을 위한 이상적인 선택입니다.
pgVector를 사용한 관리형 서비스
| 서비스 | pg벡터 포함 | 무료 플랜 | 메모 |
|---|---|---|---|
| 슈퍼베이스 | 사전 설치됨 | 예(500MB) | 대시보드 UI, 자동 REST API |
| 네온 | 사전 설치됨 | 예(0.5GB) | 서버리스, 지점 데이터베이스 |
| AWS RDS | 활성화하려면 | No | Aurora PostgreSQL의 pgVector 0.8.0 |
| 구글 클라우드 SQL | 활성화하려면 | No | pg벡터 0.8.0 지원 |
| Azure 데이터베이스 | 활성화하려면 | No | pgVector를 사용한 유연한 서버 |
-- Su Supabase, pgvector e già disponibile.
-- Basta abilitare l'estensione:
CREATE EXTENSION IF NOT EXISTS vector;
-- Verifica l'installazione
SELECT extversion FROM pg_extension WHERE extname = 'vector';
-- Risultato: 0.8.0
4. 벡터가 포함된 표 만들기
pgVector를 설치하면 유형 열을 추가할 수 있습니다. vector(n) 당신에게
테이블, 어디에 n 그리고 벡터의 차원. 가치 n
사용하는 임베딩 모델에 따라 다릅니다. OpenAI text-embedding-3-small 생산하다
1536개의 차원 벡터, text-embedding-3-large 3072까지 올라갑니다.
-- Abilita l'estensione (se non già fatto)
CREATE EXTENSION IF NOT EXISTS vector;
-- Tabella documenti per un sistema RAG
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
title VARCHAR(500) NOT NULL,
content TEXT NOT NULL,
source VARCHAR(255),
category VARCHAR(100),
embedding vector(1536),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Aggiungi un commento alla colonna per documentazione
COMMENT ON COLUMN documents.embedding IS
'Embedding generato con OpenAI text-embedding-3-small (1536 dim)';
포함된 문서 삽입
삽입은 일반적인 INSERT처럼 작동하며 벡터를 값의 문자열로 전달합니다. 대괄호 안의 쉼표로 구분됩니다.
-- Inserimento singolo
INSERT INTO documents (title, content, source, embedding)
VALUES (
'Introduzione a PostgreSQL',
'PostgreSQL e un database relazionale open-source potente e affidabile...',
'docs/postgres-intro.md',
'[0.023, -0.045, 0.067, 0.089, -0.012, ...]' -- vettore a 1536 dimensioni
);
-- Inserimento multiplo (batch)
INSERT INTO documents (title, content, source, category, embedding)
VALUES
('Capitolo 1', 'Contenuto cap 1...', 'libro.pdf', 'tutorial',
'[0.11, -0.22, 0.33, ...]'),
('Capitolo 2', 'Contenuto cap 2...', 'libro.pdf', 'tutorial',
'[0.44, -0.55, 0.66, ...]'),
('FAQ', 'Domande frequenti...', 'faq.md', 'supporto',
'[-0.12, 0.34, -0.56, ...]');
벡터 크기
열 정의에 지정된 차원(vector(1536))
삽입하는 임베딩의 크기와 정확히 일치해야 합니다. 시도
768차원 벡터를 열에 삽입하려면 vector(1536) 일으킬 것이다
오류. 사용하려는 임베딩 템플릿에 따라 크기를 선택하세요.
인기 있는 임베딩 모델의 차원
| 모델 | 공급자 | 치수 | 비용 / 100만 토큰 |
|---|---|---|---|
| 텍스트 삽입-3-작은 | 오픈AI | 1536년 | $0.02 |
| 텍스트 삽입-3-대형 | 오픈AI | 3072 | $0.13 |
| 모든-MiniLM-L6-v2 | 포옹얼굴(무료) | 384 | 무료(현지) |
| 모든 mpnet-base-v2 | 포옹얼굴(무료) | 768 | 무료(현지) |
| 항해-3 | 항해 AI | 1024 | $0.06 |
5. 거리 연산자
pgVector는 벡터 사이의 거리를 계산하는 세 가지 연산자를 제공합니다. 모든 운영자 다른 수학적 측정항목에 해당하며 특정 사용 사례가 있습니다.
세 명의 연산자 pgVector
| 연산자 | 미터법 | 공식 | 정렬 | 사용 사례 |
|---|---|---|---|---|
<=> |
코사인 거리 | 1 - 코사인_유사성 | ASC(0 = 동일) | 텍스트, 정규화된 임베딩 |
<-> |
L2(유클리드) | sqrt(합((a-b)^2)) | ASC(0 = 동일) | 이미지, 공간 데이터 |
<#> |
내부 제품(거부됨) | -1 * 도트_제품 | ASC(음수가 많을수록 유사함) | 정규화된 벡터, 최대 성능 |
-- COSINE DISTANCE <=> (il più usato per testo)
-- Risultato: 0 = identici, 2 = opposti
SELECT title, content,
embedding <=> '[0.1, 0.2, ...]' AS cosine_distance
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]' ASC
LIMIT 5;
-- L2 (EUCLIDEA) <->
-- Risultato: 0 = identici, valori crescenti = più lontani
SELECT title, content,
embedding <-> '[0.1, 0.2, ...]' AS l2_distance
FROM documents
ORDER BY embedding <-> '[0.1, 0.2, ...]' ASC
LIMIT 5;
-- INNER PRODUCT (NEGATO) <#>
-- Risultato: valori più negativi = più simili
SELECT title, content,
(embedding <#> '[0.1, 0.2, ...]') * -1 AS similarity
FROM documents
ORDER BY embedding <#> '[0.1, 0.2, ...]' ASC
LIMIT 5;
선택할 연산자
텍스트 및 AI 사용 사례의 90%에 대해 다음을 사용합니다. <=> (코사인 거리).
OpenAI와 같은 임베딩 모델은 정규화된 벡터를 생성합니다.
코사인 거리와 내적은 결과 측면에서 동일합니다. 미국 <->
(L2) 벡터 크기가 중요한 공간 데이터 또는 이미지로 작업하는 경우에만 해당됩니다.
내부곱(<#>) 방지하기 때문에 코사인보다 약간 빠릅니다.
정규화는 이미 정규화된 벡터에서만 가능합니다.
6. 유사성 검색 쿼리
유사성 검색은 pgVector의 핵심입니다. 기본 쿼리는 간단합니다. 결과를 정렬합니다. 쿼리 벡터와의 거리를 기준으로 첫 번째 K를 얻습니다. 그러나 프로덕션에서는 쿼리가 벡터 검색과 SQL 필터를 결합하여 더욱 정교해졌습니다.
6.1 기본 쿼리
-- Trova i 5 documenti più simili a un vettore query
SELECT
id,
title,
content,
1 - (embedding <=> $1) AS similarity -- $1 = vettore query
FROM documents
ORDER BY embedding <=> $1
LIMIT 5;
6.2 필터를 사용한 쿼리(pgVector의 진정한 힘)
여기서 pgVector는 전용 벡터 데이터베이스와 비교하여 빛납니다. 검색을 결합할 수 있습니다. SQL 절이 있는 벡터: WHERE, JOIN, GROUP BY, 하위 쿼리.
-- Filtra per categoria e soglia di similarità
SELECT
id, title, content,
1 - (embedding <=> $1) AS similarity
FROM documents
WHERE category = 'tutorial'
AND created_at > NOW() - INTERVAL '30 days'
ORDER BY embedding <=> $1
LIMIT 5;
-- JOIN con altre tabelle: trova documenti simili con info autore
SELECT
d.title,
d.content,
a.name AS author_name,
1 - (d.embedding <=> $1) AS similarity
FROM documents d
JOIN authors a ON d.author_id = a.id
WHERE a.verified = true
ORDER BY d.embedding <=> $1
LIMIT 10;
-- Esclusione: trova simili ma NON il documento stesso
SELECT
id, title,
1 - (embedding <=> (SELECT embedding FROM documents WHERE id = 42)) AS similarity
FROM documents
WHERE id != 42
ORDER BY embedding <=> (SELECT embedding FROM documents WHERE id = 42)
LIMIT 5;
6.3 반복 인덱스 스캔(pgVector 0.8.0)
버전 0.8.0의 가장 중요한 새로운 기능 중 하나는 반복 인덱스 스캔. 벡터 검색을 WHERE 필터와 결합하는 경우 제한적이므로 인덱스는 첫 번째 패스에서 충분한 적중을 찾지 못할 수 있습니다. 반복 스캔을 사용하면 pgVector는 만족될 때까지 인덱스를 계속 스캔합니다. 요청한 LIMIT.
-- Abilita iterative scan per HNSW
SET hnsw.iterative_scan = relaxed_order; -- o strict_order
-- Imposta il limite massimo di tuple da scansionare
SET hnsw.max_scan_tuples = 20000;
-- Ora le query con filtri restrittivi funzionano correttamente
SELECT id, title,
1 - (embedding <=> $1) AS similarity
FROM documents
WHERE category = 'raro' -- categoria con pochi documenti
ORDER BY embedding <=> $1
LIMIT 10;
-- Senza iterative scan: potrebbe restituire 0-3 risultati
-- Con iterative scan: restituisce sempre fino a 10 risultati
-- Modalità disponibili:
-- off = comportamento tradizionale (default)
-- strict_order = mantiene l'ordine esatto delle distanze
-- relaxed_order = ordine approssimato (migliori performance)
반복 스캔을 사용해야 하는 경우
- 편안한_순서: 대부분의 경우 성능과 품질 간의 최상의 균형을 제공합니다.
- 엄격한 순서: 정확한 거리 순서가 중요한 경우(예: 사용자에 대한 결과 순위)
- 끄다: WHERE 필터가 없거나 필터가 제한적이지 않은 경우
7. Python으로 임베딩 생성
pgVector에 데이터를 입력하려면 먼저 다음을 사용하여 텍스트를 숫자형 벡터로 변환해야 합니다. 임베딩 모델. OpenAI API(유료, 고품질)라는 두 가지 접근 방식을 살펴보겠습니다. 및 문장 변환기(무료, 로컬).
7.1 OpenAI API 사용
import openai
import psycopg2
from psycopg2.extras import execute_values
# Configura il client OpenAI
client = openai.OpenAI(api_key="sk-...")
def get_embedding(text: str, model: str = "text-embedding-3-small") -> list[float]:
"""Genera un embedding per un testo usando OpenAI."""
response = client.embeddings.create(
input=text,
model=model
)
return response.data[0].embedding # lista di 1536 float
# Connetti a PostgreSQL
conn = psycopg2.connect(
host="localhost",
database="vectordb",
user="admin",
password="secret_password"
)
cur = conn.cursor()
# Genera e inserisci embeddings
documents = [
("Introduzione a Python", "Python e un linguaggio di programmazione versatile..."),
("PostgreSQL Avanzato", "Le CTE ricorsive permettono di eseguire query gerarchiche..."),
("Docker per Sviluppatori", "I container Docker isolano le applicazioni..."),
]
for title, content in documents:
embedding = get_embedding(content)
cur.execute(
"INSERT INTO documents (title, content, embedding) VALUES (%s, %s, %s)",
(title, content, str(embedding))
)
conn.commit()
cur.close()
conn.close()
7.2 문장 변환기 사용(무료 및 로컬)
from sentence_transformers import SentenceTransformer
import psycopg2
import numpy as np
# Carica il modello (scaricato automaticamente la prima volta)
model = SentenceTransformer('all-MiniLM-L6-v2') # 384 dimensioni
# Genera embeddings per un batch di testi
texts = [
"Python e un linguaggio di programmazione versatile",
"Le CTE ricorsive permettono query gerarchiche in SQL",
"I container Docker isolano le applicazioni",
]
embeddings = model.encode(texts) # shape: (3, 384)
# Connetti e inserisci
conn = psycopg2.connect(
host="localhost", database="vectordb",
user="admin", password="secret_password"
)
cur = conn.cursor()
# NOTA: la colonna deve essere vector(384), non vector(1536)
for text, embedding in zip(texts, embeddings):
cur.execute(
"INSERT INTO documents (title, content, embedding) VALUES (%s, %s, %s)",
(text[:100], text, str(embedding.tolist()))
)
conn.commit()
cur.close()
conn.close()
OpenAI와 문장 변환기
| 나는 기다린다 | 오픈AI API | 문장 변환기 |
|---|---|---|
| 비용 | $0.02 / 100만 토큰 | 무료 |
| 품질 | 우수함(최신 기술) | 좋음(많은 경우에 충분함) |
| 은둔 | OpenAI로 전송된 데이터 | 모두 로컬이며 데이터가 나가지 않습니다. |
| 속도 | 요청당 ~100ms(네트워크) | 텍스트의 경우 ~10ms(GPU 사용) |
| 오프라인 | 아니요(인터넷 필요) | 예(처음 다운로드 후) |
| 치수 | 1536 또는 3072 | 384 또는 768(모델에 따라 다름) |
임베딩의 황금률
그것을 사용 동일한 임베딩 모델 문서 색인화와
쿼리 벡터를 생성합니다. 다양한 모델로 생성된 임베딩은
벡터 공간이 다르므로 비교할 수 없습니다. 색인을 생성하면
text-embedding-3-small, 동일한 모델로 검색해야 합니다.
8. 인덱싱: HNSW 대 IVFFlat
인덱스가 없으면 pgVector는 비교를 통해 순차(무차별) 스캔을 수행합니다. 테이블의 각 행에 대한 쿼리 벡터입니다. 이것은 100% 정확하지만 대규모 데이터 세트에서는 속도가 느립니다. ANN(Approximate Nearest Neighbor) 인덱스 희생 훨씬 더 빠른 검색을 얻기 위한 최소 정밀도 비율입니다.
8.1 HNSW 지수
HNSW(Hierarchical Navigable Small World)는 다단계 연결 그래프를 구축합니다. 통신사 간. 그리고 대부분의 경우 권장되는 색인은 빠른 읽기, 정확도가 높으며 재구성 없이 증분 삽입을 지원합니다.
-- Indice HNSW con parametri di default
CREATE INDEX idx_documents_embedding_hnsw
ON documents
USING hnsw (embedding vector_cosine_ops);
-- Indice HNSW con parametri personalizzati
CREATE INDEX idx_documents_embedding_hnsw
ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (
m = 24, -- connessioni per nodo (default: 16, range: 2-100)
ef_construction = 128 -- candidati durante costruzione (default: 64, range: 4-1000)
);
-- Regola ef_search per le query (default: 40)
SET hnsw.ef_search = 100; -- più alto = più preciso ma più lento
HNSW 매개변수: 구성 가이드
| 매개변수 | 기본 | 범위 | 효과 | 권하다 |
|---|---|---|---|---|
m |
16 | 2 - 100 | 더 많은 연결 = 더 정확하고 더 많은 메모리 | 대부분의 경우 16-32 |
ef_construction |
64 | 4 - 1000 | 높음 = 더 나은 인덱스, 느린 빌드 | 64-256 (일회성, 올릴 가치가 있음) |
ef_search |
40 | 1 - 1000 | 높음 = 더 정확하고 느린 검색 | 원하는 절충안을 기준으로 40-200 |
8.2 IVFFFlat 지수
IVFFlat(Inverted File with Flat 압축)은 벡터를 클러스터로 나누고 검색만 합니다. 쿼리에 가장 가까운 클러스터에 있습니다. HNSW보다 구축 속도가 빠르지만 새로운 데이터를 많이 추가하면 재구성됩니다. 데이터 세트 변경에 이상적 드물게.
-- IMPORTANTE: IVFFlat richiede dati nella tabella PRIMA di creare l'indice
-- (necessità di fare clustering k-means sui dati esistenti)
-- Indice IVFFlat
CREATE INDEX idx_documents_embedding_ivf
ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (
lists = 100 -- numero di cluster (default: 100)
);
-- Regola il numero di cluster da esplorare durante la ricerca
SET ivfflat.probes = 10; -- default: 1, consigliato: sqrt(lists)
-- Regola pratica per "lists":
-- rows < 1M: lists = rows / 1000
-- rows >= 1M: lists = sqrt(rows)
8.3 거리 유형별 연산자
인덱스 생성에 지정된 연산자는 연산자와 일치해야 합니다. 쿼리에 사용됩니다. 전체 지도는 다음과 같습니다.
지도 연산자 및 색인 클래스
| 거리 | SQL 연산자 | 인덱스 클래스(앗) |
|---|---|---|
| 작은 것들 | <=> |
vector_cosine_ops |
| L2(유클리드) | <-> |
vector_l2_ops |
| 내부 제품 | <#> |
vector_ip_ops |
8.4 HNSW 대 IVFFlat: 무엇을 선택할 것인가
HNSW와 IVFFlat 비교
| 나는 기다린다 | HNSW | IVFF플랫 |
|---|---|---|
| 검색 속도 | 더 빠르게 | 빠른 |
| 정확성(재현율) | ~95-99% | ~90-98% |
| 빌드 시간 | 느린 | 빠른 |
| 메모리 | 높은 | 평균 |
| 증분 삽입 | 지원됨 | REINDEX가 필요합니다. |
| 반복 스캔 | 예(0.8.0) | 예(0.8.0) |
| 이상적인 사용 사례 | 일반 용도, 데이터 증가 | 정적 데이터세트, 빠른 구축 |
실용적인 조언
대부분의 프로젝트의 경우, HNSW를 선택하세요. 더욱 다양한 기능을 지원합니다. 재구축 없이 증분 삽입이 가능하며 pgVector 버전 0.8.0에는 성능이 크게 향상되었습니다. 다음과 같은 경우에만 IVFFlat을 사용하십시오. 인덱스 구성 및 중요(매우 큰 데이터 세트는 한 번만 로드됨) o 엄격한 메모리 제약이 있는 경우.
9. 성능: pgVector 대 전용 벡터 데이터베이스
가장 자주 묻는 질문은 "pgVector가 프로덕션에 충분히 빠른가요?"입니다. 대답 2026년에는 분명 si, 대부분의 사용 사례에 대해. 숫자를 봅시다.
9.1 대규모 벤치마크
pgVectorscale 벤치마크(Timescale에서 개발한 pgVector에 대한 보완 확장) 5천만 개의 통신업체 중 인상적인 결과를 보여줍니다.
벤치마크: 99% 재현율의 5천만 벡터
| 체계 | QPS(쿼리/초) | 상기하다 | 메모 |
|---|---|---|---|
| pg벡터스케일 | 471 | 99% | Qdrant보다 11.4배 빠름 |
| Qdrant | 41 | 99% | 순수 벡터 검색에 최적화됨 |
9.2 중간 규모 벤치마크(1M 벡터)
벤치마크: 1M 벡터 - 처리량
| 체계 | 쿼리/초 | 삽입/초 | 관리 비용 |
|---|---|---|---|
| 솔방울 | ~5,000 | ~50,000 | 월 $70부터 |
| Qdrant | ~4,500 | ~45,000 | 자체 호스팅 또는 클라우드 |
| pg벡터 | ~3,000 | ~30,000 | PG비용에 포함 |
1M 벡터에서 pgVector는 순수 처리량 측면에서 약간 느립니다. 하지만 고려해보면 비용은 거의 0이며 (이미 PostgreSQL에 포함되어 있음) 보고서는 품질 가격과 탁월한. 대부분의 웹 애플리케이션의 경우 쿼리 3,000개 초당 충분합니다.
pgVector가 충분하지 않은 경우
다음과 같은 경우 전용 벡터 데이터베이스(Qdrant, Pinecone)를 고려하십시오.
- 당신은 끝났습니다 5천만 벡터의
- i 아래에는 p99 대기 시간이 필요합니다. 5ms
- 귀하의 작업은 오로지 벡터 검색입니다(관계형 데이터 없음).
- 기본 분산 샤딩이 필요합니다.
다른 모든 것에는 pgVector가 올바른 선택입니다. 1,000만 개 미만의 벡터가 있는 시스템 PostgreSQL이 이미 스택에 있으면 추가적인 복잡성이 필요하지 않습니다.
10. 전체 예: Python을 사용한 기술 자료
실제 사례를 통해 모든 것을 정리해보자. 우리는 다음과 같은 지식 기반을 구축할 것입니다. 임베딩이 포함된 문서 색인을 생성하고 유사성 검색을 허용하며 필터를 지원합니다. 카테고리별로.
"""
Knowledge Base con PostgreSQL + pgvector
Requisiti: pip install openai psycopg2-binary
"""
import openai
import psycopg2
from dataclasses import dataclass
# === Configurazione ===
OPENAI_API_KEY = "sk-..."
DB_CONFIG = {
"host": "localhost",
"database": "vectordb",
"user": "admin",
"password": "secret_password",
}
EMBEDDING_MODEL = "text-embedding-3-small"
EMBEDDING_DIM = 1536
@dataclass(frozen=True)
class SearchResult:
id: int
title: str
content: str
similarity: float
category: str
# === Funzioni di embedding ===
client = openai.OpenAI(api_key=OPENAI_API_KEY)
def get_embedding(text: str) -> list[float]:
"""Genera un embedding per un testo."""
response = client.embeddings.create(
input=text,
model=EMBEDDING_MODEL,
)
return response.data[0].embedding
def get_embeddings_batch(texts: list[str]) -> list[list[float]]:
"""Genera embeddings per un batch di testi (più efficiente)."""
response = client.embeddings.create(
input=texts,
model=EMBEDDING_MODEL,
)
return [item.embedding for item in response.data]
# === Setup del database ===
def setup_database() -> None:
"""Crea la tabella e gli indici."""
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
cur.execute("CREATE EXTENSION IF NOT EXISTS vector;")
cur.execute(f"""
CREATE TABLE IF NOT EXISTS kb_documents (
id BIGSERIAL PRIMARY KEY,
title VARCHAR(500) NOT NULL,
content TEXT NOT NULL,
category VARCHAR(100) DEFAULT 'general',
embedding vector({EMBEDDING_DIM}),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_kb_embedding_hnsw
ON kb_documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 24, ef_construction = 128);
""")
cur.execute("""
CREATE INDEX IF NOT EXISTS idx_kb_category
ON kb_documents (category);
""")
conn.commit()
cur.close()
conn.close()
print("Database setup completato.")
# === Inserimento documenti ===
def insert_documents(
documents: list[dict],
batch_size: int = 50,
) -> None:
"""Inserisce documenti con embeddings generati automaticamente."""
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
for i in range(0, len(documents), batch_size):
batch = documents[i : i + batch_size]
texts = [doc["content"] for doc in batch]
embeddings = get_embeddings_batch(texts)
for doc, emb in zip(batch, embeddings):
cur.execute(
"""INSERT INTO kb_documents (title, content, category, embedding)
VALUES (%s, %s, %s, %s)""",
(doc["title"], doc["content"],
doc.get("category", "general"), str(emb)),
)
print(f"Inseriti {min(i + batch_size, len(documents))}/{len(documents)} documenti")
conn.commit()
cur.close()
conn.close()
# === Ricerca per similarità ===
def search(
query: str,
limit: int = 5,
category: str | None = None,
min_similarity: float = 0.3,
) -> list[SearchResult]:
"""Cerca documenti simili alla query."""
query_embedding = get_embedding(query)
conn = psycopg2.connect(**DB_CONFIG)
cur = conn.cursor()
# Abilita iterative scan per filtri restrittivi
cur.execute("SET hnsw.iterative_scan = relaxed_order;")
if category:
cur.execute(
"""SELECT id, title, content, category,
1 - (embedding <=> %s::vector) AS similarity
FROM kb_documents
WHERE category = %s
ORDER BY embedding <=> %s::vector
LIMIT %s""",
(str(query_embedding), category,
str(query_embedding), limit),
)
else:
cur.execute(
"""SELECT id, title, content, category,
1 - (embedding <=> %s::vector) AS similarity
FROM kb_documents
ORDER BY embedding <=> %s::vector
LIMIT %s""",
(str(query_embedding), str(query_embedding), limit),
)
results = [
SearchResult(
id=row[0], title=row[1], content=row[2],
category=row[3], similarity=row[4],
)
for row in cur.fetchall()
if row[4] >= min_similarity
]
cur.close()
conn.close()
return results
# === Main ===
if __name__ == "__main__":
# 1. Setup
setup_database()
# 2. Inserisci documenti di esempio
sample_docs = [
{
"title": "Introduzione a PostgreSQL",
"content": "PostgreSQL e un RDBMS open-source con supporto ACID completo.",
"category": "database",
},
{
"title": "Indici in PostgreSQL",
"content": "I B-tree sono il tipo di indice default. HNSW e usato per vettori.",
"category": "database",
},
{
"title": "Cos'è il RAG",
"content": "RAG combina retrieval e generation per risposte basate su documenti.",
"category": "ai",
},
{
"title": "Docker per Sviluppatori",
"content": "Docker isola le applicazioni in container leggeri e portabili.",
"category": "devops",
},
{
"title": "Embeddings e Vector Search",
"content": "Gli embeddings trasformano testo in vettori per la similarity search.",
"category": "ai",
},
]
insert_documents(sample_docs)
# 3. Cerca documenti
print("\n--- Ricerca: 'come funzionano i database vettoriali' ---")
results = search("come funzionano i database vettoriali", limit=3)
for r in results:
print(f" [{r.similarity:.3f}] {r.title} ({r.category})")
print("\n--- Ricerca filtrata per categoria 'ai' ---")
results = search("tutorial su PostgreSQL", limit=3, category="ai")
for r in results:
print(f" [{r.similarity:.3f}] {r.title} ({r.category})")
11. LangChain과의 통합
RAG 시스템을 구축하는 경우 LangChain은 pgVector와의 직접 통합을 제공합니다.
패키지를 통해 langchain-postgres. 이를 통해 다음을 사용할 수 있습니다.
SQL을 수동으로 작성하지 않고 벡터 저장소로 PostgreSQL을 사용합니다.
pip install langchain-postgres langchain-openai psycopg
from langchain_postgres import PGVector
from langchain_openai import OpenAIEmbeddings
from langchain_core.documents import Document
# Configura il modello di embedding
embeddings = OpenAIEmbeddings(
model="text-embedding-3-small",
openai_api_key="sk-...",
)
# NOTA: langchain-postgres usa psycopg3 (non psycopg2)
CONNECTION_STRING = "postgresql+psycopg://admin:secret@localhost:5432/vectordb"
# Crea il vector store
vector_store = PGVector(
embeddings=embeddings,
collection_name="langchain_docs",
connection=CONNECTION_STRING,
use_jsonb=True, # metadati JSONB per filtri efficienti
)
# Aggiungi documenti
docs = [
Document(
page_content="pgvector trasforma PostgreSQL in un vector database",
metadata={"source": "tutorial.md", "chapter": 1},
),
Document(
page_content="HNSW e l'indice consigliato per la maggior parte dei casi",
metadata={"source": "tutorial.md", "chapter": 2},
),
Document(
page_content="LangChain semplifica la costruzione di sistemi RAG",
metadata={"source": "guida-rag.md", "chapter": 1},
),
]
vector_store.add_documents(docs)
# Ricerca per similarità
results = vector_store.similarity_search(
"come creare un indice vettoriale",
k=3,
)
for doc in results:
print(f"[{doc.metadata['source']}] {doc.page_content[:80]}...")
# Ricerca con score
results_with_scores = vector_store.similarity_search_with_score(
"cos'è pgvector",
k=3,
)
for doc, score in results_with_scores:
print(f"[Score: {score:.4f}] {doc.page_content[:80]}...")
# Usa come retriever in una catena RAG
retriever = vector_store.as_retriever(
search_type="similarity",
search_kwargs={"k": 5},
)
# Il retriever può essere usato direttamente nelle chain LangChain
relevant_docs = retriever.invoke("installazione pgvector docker")
psycopg3에 대한 참고 사항
패키지 langchain-postgres 필요하다 정신병자3 (psychopg2 아님).
연결 문자열은 다음 형식을 사용해야 합니다. postgresql+psycopg:// 대신
의 postgresql+psycopg2://. 다음에서 이주하는 경우 langchain-community,
연결 문자열을 업데이트합니다.
12. 프로덕션에서 pgVector에 대한 모범 사례
12.1 벡터 크기
벡터가 작을수록 공간을 덜 차지하고 인덱스 속도가 빨라지며 비용이 절감됩니다.
오픈AI text-embedding-3-small (1536 희미) 최고의 가치를 제공합니다
대부분의 경우 품질 크기. 약간의 손실을 감수할 수 있다면
품질, all-MiniLM-L6-v2 (384 어두움) 그리고 훌륭한 선택이 가능합니다.
12.2 일괄 삽입
from psycopg2.extras import execute_values
# SBAGLIATO: un INSERT alla volta (lento)
for doc in documents:
cur.execute("INSERT INTO docs (content, embedding) VALUES (%s, %s)",
(doc.content, str(doc.embedding)))
# CORRETTO: batch insert con execute_values (10-50x più veloce)
data = [
(doc.content, str(doc.embedding))
for doc in documents
]
execute_values(
cur,
"INSERT INTO docs (content, embedding) VALUES %s",
data,
page_size=500, # righe per batch SQL
)
conn.commit()
12.3 연결 풀링
프로덕션에서는 각 요청에 대해 새 PostgreSQL 연결을 열지 마십시오.
다음과 같은 연결 풀을 사용하십시오. PgBouncer 또는 통합 풀링
psycopg2.
from psycopg2 import pool
# Crea un pool di connessioni (all'avvio dell'applicazione)
connection_pool = pool.ThreadedConnectionPool(
minconn=5, # connessioni minime
maxconn=20, # connessioni massime
host="localhost",
database="vectordb",
user="admin",
password="secret_password",
)
# Usa una connessione dal pool
conn = connection_pool.getconn()
try:
cur = conn.cursor()
cur.execute("SELECT ... ORDER BY embedding <=> %s LIMIT 5", ...)
results = cur.fetchall()
cur.close()
finally:
connection_pool.putconn(conn) # restituisci al pool
12.4 유지보수
-- VACUUM per recuperare spazio dopo DELETE/UPDATE
VACUUM ANALYZE documents;
-- Ricostruisci l'indice IVFFlat dopo inserimenti massicci
REINDEX INDEX CONCURRENTLY idx_documents_embedding_ivf;
-- NOTA: HNSW non richiede REINDEX per nuovi inserimenti
-- Monitora la dimensione dell'indice
SELECT
indexname,
pg_size_pretty(pg_relation_size(indexname::regclass)) AS size
FROM pg_indexes
WHERE tablename = 'documents';
-- Verifica che l'indice venga usato
EXPLAIN ANALYZE
SELECT id, 1 - (embedding <=> '[0.1, 0.2, ...]') AS similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 5;
-- Cerca "Index Scan using idx_..._hnsw" nell'output
생산 체크리스트
- 다음을 사용하여 HNSW 인덱스를 생성합니다.
m = 24eef_construction = 128 - Imposta
ef_search대기 시간/정밀도 균형을 기준으로 40~200 사이 - 능력
hnsw.iterative_scan = relaxed_orderWHERE 필터를 사용하는 경우 - 다음과 함께 일괄 삽입을 사용하세요.
execute_values대용량 부하용 - 연결 풀 설정(PgBouncer 또는 psycopg2.pool)
- 일정
VACUUM ANALYZE주기적 - 다음을 사용하여 쿼리를 모니터링합니다.
EXPLAIN ANALYZE인덱스 사용을 확인하기 위해 - 미국
halfvec대신에vector50% 공간 절약(float16 정밀도가 충분한 경우)
결론
pgVector는 PostgreSQL을 단순한 관계형 데이터베이스에서 AI 지원 플랫폼으로 전환했습니다. 버전 0.8.0과 반복 인덱스 스캔을 통해 벡터 데이터베이스와의 격차 전용 비용이 대폭 감소했으며 대부분의 프로젝트에서 1,000만 개 미만 통신사의 경우 스택에 별도의 서비스를 추가할 이유가 없습니다.
이 기사에서는 pgVector를 설치하는 방법, 벡터 열이 있는 테이블을 만드는 방법, 세 가지 거리 연산자로 유사성 검색을 수행하고 Python으로 임베딩을 생성합니다. HNSW 및 IVFFlat 인덱스를 설정하고 모든 것을 LangChain과 통합합니다. 당신도 본 적이 있나요? 프로덕션에서 pgVector의 성능을 확인하는 벤치마크입니다.
에서 다음 기사 우리는 그들에 대해 더 깊이 탐구할 것입니다 임베딩: 내부적으로 작동하는 방법, 올바른 모델을 선택하는 방법, 청킹 전략 긴 문서의 경우 검색 품질을 최적화하는 방법을 알아보세요. 에서 세 번째 기사 우리가 하나 만들 거야 RAG 파이프라인 완료 PostgreSQL을 유일한 백엔드로 사용합니다.
추가 리소스
- pgVector GitHub: github.com/pgVector/pgVector - 공식 문서 및 변경 로그
- pg벡터스케일: github.com/timescale/pgVectorscale - 향상된 성능 확장
- LangChain PG벡터: python.langchain.com - 공식 Python 통합
- 초기본 벡터: supabase.com/docs/guides/ai - Supabase의 pgVector 가이드
- 네온 AI: neo.tech/docs/ai - Neon 서버리스의 pgVector







