pgvector: PostgreSQL의 임베딩
PostgreSQL에서 pgvector 확장을 활성화하고, 벡터 열이 있는 테이블을 만들며, 임베딩을 삽입하고, 코사인 거리 연산자로 최근접 이웃 질의를 실행합니다.
pgvector: PostgreSQL의 임베딩은(는) CoddyKit의 무료 AI Engineering Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 AI Engineering Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
pgvector: PostgreSQL의 벡터 검색
pgvector는 vector 데이터 유형과 유사도 검색 연산자를 추가하는 오픈 소스 PostgreSQL 확장 기능입니다. 이미 운영 중인 동일한 데이터베이스에 일반 애플리케이션 데이터와 함께 임베딩을 저장할 수 있으므로 별도의 벡터 저장소가 필요하지 않습니다.
이미 PostgreSQL을 사용하고 있으며 새로운 인프라 의존성을 추가하지 않고 의미 검색을 도입하려는 팀에 적합합니다.
pgvector 확장 기능 활성화
공식 저장소에서 pgvector를 설치하거나, pgvector가 사전 설치된 관리형 PostgreSQL 제공업체(Supabase, Neon, AWS RDS, Render)를 사용하세요. 그런 다음 단일 SQL 명령으로 데이터베이스에서 활성화하면 됩니다. 재시작할 필요는 없습니다.
-- Run this once per database to enable the extension
CREATE EXTENSION IF NOT EXISTS vector;
-- Verify it's installed
SELECT extname, extversion
FROM pg_extension
WHERE extname = 'vector';
-- Returns: vector | 0.7.0 (or similar)벡터 열이 있는 테이블 만들기
임베딩 차원을 나타내는 n을 사용하여 vector(n)을 지정하면 벡터 열을 추가할 수 있습니다. 메타데이터를 저장하는 일반 PostgreSQL 열과 함께 사용할 수도 있으므로, 표준 SQL WHERE 절을 사용해 user_id, created_at 또는 다른 모든 필드로 필터링할 수 있습니다.
CREATE TABLE documents (
id BIGSERIAL PRIMARY KEY,
content TEXT NOT NULL,
category TEXT,
created_at TIMESTAMPTZ DEFAULT NOW(),
embedding vector(1536) -- must match your model dimension
);
-- Index on category for fast metadata filtering
CREATE INDEX ON documents (category);
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'documents';Python에서 임베딩 삽입하기
psycopg2 또는 asyncpg 드라이버를 사용하여 임베딩이 포함된 행을 삽입하세요. Python의 실수 목록을 '[0.1, 0.2, ...]' 형식의 문자열로 변환하면 pgvector가 올바르게 구문 분석합니다. pgvector Python 패키지는 이 작업을 자동으로 처리하는 register_vector 도우미를 제공합니다.
import psycopg2
from pgvector.psycopg2 import register_vector
from openai import OpenAI
conn = psycopg2.connect('postgresql://user:pass@localhost/mydb')
register_vector(conn)
cur = conn.cursor()
client = OpenAI()
document = 'pgvector adds vector search to PostgreSQL.'
resp = client.embeddings.create(model='text-embedding-3-small', input=document)
embedding = resp.data[0].embedding
cur.execute(
'INSERT INTO documents (content, category, embedding) VALUES (%s, %s, %s)',
(document, 'database', embedding)
)
conn.commit()
print('Inserted document with embedding')<=> 연산자를 사용한 코사인 유사도
pgvector는 세 가지 거리 연산자를 추가합니다.
<=>— 코사인 거리(1 - cosine_similarity)<->— 유클리드(L2) 거리<#>— 음의 내적(dot product 유사도에 사용)
텍스트 임베딩에는 <=>(코사인 거리)를 사용하세요. ORDER BY distance ASC는 가장 유사한 문서부터 반환합니다.
-- Find top 5 documents most similar to a query embedding
-- Replace '[0.1, 0.2, ...]' with the actual query vector
SELECT
id,
content,
category,
1 - (embedding <=> '[0.1, 0.2, 0.3]'::vector) AS cosine_similarity
FROM documents
ORDER BY embedding <=> '[0.1, 0.2, 0.3]'::vector
LIMIT 5;벡터 검색과 SQL 필터 결합하기
pgvector의 가장 큰 장점 중 하나는 ANN 검색을 표준 SQL WHERE 절과 결합할 수 있다는 점입니다. 특별한 구문 없이 메타데이터를 기본적으로 필터링할 수 있으므로, SQL만 작성하면 됩니다.
-- Semantic search filtered to the 'database' category
-- and only recent documents
SELECT
id,
content,
1 - (embedding <=> %s::vector) AS similarity
FROM documents
WHERE
category = 'database'
AND created_at > NOW() - INTERVAL '30 days'
ORDER BY embedding <=> %s::vector
LIMIT 5;
-- In Python with psycopg2:
# cur.execute(sql, (query_embedding, query_embedding))속도를 위한 HNSW 인덱스 만들기
인덱스가 없으면 pgvector는 모든 행을 정확하게 스캔합니다. 10,000개 미만의 행에서는 괜찮지만 규모가 커지면 느려집니다. 근사 최근접 이웃 검색을 위해 HNSW 인덱스를 만드세요. m(노드당 연결 수)과 ef_construction(생성 시 검색 폭) 매개변수는 인덱스 크기와 생성 시간을 늘리거나 줄이는 대신 재현율 정확도에 영향을 줍니다.
-- Create an HNSW index for cosine distance queries
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- At query time, control recall vs speed:
SET hnsw.ef_search = 40; -- higher = better recall, slower
-- Verify the index is being used:
EXPLAIN SELECT * FROM documents
ORDER BY embedding <=> '[0.1]'::vector(1)
LIMIT 5;IVFFlat 인덱스: HNSW의 대안
IVFFlat 인덱스 유형은 벡터를 lists 버킷으로 클러스터링하고, 쿼리 시 가장 가까운 probes 버킷만 검색합니다. HNSW보다 빠르게 생성되고 메모리를 덜 사용하지만, 같은 속도에서는 재현율이 약간 낮습니다.
일반적인 기준은 다음과 같습니다. 자주 인덱스를 다시 생성하는 동안 더 빠른 인덱스 생성을 원한다면 IVFFlat을 사용하고, 안정적인 말뭉치에서 최대 쿼리 속도가 필요하다면 HNSW를 사용하세요.
-- IVFFlat index: good for large, infrequently updated corpora
-- lists ≈ sqrt(n) where n is the number of vectors
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
-- At query time, probes controls recall vs speed:
SET ivfflat.probes = 10; -- check 10 of 100 clusters전체 Python 쿼리 예제
다음은 사용자 쿼리를 받아 임베딩하고, 메타데이터 필터링을 적용한 pgvector 유사도 검색을 수행한 다음, 상위 k개 결과를 딕셔너리 목록으로 반환하는 완전한 Python 함수입니다.
import psycopg2
from pgvector.psycopg2 import register_vector
from openai import OpenAI
conn = psycopg2.connect('postgresql://user:pass@localhost/mydb')
register_vector(conn)
client = OpenAI()
def semantic_search(query, category=None, top_k=5):
resp = client.embeddings.create(model='text-embedding-3-small', input=query)
q_vec = resp.data[0].embedding
sql = '''
SELECT content,
1 - (embedding <=> %s::vector) AS similarity
FROM documents
{where}
ORDER BY embedding <=> %s::vector
LIMIT %s
'''
where = 'WHERE category = %s' if category else ''
params = [q_vec, q_vec, top_k] if not category else [q_vec, category, q_vec, top_k]
cur = conn.cursor()
cur.execute(sql.format(where=where), params)
return [{'text': r[0], 'score': r[1]} for r in cur.fetchall()]pgvector와 Pinecone의 장단점 비교
pgvector와 Pinecone을 비교해 보겠습니다.
- pgvector: 자체 호스팅, 추가 비용 없음, 완벽한 SQL 통합, 약 500만 개의 벡터까지 우수한 확장성, 조정을 위해 DBA 지식 필요
- Pinecone: 완전 관리형, 대규모 확장(수십억 개의 벡터), 특화된 필터링, 더 높은 비용, 별도로 운영해야 하는 서비스
이미 PostgreSQL을 실행 중이고 말뭉치가 수백만 개 미만의 문서로 구성되어 있다면 pgvector를 선택하세요. 대규모 확장이 필요하거나 운영 부담을 피하는 데 비용을 지불할 가치가 있다면 Pinecone을 선택하세요.
Supabase에서 pgvector 사용하기
Supabase는 pgvector가 사전 설치된 호스팅 PostgreSQL 서비스입니다. Python 클라이언트(supabase-py)와 벡터 쿼리용 REST API를 제공하므로, 데이터베이스 서버를 직접 관리하지 않고도 운영 환경의 pgvector를 가장 쉽게 구성할 수 있습니다.
from supabase import create_client
import os
url = os.environ['SUPABASE_URL']
key = os.environ['SUPABASE_SERVICE_KEY']
supabase = create_client(url, key)
# Insert a document with embedding
supabase.table('documents').insert({
'content': 'Supabase hosts PostgreSQL with pgvector.',
'embedding': embedding # list of 1536 floats
}).execute()
# Vector similarity search via RPC (Supabase edge function)
# result = supabase.rpc('match_documents', {'query_embedding': q_vec, 'match_count': 5}).execute()빠른 확인
이 레슨에서 배운 AI 엔지니어링 개념을 이해했는지 확인해 보세요.
레슨 요약
이 레슨에서는 다음을 배웠습니다. pgvector는 PostgreSQL에 벡터 열 유형과 코사인/유클리드 거리 연산자를 추가합니다. HNSW 인덱스를 사용하면 대규모 환경에서 빠른 근사 최근접 이웃 검색을 수행할 수 있습니다. 또한 표준 SQL WHERE 절을 사용하면 특별한 구문 없이 메타데이터를 필터링할 수 있습니다. 다음 레슨에서는 주요 벡터 저장소 옵션을 모두 비교하여 프로젝트에 적합한 것을 선택하는 방법을 알아봅니다.
자주 묻는 질문
“pgvector: PostgreSQL의 임베딩” 강의는 무료인가요?
네 — “pgvector: PostgreSQL의 임베딩” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 AI Engineering Academy 강의 전체를 잠금 해제할 수 있습니다. AI Engineering Academy 강의에는 총 4개의 강의가 포함되어 있습니다.
“pgvector: PostgreSQL의 임베딩”에서 뭘 배우나요?
PostgreSQL에서 pgvector 확장을 활성화하고, 벡터 열이 있는 테이블을 만들며, 임베딩을 삽입하고, 코사인 거리 연산자로 최근접 이웃 질의를 실행합니다. 브라우저에서 직접 실행하는 실습 코드로 AI Engineering Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
AI Engineering Academy을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 AI Engineering Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.
“pgvector: PostgreSQL의 임베딩” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 AI Engineering Academy 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 AI Engineering Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 벡터 데이터베이스가 필요한 이유
- Pinecone 시작하기
- pgvector: PostgreSQL의 임베딩
- 벡터 저장소 선택 및 벤치마킹