pgvector es una extensión de PostgreSQL que añade tipo de columna vector y operadores de distancia. Con CREATE EXTENSION vector; y un par de índices, conviertes tu Postgres existente en una base vectorial razonable. En 2023 es la opción que cada vez más equipos eligen frente a desplegar un servicio dedicado, sobre todo para proyectos que ya tienen Postgres en producción.
Por qué pgvector tiene sentido
La pregunta clave: ¿necesito una BD vectorial dedicada (Qdrant, Pinecone, Milvus) o me basta con una extensión sobre Postgres?
Argumentos a favor de pgvector:
- Una sola base de datos. Datos relacionales (usuarios, posts, metadatos) y embeddings en el mismo sitio. Joins reales, no llamadas paralelas.
- Backups y operaciones existentes. Tu pipeline de backups, monitorización, alertas y replicación de Postgres ya cubren los embeddings sin trabajo extra.
- Skill team existente. Tu equipo ya sabe Postgres. No hay que aprender un sistema nuevo.
- Compliance simplificado. Una sola BD que auditar, una sola política de seguridad.
- Coste. Si ya pagas por Postgres, esto es una extensión gratuita.
Cuándo pgvector no basta:
- Volumen masivo (cientos de millones de vectores con queries QPS altos sostenidos). Bases dedicadas escalan mejor.
- Dimensiones muy altas (>2000). pgvector funciona pero hay alternativas más optimizadas.
- Necesidad de búsqueda híbrida muy avanzada con múltiples filtros y agregaciones específicas vectoriales.
Para el 80% de proyectos LLM que usan embeddings con menos de 10M de vectores, pgvector es suficiente y simplifica enormemente la arquitectura.
Instalación y uso básico
En Postgres 16 (o cualquier versión soportada >= 11):
CREATE EXTENSION vector;
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
content TEXT,
embedding vector(1536) -- dimensión del modelo (ej. OpenAI ada-002)
);
INSERT INTO documents (content, embedding)
VALUES ('Texto de ejemplo', '[0.1, 0.2, ..., -0.05]'::vector);
-- Búsqueda por similitud coseno (top 5)
SELECT id, content, 1 - (embedding <=> '[...]'::vector) AS score
FROM documents
ORDER BY embedding <=> '[...]'::vector
LIMIT 5;
Tres operadores principales:
<=>distancia coseno<->distancia euclídea (L2)<#>producto interior negativo
La función 1 - (a <=> b) convierte distancia coseno a similitud (rango 0-1).
Los índices: IVFFlat y HNSW
Sin índice, la búsqueda es secuencial — funciona pero escala mal. pgvector ofrece dos tipos de índice:
IVFFlat
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);
Particiona los vectores en lists clusters. Al buscar, mira solo los clusters más cercanos a la query (probes, configurable a tiempo de query). Trade-off recall vs velocidad.
Buena regla: lists = sqrt(N) donde N es el número de vectores. Para 1M vectores, lists = 1000. Y para un 95-98% de recall, SET ivfflat.probes = 10 antes de la query.
HNSW (desde pgvector 0.5)
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops);
Hierarchical Navigable Small World — el mismo algoritmo que usan Qdrant y Pinecone. Mejor calidad y velocidad que IVFFlat en la mayoría de casos. Coste: más memoria y construcción más lenta.
Para proyectos nuevos en pgvector 0.5+, HNSW es la elección por defecto.
Patrones que importan en producción
Tres detalles operativos que cambian la experiencia:
- Construcción de índice no bloqueante.
CREATE INDEX CONCURRENTLYevita lockear la tabla. Importante para tablas con escrituras frecuentes. - Reindexado periódico. Si insertas miles de vectores nuevos al día, el índice IVFFlat puede degradarse. HNSW es más estable. Para IVFFlat,
REINDEXocasional. - Filtrado por metadatos antes del vector search. La sintaxis correcta:
WHERE category = 'tech' ORDER BY embedding <=> '[...]' LIMIT 10
Postgres aplica el filtro primero (si tiene índice), luego el ranking vectorial sobre el subconjunto. Mucho más rápido que filtrar después.
Comparativa práctica
| Aspecto | pgvector | Qdrant | Pinecone |
|---|---|---|---|
| Setup | Extensión sobre PG | Servicio Docker | Cuenta managed |
| Coste fijo | El de tu PG | Servidor adicional | Suscripción mensual |
| Joins con datos relacionales | Nativo | Requiere capa custom | Requiere capa custom |
| Escala (vectores) | Hasta ~10M cómodo | Cientos de millones | Sin límite práctico |
| Latencia query | 5-50ms típica | 1-10ms | 10-50ms |
| Operación día a día | Cero (es PG) | Servicio adicional | Cero (managed) |
| Privacidad | Local | Local | SaaS externa |
Cuándo conviene mover a otra cosa
Señales de que has superado pgvector:
- Latencia query sostenida >100ms con índice HNSW correctamente configurado.
- Más de 50M vectores con crecimiento alto.
- Memoria RAM insuficiente para mantener índices HNSW en cache.
- Necesidad de cuantización de vectores (compresión) que pgvector no implementa todavía.
En esos puntos, Qdrant es probablemente la mejor migración: open source, escala bien, mantiene la propiedad de “puedes ejecutarlo tú”.
Conclusión
pgvector es la opción pragmática por defecto en 2023 si ya usas Postgres. Reduce la superficie operativa del stack a costa de un poco menos de rendimiento que las BDs vectoriales dedicadas — pero esa diferencia rara vez es el cuello de botella en proyectos típicos. Empezar aquí y migrar después si es necesario es casi siempre la decisión correcta.
Síguenos en jacar.es para más sobre PostgreSQL, vector databases y arquitecturas de búsqueda semántica.