pgvector: embeddings en PostgreSQL
Activará la extensión pgvector en PostgreSQL, creará una tabla con una columna vectorial, insertará embeddings y ejecutará consultas de vecinos más cercanos mediante el operador de distancia coseno .
pgvector: embeddings en PostgreSQL es una lección gratuita de AI Engineering Academy en CoddyKit. Esta es la lección 3 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de AI Engineering Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de AI Engineering Academy incluye 4 lecciones en total.
Partes de esta lección aún no han sido traducidas y se muestran en inglés.
pgvector: Vector Search in PostgreSQL
pgvector is an open-source PostgreSQL extension that adds a vector data type and similarity search operators. It lets you store embeddings alongside your regular application data in the same database you already operate, avoiding a separate vector store.
This is ideal for teams that already use PostgreSQL and want to add semantic search without introducing a new infrastructure dependency.
Enabling the pgvector Extension
Install pgvector from the official repository or use a managed PostgreSQL provider that pre-installs it (Supabase, Neon, AWS RDS, Render). Then enable it in your database with a single SQL command — no restart required.
-- 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)Creating a Table with a Vector Column
Add a vector column by specifying vector(n) where n is the embedding dimension. You can combine it with regular PostgreSQL columns for metadata — this lets you filter by user_id, created_at, or any other field using standard SQL WHERE clauses.
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';Inserting Embeddings from Python
Use the psycopg2 or asyncpg driver to insert rows with embeddings. Convert the Python list of floats to a string in the format '[0.1, 0.2, ...]' which pgvector parses correctly. The pgvector Python package provides a register_vector helper to handle this automatically.
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')Cosine Similarity with the <=> Operator
pgvector adds three distance operators:
<=>— cosine distance (1 - cosine_similarity)<->— Euclidean (L2) distance<#>— negative inner product (use for dot product similarity)
For text embeddings, use <=> (cosine distance). ORDER BY distance ASC returns the most similar documents first.
-- 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;Combining Vector Search with SQL Filters
One of pgvector's biggest advantages is that you can combine ANN search with standard SQL WHERE clauses. This enables metadata filtering natively without any special syntax — just write 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))Creating an HNSW Index for Speed
Without an index, pgvector does an exact scan of every row — fine for under 10,000 rows but slow at scale. Create an HNSW index for approximate nearest neighbor search. The m (connections per node) and ef_construction (build-time search width) parameters trade index size and build time for recall accuracy.
-- 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 Index: Alternative to HNSW
The IVFFlat index type clusters vectors into lists buckets and searches only the nearest probes buckets at query time. It builds faster than HNSW and uses less memory, but has slightly lower recall for the same speed.
Rule of thumb: use IVFFlat when you need faster index builds during frequent re-indexing; use HNSW for stable corpora that need maximum query speed.
-- 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 clustersFull Python Query Example
Here is a complete Python function that takes a user query, embeds it, runs a pgvector similarity search with metadata filtering, and returns the top-k results as a list of dicts.
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 vs Pinecone Trade-offs
Comparing pgvector and Pinecone:
- pgvector: self-hosted, no extra cost, perfect SQL integration, scales to ~5M vectors well, requires DBA knowledge for tuning
- Pinecone: fully managed, massive scale (billions of vectors), specialized filtering, more expensive, separate service to operate
Choose pgvector when you already run PostgreSQL and your corpus is under a few million documents. Choose Pinecone for massive scale or when avoiding ops burden is worth the cost.
Using pgvector with Supabase
Supabase is a hosted PostgreSQL service with pgvector pre-installed. It provides a Python client (supabase-py) and a REST API for vector queries, making it the easiest way to get a production pgvector setup without managing a database server yourself.
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()Quick Check
Test your understanding of AI Engineering concepts from this lesson.
Lesson Recap
In this lesson you learned: pgvector adds a vector column type and cosine/Euclidean distance operators to PostgreSQL, HNSW indexes enable fast approximate nearest neighbor search at scale, and standard SQL WHERE clauses provide metadata filtering without any special syntax. Next up we compare all the major vector store options to help you choose the right one for your project.
Preguntas frecuentes
¿La lección «pgvector: embeddings en PostgreSQL» es gratis?
Sí — el texto completo de «pgvector: embeddings en PostgreSQL» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de AI Engineering Academy, actualiza a CoddyKit PRO. El curso de AI Engineering Academy incluye 4 lecciones en total.
¿Qué aprenderé en «pgvector: embeddings en PostgreSQL»?
Activará la extensión pgvector en PostgreSQL, creará una tabla con una columna vectorial, insertará embeddings y ejecutará consultas de vecinos más cercanos mediante el operador de distancia coseno . Practicas AI Engineering Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar AI Engineering Academy?
No se requiere experiencia previa. AI Engineering Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 3 de 4.
¿Cuánto tiempo toma la lección «pgvector: embeddings en PostgreSQL»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de AI Engineering Academy?
Sí. Cada lección de AI Engineering Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.
Todas las lecciones de este curso
- Por qué necesita una base de datos vectorial
- Primeros pasos con Pinecone
- pgvector: embeddings en PostgreSQL
- Selección y evaluación comparativa de vector stores