<!-- Canonical: https://lucioduran.com/es/blog/vector-databases-pgvector-qdrant-pinecone
Language: es
Content-SHA256: f2cecca2ac72b5ac5ef53b916a937dcd26664098597698e1e483035a4f86b8a7
-->

AI/ML

# Bases de Datos Vectoriales Comparadas: Ejecutando el Mismo Pipeline RAG en pgvector, Qdrant, Pinecone y Weaviate

2025-12-029 min lectura

Lucio Durán
Engineering Manager & AI Solutions Architect

También disponible en: [English](<https://lucioduran.com/blog/vector-databases-pgvector-qdrant-pinecone>)

## El Setup de Test

**Dataset**: 2.3M chunks de documentos de una base de conocimiento de soporte al cliente. Tamaño promedio de chunk: 512 tokens. Embeddeado con ` text-embedding-3-small ` (1536 dimensiones).

**Queries**: 10,000 queries reales de usuarios recolectadas de logs de producción (anonimizadas). Mix de cortas ("resetear contraseña"), medianas ("cómo configurar SSO con Azure AD"), y largas ("nuestro equipo está migrando de on-premise a cloud y necesitamos entender las implicaciones de residencia de datos para cumplimiento GDPR").

**Hardware**:

- pgvector: RDS ` db.r7g.xlarge ` (4 vCPU, 32GB RAM), PostgreSQL 16 con pgvector 0.8
- Qdrant: cluster de 3 nodos en ` c7g.xlarge ` (4 vCPU, 8GB RAM cada uno), Qdrant 1.13
- Pinecone: Serverless (Standard), us-east-1
- Weaviate: cluster de 3 nodos en ` c7g.xlarge `, Weaviate 1.28

**Búsqueda**: Top-10 vecinos más cercanos, similaridad coseno, con filtro de metadata (categoría = valor específico, reduciendo candidatos en ~80%).

## Números Crudos: Latencia y Throughput

### Latencia de Query (10K queries, ms)

| Base de datos | p50 | p95 | p99 | p99.9 |
| --- | --- | --- | --- | --- |
| pgvector (HNSW) | 8.2 | 14.1 | 22.3 | 41.7 |
| pgvector (IVF) | 12.4 | 24.8 | 38.1 | 67.2 |
| Qdrant | 3.1 | 5.8 | 8.4 | 14.2 |
| Pinecone Serverless | 18.4 | 32.1 | 48.7 | 142.3 |
| Weaviate | 5.7 | 11.2 | 18.9 | 33.4 |

Qdrant gana en latencia cruda, y no es ni cerca. Su engine basado en Rust con almacenamiento memory-mapped es genuinamente rápido. Pero observar el p99.9 de Pinecone, ese es 142ms de cola son el cold start serverless afectando el rendimiento. Para aplicaciones interactivas, esa cola es un problema.

pgvector con HNSW es sorprendentemente competitivo. Con 8.2ms de p50, es suficientemente rápido para cualquier aplicación RAG. La brecha se amplía en la cola, pero para la mayoría de los case es de uso, es más que adecuado.

### Throughput (queries/segundo, 100 conexiones concurrentes)

| Base de datos | QPS (sin filtro) | QPS (con filtro) | Delta |
| --- | --- | --- | --- |
| pgvector (HNSW) | 2,840 | 2,120 | -25.4% |
| Qdrant | 8,420 | 7,180 | -14.7% |
| Pinecone | 1,200 | 980 | -18.3% |
| Weaviate | 4,100 | 3,250 | -20.7% |

La diferencia de performance con filtrado es reveladora. pgvector pierde 25% de throughput con filtros porque los aplica post-búsqueda HNSW (una limitación conocida). Qdrant integra el filtrado en el algoritmo de búsqueda, así que la penalidad es menor. Weaviate cae en algún punto intermedio.

El techo de throughput de Pinecone es notablemente más bajo de lo que se esperaría para un servicio managed. La arquitectura serverless prioriza optimización de costo por query sobre throughput crudo.

## HNSW vs IVF: Cuándo Gana Cada Uno

pgvector 0.8 soporta tanto índices HNSW como IVF-Flat. La elección importa más de lo que la mayoría cree.

### HNSW (Hierarchical Navigable Small World)

```sql
CREATE INDEX ON documents
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 256);

-- Al momento de la query
SET hnsw.ef_search = 100;
```

**Pros**: Queries rápidas, alto recall, sin paso de entrenamiento **Contras**: Alto uso de memoria (~1.5x los datos de vectores), builds de índice lentos

Tiempo de build HNSW para 2.3M vectores a 1536 dimensiones: **47 minutos** en nuestra instancia RDS. Uso de memoria: **14.2GB** solo para el índice.

### IVF-Flat (Inverted File con cuantización Flat)

```sql
CREATE INDEX ON documents
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 1500);

-- Al momento de la query
SET ivfflat.probes = 40;
```

**Pros**: Menor uso de memoria (~0.3x), builds de índice más rápidos **Contras**: Requiere entrenamiento (el parámetro lists necesita tuning), menor recall a la misma latencia

Tiempo de build IVF: **12 minutos**. Memoria: **4.1GB**. Pero el recall a la misma latencia fue 91.2% vs 97.8% de HNSW.

### Recomendación

Usar HNSW a menos que la memoria sea la restricción principal. La diferencia de recall (97.8% vs 91.2%) significa que por cada 100 queries, IVF se pierde ~7 resultados relevantes que HNSW encuentra. En un pipeline RAG, ese es chunks perdidos impactan directamente la calidad de las respuestas.

## Cuantización: El Tradeoff de Memoria vs Calidad

Con 2.3M vectores a 1536 dimensiones (float32), los datos crudos de vectores son aproximadamente **13.4GB**. La cuantización reduce esto dramáticamente:

### pgvector: halfvec (float16)

```sql
-- pgvector 0.8 soporta halfvec nativamente
ALTER TABLE documents
 ALTER COLUMN embedding TYPE halfvec(1536);

CREATE INDEX ON documents
USING hnsw (embedding halfvec_cosine_ops);
```

Reducción de memoria: 50%. Impacto en recall: **-0.8%** (despreciable). Esto es un decisión evidente para usuarios de pgvector.

### Qdrant: Cuantización Binaria con Rescoring

```json
{
 "collection_name": "documents",
 "vectors": {
 "size": 1536,
 "distance": "Cosine",
 "quantization_config": {
 "binary": {
 "always_ram": true
 }
 }
 }
}
```

La cuantización binaria reduce cada float32 a un solo bit. 32x de reducción de memoria. Pero el recall crudo baja a ~85%. El truco es el **rescoring**: Qdrant primero busca en el índice binario para obtener un conjunto de candidatos (digamos, top-100), después re-evalúa ese es candidatos contra los vectores de precisión completa. Recall final: **94.7%** con una fracción de la memoria.

En las pruebas de benchmark:

| Modo Qdrant | Memoria | Latencia p50 | Recall@10 |
| --- | --- | --- | --- |
| Precisión completa | 14.8GB | 3.1ms | 98.2% |
| Binario (sin rescore) | 0.46GB | 1.2ms | 84.9% |
| Binario + rescore 100 | 0.46GB + 14.8GB disco | 4.8ms | 94.7% |
| Escalar (int8) | 3.7GB | 2.8ms | 96.1% |

La cuantización escalar (int8) es el punto dulce para la mayoría: 75% de reducción de memoria con solo 2.1% de pérdida de recall.

## La Pregunta de la Búsqueda Híbrida

Los pipelines RAG reales no hacen solo búsqueda vectorial. Necesitás matching de keywords, filtrado de metadata, y muchas veces ambos combinados.

### pgvector: La Ventaja Injusta

```sql
WITH vector_results AS (
 SELECT id, content,
 1 - (embedding <=> $1::vector) AS vector_score
 FROM documents
 WHERE category = $2
 ORDER BY embedding <=> $1::vector
 LIMIT 20
),
text_results AS (
 SELECT id, content,
 ts_rank(search_vector, plainto_tsquery($3)) AS text_score
 FROM documents
 WHERE category = $2
 AND search_vector @@ plainto_tsquery($3)
 LIMIT 20
)
SELECT COALESCE(v.id, t.id) AS id,
 COALESCE(v.content, t.content) AS content,
 COALESCE(v.vector_score, 0) * 0.7 +
 COALESCE(t.text_score, 0) * 0.3 AS combined_score
FROM vector_results v
FULL OUTER JOIN text_results t ON v.id = t.id
ORDER BY combined_score DESC
LIMIT 10;
```

Esta es la característica más destacada de pgvector: búsqueda híbrida en una sola query, con todo el poder del query planner de PostgreSQL. Sin orquestación externa, sin índice de keywords separado, sin fusión de resultados en código de aplicación.

### Weaviate: Híbrido Built-in

```graphql
{
 Get {
 Document(
 hybrid: {
 query: "configuración SSO Azure AD"
 alpha: 0.7
 fusionType: relativeScoreFusion
 }
 where: {
 path: ["category"]
 operator: Equal
 valueText: "authentication"
 }
 limit: 10
 ) {
 content
 _additional { score }
 }
 }
}
```

Weaviate tiene la mejor historia de búsqueda híbrida entre las bases vectoriales dedicadas. El parámetro ` alpha ` controla el peso vector vs keyword.

## Análisis de Costos (La Parte Que Decide)

Para 2.3M vectores a 1536 dimensiones, corriendo 24/7:

| Base de datos | Costo Mensual | Notas |
| --- | --- | --- |
| pgvector (RDS r7g.xlarge) | $412 | Incluye cómputo + almacenamiento |
| pgvector (Neon Pro) | $69-190 | Escala a cero, pago por query |
| pgvector (Supabase Pro) | $75-200 | Incluye otras features de Postgres |
| Qdrant Cloud (3 nodos) | $720 | Cluster dedicado |
| Qdrant (self-hosted EC2) | $390 | 3x c7g.xlarge |
| Pinecone Serverless | $280-650 | Depende del volumen de queries |
| Weaviate Cloud | $580 | Managed 3 nodos |

pgvector en [Neon](<https://neon.com/>) o [Supabase](<https://supabase.com/>) es absurdamente barato para workloads chicos a medianos. Y como es solo Postgres, no se está pagando un servicio separado, tus vectores viven al lado de tus datos relacionales.

Para workloads de alto throughput (\>1000 QPS sostenido), Qdrant self-hosted en instancias ARM es el ganador en relación precio-performance.

El pricing serverless de Pinecone es atractivo a volúmenes bajos pero escala de forma impredecible. En un caso, los patrones de queries cambiaron y la factura saltó 2.3x.

## Recomendaciones Prácticas

**Para la mayoría de startups y MVPs**: pgvector en Supabase o Neon. Teners una base de datos vectorial y una base relacional en una. La búsqueda híbrida funciona de una. La latencia es suficientemente buena. Siempre es posible migrar después si lo superás, y en la práctica, la mayoría de los productos nunca lo harán.

**Para producción de alto throughput y sensible a latencia**: Qdrant. El engine en Rust es genuinamente más rápido, las opciones de cuantización te dan control fino sobre el tradeoff memoria/recall, y el filtrado está bien integrado. Self-hostealo en instancias Graviton para la mejor relación precio-rendimiento.

**Para equipos que quieren todo managed y no les importa el costo**: Pinecone. Funciona, es simple, y no teners que pensar en infraestructura. Solo sepa que se está pagando un premium por esa simplicidad, y los cold starts serverless resultarán problemáticos.

**Para aplicaciones heavy en búsqueda híbrida**: Weaviate si se desea una DB vectorial dedicada, pgvector si se desea la flexibilidad de SQL.

## La Verdad Incómoda

Aquí va lo que nadie en el espacio de bases vectoriales quiere admitir: para el 90% de las aplicaciones RAG, pgvector es suficiente. Las bases vectoriales dedicadas son más rápidas, pero "más rápido" significa 3ms vs 8ms, ambas son invisibles para el usuario final que está esperando 800ms a que el LLM genere una respuesta.

El diferenciador real es a escala (\>10M vectores), a throughput extremo (\>5000 QPS), o cuando se necesita latencia p99 sub-5ms para aplicaciones en tiempo real. Si esa es la situación, Qdrant o Weaviate valen la complejidad operacional. Si no, y ser honesto sobre si lo es, simplemente utilizar pgvector y dedicar tu tiempo de ingeniería a lo que realmente mueve la aguja: mejores estrategias de chunking, mejores prompts, y mejor evaluación.

La elección aburrida muchas veces es la correcta.

## Preguntas frecuentes

### ¿Debería usar una base de datos vectorial dedicada o simplemente pgvector?

Para la mayoría de las aplicaciones bajo 5M de vectores, pgvector es la elección correcta, evitás complejidad operacional y es posible hacer queries híbridas joineando vectores con datos relacionales. Arriba de 10M de vectores o si se necesita latencia p99 sub-10ms, las bases vectoriales dedicadas empiezan a justificar su complejidad.

### ¿Qué dimensión de embedding debería usar?

Para la mayoría de aplicaciones RAG, 768 o 1024 dimensiones de un modelo como text-embedding-3-small es el punto dulce. Ir a 1536 o 3072 dimensiones rara vez mejora la calidad de retrieval lo suficiente para justificar el costo 2-4x en almacenamiento y latencia.

### ¿Cuánto degrada la calidad de búsqueda vectorial con la cuantización?

Con cuantización escalar (float32 a int8), el recall baja 1-3%. Con cuantización binaria más rescoring, el recall baja solo 2-5% mientras reduce la memoria 32x. La cuantización de producto puede perder 5-10% de recall pero ahorra más espacio.

## Tips

1. **Win de pgvector:** Utilizar índices ` HNSW ` con ` vector_cosine_ops ` y configurar ` hnsw.ef_search = 100 ` a nivel sesión, el default de 40 sacrifica demasiado recall para la mayoría de los case es RAG.
2. **Secreto de cuantización:** La cuantización binaria en Qdrant con rescoring te da el 95% del recall de precisión completa con 32x menos memoria. Configurar ` always_ram: true ` para el índice de rescoring.
3. **Gotcha de Pinecone:** Los índices serverless tienen una penalidad de cold-start de 200-500ms en la primera query después de idle. Si la latencia importa, mantener una query heartbeat corriendo cada 30 segundos.
4. **Truco de costos:** Para datasets bajo 500K vectores, pgvector en una instancia RDS ` db.r7g.large ` supera a toda base vectorial managed en precio y latencia. No complicarse.

- vector-databases
- pgvector
- qdrant
- pinecone
- weaviate
- rag
- embeddings
- hnsw
- ai

[Volver al Blog](<https://lucioduran.com/es/blog>)
