Intermedio 11 minStack

pgvector: la búsqueda vectorial en PostgreSQL

Respuesta directa

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.

Por Mohamed Meguedmi·Actualización 2026-09-28·Probado en Windows, macOS y Linux

#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?

El kit RAG Local

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.

Los elementos del rompecabezas
ElementoQué esA monitorear
Columna vectorialUn array de números en coma flotante de dimensión fijaLa dimensión viene determinada por el modelo de embedding y no se puede cambiar sin volver a codificarlo todo
Operador de distanciaCoseno, producto escalar o distancia euclidiana (L2)Debe coincidir con el modelo
Índice HNSWÍndice en grafo, consultas rápidasConstrucció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 construirCrear una vez que haya datos representativos
Sin índiceRecorrido exacto de todas las líneasPerfectamente viable hasta unas decenas de miles de líneas

#El SQL mínimo para comenzar

  1. 01
    Activar la extensión
    CREATE EXTENSION IF NOT EXISTS vector; — un solo comando que se ejecuta una vez por base de datos.
  2. 02
    Añadir la columna
    ALTER TABLE chunks ADD COLUMN embedding vector(1024); — la dimensión debe coincidir exactamente con la del modelo de embedding utilizado.
  3. 03
    Cargar los datos antes de indexar
    Una 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.
  4. 04
    Crear el índice
    CREATE 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.
  5. 05
    Consultar
    SELECT 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.

→
La cuantización no es solo un detalle de almacenamiento
Pasar de vector a halfvec reduce el tamaño de cada fila a la mitad, lo que permite mantener más índices en memoria y acelera las consultas a gran escala sin cambiar tu modelo de embedding. La cuantización binaria (tipo bit) va más allá: comprime el índice para la búsqueda y, después, una reordenación basada en los vectores completos recupera la precisión perdida: es el método documentado por el propio proyecto para mantener un índice grande completamente en memoria en lugar de que parte de él acabe en disco.

#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.

!
Los permisos de acceso no se gestionan en el prompt
Cuando varias personas consultan el mismo índice, el filtro de permisos es lo que impide que un modelo cite a alguien un documento que esa persona no debería ver. Ninguna instrucción del prompt sustituye este filtro, y expresarlo en SQL utilizando tu modelo de autorización existente es mucho más seguro que reimplementarlo.

#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.
i
El VACUUM en un índice HNSW puede ser lento
La documentación oficial lo indica explícitamente: la limpieza (VACUUM) de una tabla cuyo índice vectorial es HNSW puede llevar tiempo cuando el volumen de datos es grande. Para acelerarla, hay que ejecutar REINDEX INDEX CONCURRENTLY antes de VACUUM, en lugar de dejar que la operación de mantenimiento se ejecute sola: un detalle operativo que pocos tutoriales mencionan antes de que el mantenimiento nocturno exceda su ventana de ejecución.

#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.

Elegir según la situación
SituaciónOpciones
PostgreSQL ya en uso, menos de unos cientos de miles de fragmentospgvector, cómodamente
Los vectores deben mantenerse coherentes con datos relacionalespgvector: las transacciones lo hacen gratis
Filtrado granular basado en los permisos de acceso existentespgvector
Modelo de embedding con más de 4.000 dimensiones sin posibilidad de reducciónVerificar el tipo sparsevec o una base dedicada pensada para este caso
Millones de vectores, muchas consultasUn motor dedicado (Qdrant, Milvus)
Prototipo en un notebookCualquiera, esta elección es reversible

#FAQ

¿Es suficientemente rápido pgvector para RAG?+
Para un corpus local típico —de unas decenas a unos cientos de miles de fragmentos—, sí, con un índice HNSW, y a menudo incluso sin índice en el extremo inferior de ese intervalo. La recuperación rara vez es la etapa lenta de una cadena local: es la generación por parte del modelo la que domina el tiempo de respuesta percibido.
¿pgvector o Qdrant?+
pgvector si PostgreSQL ya está instalado y tus datos son relacionales: menos servicios, coherencia transaccional, filtros SQL nativos y una sola copia de seguridad que organizar. Qdrant cuando la escala, la cuantización agresiva para ahorrar memoria o un servicio dedicado diseñado íntegramente para trabajar con vectores importan más que la sencillez de administrar una única base de datos. Ambos satisfacen adecuadamente la misma necesidad hasta varios cientos de miles de vectores.
¿Qué índice elegir, HNSW o IVFFlat?+
HNSW es la opción predeterminada desde hace varias versiones: mejor rendimiento en las consultas, a costa de una construcción más lenta y un mayor consumo de memoria. IVFFlat es menos costoso de construir, pero debe crearse cuando ya se hayan cargado datos representativos; de lo contrario, las particiones quedarán mal distribuidas.
¿Puedo filtrar por metadatos?+
Sí, en SQL común, incluyendo joins. Es una de las mejores razones para elegirlo, especialmente para filtrar por permisos de acceso. Sin embargo, ten cuidado: con un índice aproximado, este filtro se aplica después de recorrer el índice, lo que puede devolver menos resultados de los esperados sin el recorrido iterativo.
¿Qué pasa si cambio de modelo de embedding?+
Todo debe ser reencodificado: la dimensión y la geometría de los vectores pertenecen al modelo, no a la base. Es un procesamiento por lotes en la GPU, no una migración de esquema, y se debe recrear la columna si la nueva dimensión supera la declarada. Prevé un periodo de transición, ya que el índice anterior sigue siendo válido mientras no termine la reencodificación.
Mi modelo de embedding tiene más de 2 000 dimensiones, ¿qué hacer?+
El tipo vector estándar indexa hasta 2.000 dimensiones. Por encima de ese límite, pasa al tipo halfvec (hasta 4.000, en media precisión) o reduce la dimensión durante la generación si tu proveedor lo permite, como ofrece OpenAI para text-embedding-3-large. Sin índice, PostgreSQL puede almacenar hasta 16.000 dimensiones, aunque la búsqueda se realiza mediante un recorrido exacto.
¿Cómo diagnosticar una consulta vectorial lenta?+
La documentación recomienda anteponer EXPLAIN (ANALYZE, BUFFERS) a la consulta para ver si realmente se utiliza el índice y cuántos bloques se leen. Una consulta exacta sin índice se beneficia de aumentar max_parallel_workers_per_gather; una consulta aproximada lenta suele indicar que el índice sigue en construcción o que no hay suficiente memoria para mantenerlo en caché.
¿Esta guía te ha ayudado?

¿Un comentario, un error, una precisión? Avísanos, eso mejora la guía para todos.