pgvector: la búsqueda vectorial en PostgreSQL
pgvector es una extensión de código abierto de PostgreSQL (licencia PostgreSQL, permisiva) que añade el almacenamiento y la búsqueda de vectores a una base de datos que ya administras, con columnas indexables de hasta 2.000 dimensiones (4.000 en media precisión). Para un corpus local de unos cientos de miles de fragmentos, supone un servicio menos que gestionar y filtros SQL que funcionan, sin tener que mantener una sincronización con tus datos relacionales.
pgvector es una extensión de PostgreSQL que añade el almacenamiento y la búsqueda de vectores a una base de datos que ya administras. Para la mayoría de los proyectos de búsqueda documental local, supone un servicio menos que mantener en funcionamiento, una copia de seguridad menos que organizar y filtros SQL que funcionan realmente, también para los permisos de acceso. El proyecto, mantenido bajo licencia PostgreSQL y alojado en GitHub, contaba con más de 23.000 estrellas a finales de septiembre de 2026, en la versión 0.8.6, compatible con PostgreSQL 13 y versiones posteriores.
#El argumento: no añadir un servicio
Una instalación local para trabajar con documentos ya ejecuta un servidor de modelos, una etapa de codificación y un sistema de almacenamiento de documentos. Añadir una base de datos vectorial dedicada supone un contenedor más, un puerto más, una copia de seguridad más y un elemento más que puede desincronizarse de tus datos relacionales cuando se elimina un documento.
Si PostgreSQL ya está presente —y en una aplicación empresarial casi siempre lo está—, pgvector elimina toda esta categoría de problemas. Tus fragmentos de texto están en una tabla junto a los documentos de los que proceden, con claves foráneas que los mantienen coherentes, y una eliminación se propaga como esperas, sin tener que escribir ni supervisar una tarea de limpieza independiente. El proyecto añade además búsqueda exacta y aproximada, vectores de precisión simple, de media precisión, binarios y dispersos, cinco distancias (L2, producto escalar, coseno, L1, Hamming, Jaccard), y hereda sin coste adicional la conformidad ACID, la recuperación a un punto en el tiempo y las uniones de PostgreSQL.
#¿Cómo funciona en la práctica?
Tus documentos, tu IA: un RAG local fiable sobre tus PDF, notas y correos — sin enviar nada a la nube.
- Espacio en línea de por vida
- PDF + archivos
- Actualizaciones de por vida
Almacenas una columna de vectores junto a tus columnas habituales. Una consulta ordena las filas por distancia al vector de la pregunta y devuelve las más cercanas. Tres operadores de distancia cubren los casos comunes, y el que elijas debe coincidir con la convención del modelo de embeddings: es la causa más frecuente de resultados mediocres que pasan desapercibidos. Para vectores normalizados a longitud 1 (el caso de OpenAI y de la mayoría de los modelos de embeddings recientes), el producto escalar es el más rápido de calcular y da la misma clasificación que el coseno.
| Elemento | Qué es | A monitorear |
|---|---|---|
| Columna vectorial | Un array de números en coma flotante de dimensión fija | La dimensión viene determinada por el modelo de embedding y no se puede cambiar sin volver a codificarlo todo |
| Operador de distancia | Coseno, producto escalar o distancia euclidiana (L2) | Debe coincidir con el modelo |
| Índice HNSW | Índice en grafo, consultas rápidas | Construcción lenta y con un alto consumo de memoria; la opción predeterminada razonable desde la versión 0.5 |
| Índice IVFFlat | Índice por particiones, poco costoso de construir | Crear una vez que haya datos representativos |
| Sin índice | Recorrido exacto de todas las líneas | Perfectamente viable hasta unas decenas de miles de líneas |
#El SQL mínimo para comenzar
- 01Activar la extensiónCREATE EXTENSION IF NOT EXISTS vector; — un solo comando que se ejecuta una vez por base de datos.
- 02Añadir la columnaALTER TABLE chunks ADD COLUMN embedding vector(1024); — la dimensión debe coincidir exactamente con la del modelo de embedding utilizado.
- 03Cargar los datos antes de indexarUna carga masiva mediante COPY es más rápida sin un índice existente; crea el índice una vez que haya una cantidad representativa de filas.
- 04Crear el índiceCREATE INDEX CONCURRENTLY ON chunks USING hnsw (embedding vector_cosine_ops); — la opción CONCURRENTLY evita bloquear las escrituras durante la construcción del índice, que tarda mucho en una tabla grande.
- 05ConsultarSELECT contenu FROM chunks WHERE document_id IN (SELECT id FROM documents WHERE utilisateur_autorise($1)) ORDER BY embedding <=> $2 LIMIT 5; — el filtro de autorización y la ordenación por similitud en la misma consulta.
#Las limitaciones de dimensión, concretamente
pgvector define cuatro tipos de columnas, cada uno con su propio límite de dimensiones indexables. El tipo vector estándar (precisión simple, 4 bytes por elemento) se puede indexar hasta 2 000 dimensiones, lo que cubre la mayoría de los modelos de embedding de código abierto habituales (de 384 a 1 024 dimensiones). Un modelo de mayor dimensionalidad como text-embedding-3-large de OpenAI, con 3 072 dimensiones por defecto, supera este límite: la solución documentada consiste en reducir la dimensión al generar el embedding (la API lo permite) o pasar al tipo halfvec, que almacena en semiprecisión (2 bytes por elemento, la mitad de espacio) y se puede indexar hasta 4 000 dimensiones. El tipo bit (vectores binarios, distancias de Hamming o Jaccard) alcanza las 64 000 dimensiones indexables, y sparsevec (vectores dispersos), los 1 000 elementos no nulos indexados. Más allá de esos límites, PostgreSQL sigue almacenando la columna (hasta 16 000 dimensiones para vector, halfvec y sparsevec), pero sin poder indexarla, lo que obliga a realizar un recorrido exacto.
#El filtrado y los derechos de acceso
Una pregunta real rara vez abarca todo el corpus: se quieren los pasajes de este servicio, posteriores a esta fecha, en los documentos que este usuario tiene derecho a leer. En una base vectorial dedicada, es un filtro de metadatos con su sintaxis y sus casos límite. En PostgreSQL, es una cláusula WHERE junto a una ordenación por similitud, con una unión a tu tabla de usuarios si es necesario.
Conviene conocer una dificultad documentada por el propio proyecto antes de descubrirla en producción: con un índice aproximado (HNSW o IVFFlat), el filtro se aplica después de recorrer el índice, no antes. Si una condición retiene solo un 10 % de las filas y el parámetro por defecto hnsw.ef_search vale 40, solo se obtienen 4 filas de media, no las diez solicitadas. La solución oficial, disponible desde la versión 0.8.0, se llama escaneo iterativo del índice (SET hnsw.iterative_scan = strict_order), que vuelve a recorrer automáticamente el índice hasta encontrar suficientes resultados, en lugar de devolver un conjunto truncado en silencio.
#Dónde están los límites
- La memoria a gran escala
- Millones de vectores con precisión completa ocupan mucho espacio; halfvec y la cuantización binaria reducen el uso de memoria, pero los motores especializados llevan la compresión más lejos de forma nativa. Es la diferencia más clara.
- Tiempo de construcción del índice
- Construir un índice HNSW en una tabla muy grande lleva tiempo y consume muchos recursos; en producción, hacerlo con CREATE INDEX CONCURRENTLY evita bloquear las escrituras durante la operación.
- La concurrencia
- Ejecutar búsquedas vectoriales intensivas junto a tu carga transaccional coloca ambas cargas en el mismo servidor. Las réplicas de lectura ayudan; separar los roles ayuda aún más.
- La dimensión de los vectores
- Los vectores indexados tienen un límite según su tipo (2 000 para vector, 4 000 para halfvec). Los modelos habituales caben dentro de ese límite; un modelo con una dimensionalidad muy alta debe reducirse o cuantizarse.
- Búsqueda híbrida
- PostgreSQL permite realizar búsquedas de texto completo (tsvector) y puedes combinarlas con la distancia vectorial, pero facilitar su uso corre por tu cuenta: debes ejecutar las dos consultas por separado y después fusionar las clasificaciones, por ejemplo mediante una fusión de rangos recíprocos (Reciprocal Rank Fusion), en lugar de obtener una puntuación híbrida nativa en una sola consulta.
- La escalabilidad horizontal
- Más allá de un solo servidor, la vía documentada pasa por réplicas de lectura de PostgreSQL o por una herramienta de distribución como Citus o PgDog: un componente adicional, en contra del argumento inicial.
#pgvector o una base dedicada
La pregunta no es cuál es objetivamente mejor, sino cuál se adapta a tu situación actual. pgvector gana cuando PostgreSQL ya es la fuente de verdad de la aplicación: facturación, cuentas, documentos fuente. Un motor dedicado gana cuando el volumen de vectores o la tasa de consultas supera lo que un solo servidor transaccional puede absorber sin perjudicar el funcionamiento del resto de la aplicación, o cuando el equipo prefiere aislar el componente de IA del resto del sistema de información por razones operativas más que de rendimiento puro.
| Situación | Opciones |
|---|---|
| PostgreSQL ya en uso, menos de unos cientos de miles de fragmentos | pgvector, cómodamente |
| Los vectores deben mantenerse coherentes con datos relacionales | pgvector: las transacciones lo hacen gratis |
| Filtrado granular basado en los permisos de acceso existentes | pgvector |
| Modelo de embedding con más de 4.000 dimensiones sin posibilidad de reducción | Verificar el tipo sparsevec o una base dedicada pensada para este caso |
| Millones de vectores, muchas consultas | Un motor dedicado (Qdrant, Milvus) |
| Prototipo en un notebook | Cualquiera, esta elección es reversible |
- Qdrant: la base vectorial dedicada
- Milvus, cuando el volumen supere lo que puede manejar pgvector
- FAISS: la biblioteca detrás de la búsqueda vectorial
- Construir la cadena RAG completa
- Elegir tu modelo de embedding
- El kit RAG local QuelLLM: todos los componentes en una página
- Fuente: repositorio oficial pgvector en GitHub
- Fuente: documentación de índices y tipos pgvector
- Fuente: guía de escalabilidad de pgvector
#FAQ
¿Es suficientemente rápido pgvector para RAG?+
¿pgvector o Qdrant?+
¿Qué índice elegir, HNSW o IVFFlat?+
¿Puedo filtrar por metadatos?+
¿Qué pasa si cambio de modelo de embedding?+
Mi modelo de embedding tiene más de 2 000 dimensiones, ¿qué hacer?+
¿Cómo diagnosticar una consulta vectorial lenta?+
¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.