Mascota Jacar — leyendo contigo Un portátil cuyos ojos siguen el cursor mientras lees.
Arquitectura Inteligencia Artificial

pgvector en 2024: índices HNSW y escalado real

pgvector en 2024: índices HNSW y escalado real

Actualizado: 2026-05-03

pgvector[1] pasó de curiosidad a infraestructura seria durante 2023. La versión 0.5 en agosto incorporó HNSW (Hierarchical Navigable Small World) como tipo de índice, acercándose al rendimiento de bases vectoriales dedicadas, y la serie 0.6 añade construcción paralela y reduce a la mitad el uso de memoria durante el build. Para equipos que ya operan PostgreSQL, la pregunta “¿necesito Pinecone, Qdrant o Weaviate?” tiene cada vez menos respuestas afirmativas.

Por qué pgvector gana tracción

La tracción no es moda: es operación. Los embeddings viven casi siempre al lado de metadatos relacionales — tenant, usuario, fecha, categoría, permisos — y el JOIN nativo entre vector y tabla evita pipelines de dos fases donde primero consultas una base vectorial, luego cruzas con PostgreSQL para filtrar, y rezas para que la cardinalidad no machaque la latencia. Con pgvector ese cruce es un único plan que el planner optimiza.

El segundo motivo es el coste cognitivo. Backups, streaming replication, pg_stat_statements, permisos a nivel de fila, extensiones como pg_cron o PostGIS, herramientas como pgBadger o pgbackrest: todo ese capital operativo ya está pagado. Introducir Pinecone o Qdrant significa otra autoridad de verdad, otro sistema de autenticación, otro runbook de incidentes. Para equipos pequeños o medianos, el coste marginal supera cualquier mejora de rendimiento.

El tercer motivo es la licencia. PostgreSQL y pgvector son BSD puro, sin cláusulas comerciales ni SSPL. En un paisaje donde Elastic, MongoDB y Redis han cambiado de licencia en años recientes — un patrón documentado en el impacto del cambio de licencia de Terraform — esa estabilidad es valor real.

Donde pgvector no compite: escala extrema (miles de millones de vectores con latencia sub-10ms como requisito duro) o cargas donde la búsqueda híbrida vector + BM25 + filtros geoespaciales complejos necesita un motor diseñado desde cero para esa mezcla.

IVFFlat contra HNSW: la transición que cambió todo

Hasta la versión 0.5, pgvector solo ofrecía IVFFlat: un índice basado en k-means que particiona el espacio en lists celdas. Funciona, pero tiene dos problemas importantes:

  • El recall por defecto ronda el 70-80%; subirlo implica aumentar probes, disparando la latencia linealmente.
  • IVFFlat se entrena sobre los datos existentes, así que inserts posteriores no se distribuyen bien y hay que reindexar periódicamente.

HNSW resuelve ambos. Construye un grafo multinivel donde cada nodo se conecta con sus vecinos más cercanos, y las consultas navegan de nivel grueso a nivel fino. El recall por defecto supera el 95% en la mayoría de datasets, los inserts son incrementales sin pérdida de calidad, y la latencia escala logarítmicamente con el tamaño. El precio: más memoria por consulta y un build más lento — problema que la 0.6 ataca con construcción paralela.

Para la mayoría de casos en la actualidad, HNSW es la opción correcta. IVFFlat solo tiene sentido en datasets enormes donde la huella de memoria de HNSW sería prohibitiva.

Crear y consultar un índice HNSW

El flujo mínimo cabe en pocas líneas de SQL:

sql
CREATE EXTENSION IF NOT EXISTS vector;

CREATE TABLE docs (
    id         bigserial PRIMARY KEY,
    tenant_id  int NOT NULL,
    content    text,
    embedding  vector(1536)
);

CREATE INDEX ON docs USING hnsw (embedding vector_cosine_ops)
  WITH (m = 16, ef_construction = 64);

SET hnsw.ef_search = 100;

SELECT content FROM docs
 ORDER BY embedding <=> $1
 LIMIT 10;

Los tres parámetros que mueven la aguja:

  • m: cuántos vecinos almacena cada nodo. 16 es razonable hasta pocos millones de vectores.
  • ef_construction: exhaustividad del build. 64 es el mínimo decente; 128-200 mejora calidad.
  • ef_search: palanca principal en producción, se fija por sesión. Empezar en 40 y subir hasta que el recall medido satisfaga el caso.

Sobre operadores: <=> es coseno, <-> euclidiana, <#> producto interno negativo. Los embeddings modernos están normalizados, así que coseno y producto interno son equivalentes salvo signo, pero cada operador requiere su propia opclass — no son intercambiables.

Filtros combinados y la trampa del orden

El punto donde pgvector brilla sobre bases dedicadas es la consulta “embedding más WHERE”. Cuando filtras por tenant y ventana temporal antes de ordenar por similitud, PostgreSQL tiene dos estrategias: recorrer el índice HNSW primero y filtrar después, o hacer un index scan convencional sobre el filtro y ordenar por distancia en memoria. La elección depende de la selectividad.

Si el WHERE reduce de un millón a cien mil filas, el índice vectorial merece la pena. Si reduce a cien, HNSW es contraproducente — examinar el grafo para descartar el 99.99% de nodos cuesta más que calcular cien distancias directamente.

Aquí entran los índices parciales: crear un HNSW restringido a los tenants más activos acota el grafo cuando el tráfico es muy desigual. La versión 0.6 también añade iterative_scan, que escanea más allá del top-K inicial si el WHERE descarta demasiados candidatos.

Diagrama de un grafo HNSW multinivel: nodos en capas con conexiones entre vecinos más próximos y navegación coarse-to-fine en la consulta

Rendimiento orientativo y la palanca del modelo

En hardware mediano — 16 cores, 64 GB de RAM, NVMe — un índice HNSW sobre 10 millones de vectores de 1536 dimensiones ocupa unos 30 GB y responde en 5 ms p50 con ef_search=40. A 100 millones, el índice se acerca a 300 GB y la latencia a 20 ms p50, momento en que necesitas scale-up serio o sharding por tenant. Por encima de mil millones, pgvector queda corto y Qdrant o Milvus escalan mejor por diseño.

La dimensión del embedding es una palanca infravalorada. text-embedding-ada-002 de OpenAI devuelve 1536 dims, pero modelos abiertos como all-MiniLM-L6-v2 rinden decentemente con 384, y BGE-small con 384 o BGE-base con 768 ofrecen trade-offs intermedios. Reducir de 1536 a 384 recorta el índice casi cuatro veces. Para cargas RAG donde la precisión absoluta del modelo grande no es crítica, medir qué tal aguanta el caso con un encoder más pequeño suele ser más barato que comprar hardware. Ver text-embedding-3 de OpenAI para el análisis de las opciones recientes.

Observabilidad, HA y síntomas del dolor

pgvector hereda todo el ecosistema PostgreSQL: streaming replication, logical replication, Patroni para failover, pgbackrest para backups. Un patrón que funciona bien: dedicar una réplica de solo lectura a las consultas vectoriales y dejar la primaria absorbiendo inserts, evitando que picos de ingesta contaminen la latencia RAG.

Monitorizar HNSW requiere vigilar:

  • pg_stat_user_indexes.idx_scan para confirmar que el índice se usa.
  • El buffer cache hit ratio — si HNSW se sale de memoria, el rendimiento cae en acantilado.
  • El recall efectivo: hay que comparar periódicamente el top-10 aproximado contra el top-10 exacto por fuerza bruta sobre un subconjunto de consultas. Si HNSW se fragmenta tras muchos updates o deletes, el recall degrada silenciosamente y nada en el log lo avisa.

Los síntomas de haber pasado el límite son reconocibles: más de cien millones de vectores con p99 exigente, más de mil QPS saturando CPU, índices que no caben en RAM, o la necesidad de ranking híbrido vector-BM25. Antes de migrar a Weaviate o Qdrant, agota las opciones baratas: escalar a 32 cores y 256 GB, separar la carga vectorial a una réplica dedicada, reducir dimensiones o shardar por tenant.

Para la instalación desde cero en Debian/Ubuntu, ver el artículo complementario cómo instalar PostgreSQL con pgvector. Para el panorama general de bases vectoriales dedicadas, ver bases de datos vectoriales: comparativa.

Conclusión

pgvector ha madurado hasta ser la opción por defecto razonable para quien ya opera PostgreSQL. El listón para justificar una base vectorial dedicada se ha movido notablemente hacia arriba. La decisión se ha invertido: el default ya no es añadir infraestructura, es demostrar con números por qué PostgreSQL no basta. La mayoría de las veces, basta.

¿Te ha resultado útil?
[Total: 11 · Media: 4.4]
  1. pgvector

Escrito por

CEO - Jacar Systems

Apasionado de la tecnología, la infraestructura cloud y la inteligencia artificial. Escribe sobre DevOps, IA, plataformas y software desde Madrid.