Inicio / Inteligencia Artificial / AI Engineering Pro / Vector Databases en Profundidad

Vector Databases en Profundidad

Pinecone, Weaviate, Qdrant, pgvector: comparativa y casos de uso.

Avanzado
🔒 Solo lectura
📖

Estás en modo lectura

Puedes leer toda la lección, pero para marcar progreso, hacer ejercicios y ganar XP necesitas una cuenta Pro.

Desbloquear por $9/mes

Vector Databases: Pinecone, Weaviate, Qdrant y pgvector

¿Qué es una Vector Database?

Una base de datos vectorial almacena, indexa y busca embeddings (vectores de alta dimensionalidad) de forma eficiente. Es el componente central de cualquier pipeline RAG.

Texto → Embedding Model → Vector [0.12, -0.45, 0.78, ...] → Vector DB
                                     (1536 dimensiones)

Distancia entre Vectores

Métrica Fórmula Uso
Cosine Similarity cos(θ) = A·B / (|A||B|) Texto, embeddings normalizados
Euclidean (L2) √Σ(aᵢ-bᵢ)² Clusters, imágenes
Dot Product Σ(aᵢ·bᵢ) Embeddings no normalizados

Algoritmos de Indexación

HNSW (Hierarchical Navigable Small World)

El más usado en producción. Crea un grafo multi-capa para búsqueda aproximada.

Capa 3:  ○ ──────────── ○            (pocos nodos, saltos largos)
Capa 2:  ○ ──── ○ ──── ○ ──── ○     (más nodos)
Capa 1:  ○ ─ ○ ─ ○ ─ ○ ─ ○ ─ ○ ─ ○  (todos los nodos)

Búsqueda: Empieza arriba, baja refinando
Parámetro Efecto
M (connections) Más = mejor recall, más memoria
ef_construction Más = mejor índice, más lento de construir
ef_search Más = mejor recall, más lento búsqueda

IVF (Inverted File Index)

Divide el espacio en clusters. Busca solo en los clusters más cercanos.

Cluster 1: [v1, v5, v12, ...]
Cluster 2: [v2, v8, v15, ...]
Cluster 3: [v3, v7, v22, ...]

Query → Encuentra clusters cercanos → Busca dentro de ellos

Pinecone

Base de datos vectorial serverless. Sin infraestructura que administrar.

from pinecone import Pinecone, ServerlessSpec

pc = Pinecone(api_key="your-api-key")

# Crear índice
pc.create_index(
    name="knowledge-base",
    dimension=1536,              # Debe coincidir con las dimensiones del modelo de embedding (ej: text-embedding-3-small = 1536)
    metric="cosine",             # Similitud coseno: ideal para texto, mide ángulo entre vectores (ignora magnitud)
    spec=ServerlessSpec(         # Configuración del proveedor cloud — Pinecone gestiona la infra por ti
        cloud="aws",
        region="us-east-1",
    ),
)

index = pc.Index("knowledge-base")

# Upsert vectores (upsert = insert + update: si el ID ya existe, lo actualiza; si no, lo inserta)
index.upsert(
    vectors=[
        {
            "id": "doc-1",
            "values": embedding_vector,
            "metadata": {
                "source": "manual.pdf",
                "page": 5,
                "topic": "authentication",
            },
        },
    ],
    namespace="technical-docs",  # Partición lógica dentro del índice — permite separar datos sin crear índices separados
)

# Buscar
results = index.query(
    vector=query_embedding,
    top_k=5,                     # Retorna los 5 vectores más similares al query
    include_metadata=True,       # Incluye la metadata de cada resultado (source, page, topic, etc.)
    filter={                     # Pre-filtrado por metadata ANTES de la búsqueda vectorial
        "topic": {"$eq": "authentication"},  # $eq = igual. Otros: $ne, $gt, $gte, $lt, $lte, $in, $nin
    },
    namespace="technical-docs",
)

for match in results.matches:
    print(f"Score: {match.score:.4f} | {match.metadata}")

Pros: Serverless, fácil de escalar, filtros de metadata potentes Contras: Vendor lock-in, costo puede escalar rápido, no self-hosted

Weaviate

Vector DB open-source con búsqueda híbrida (vectorial + keyword).

import weaviate
from weaviate.classes.config import Configure, Property, DataType
from weaviate.classes.query import MetadataQuery, Filter

client = weaviate.connect_to_local()  # o connect_to_weaviate_cloud()

# Crear collection con vectorizer integrado
collection = client.collections.create(
    name="Document",
    vectorizer_config=Configure.Vectorizer.text2vec_openai(
        model="text-embedding-3-large"
    ),
    properties=[
        Property(name="content", data_type=DataType.TEXT),
        Property(name="source", data_type=DataType.TEXT),
        Property(name="page", data_type=DataType.INT),
    ],
)

# Insertar (vectoriza automáticamente)
collection.data.insert({
    "content": "JWT authentication requires...",
    "source": "api-docs.md",
    "page": 12,
})

# Búsqueda híbrida (vector + BM25 keyword)
results = collection.query.hybrid(
    query="JWT authentication setup",
    alpha=0.7,  # 0=keyword puro, 1=vector puro, 0.7=balance
    limit=5,
    return_metadata=MetadataQuery(score=True),
    filters=Filter.by_property("source").equal("api-docs.md"),
)

Pros: Open-source, búsqueda híbrida, vectorización integrada, GraphQL API Contras: Más complejo de operar, mayor consumo de memoria

Qdrant

Escrito en Rust. Alto rendimiento y filtrado avanzado.

from qdrant_client import QdrantClient
from qdrant_client.models import (
    Distance, VectorParams, PointStruct,
    Filter, FieldCondition, MatchValue,
)

client = QdrantClient(host="localhost", port=6333)

# Crear colección
client.create_collection(
    collection_name="knowledge_base",
    # VectorParams: configuración del espacio vectorial
    #   size=1536 → dimensiones del vector (debe coincidir con el modelo de embedding)
    #   distance=Distance.COSINE → métrica de distancia (COSINE, EUCLID, DOT)
    vectors_config=VectorParams(size=1536, distance=Distance.COSINE),
)

# Insertar
client.upsert(
    collection_name="knowledge_base",
    points=[
        PointStruct(             # PointStruct = un punto en el espacio vectorial: id + vector + payload
            id=1,
            vector=embedding_vector,
            payload={            # payload = metadata almacenada junto al vector (filtrable y retornable)
                "content": "JWT authentication...",
                "source": "api-docs.md",
                "category": "security",
                "timestamp": "2026-01-15",
            },
        ),
    ],
)

# Buscar con filtros
results = client.query_points(
    collection_name="knowledge_base",
    query=query_vector,
    limit=5,
    query_filter=Filter(
        # must = AND (todos deben cumplirse). También: should = OR, must_not = NOT
        must=[
            # FieldCondition: filtra por un campo del payload
            # MatchValue: coincidencia exacta del valor
            FieldCondition(key="category", match=MatchValue(value="security")),
        ]
    ),
)

Pros: Muy rápido (Rust), filtrado expresivo, quantización nativa, open-source Contras: Ecosistema más pequeño, menos integraciones cloud-managed

pgvector: Vectores en PostgreSQL

Extensión que añade capacidades vectoriales a PostgreSQL. Ideal cuando ya usas Postgres.

Parámetros clave de pgvector:

  • HNSW index: m = 16 controla conexiones por nodo (más = mejor recall, más memoria), ef_construction = 200 controla calidad de construcción del índice (más = mejor índice, más lento de construir)
  • vector_cosine_ops: clase de operador que indica a PostgreSQL usar distancia coseno para este índice
  • Operador <=>: calcula la distancia coseno entre dos vectores (0 = idénticos, 2 = opuestos)
  • 1 - (embedding <=> ...): convierte distancia en similitud (1 = idénticos, -1 = opuestos), porque <=> retorna distancia, no similitud
-- Habilitar extensión
CREATE EXTENSION vector;

-- Crear tabla con columna vectorial
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    content TEXT NOT NULL,
    source VARCHAR(255),
    embedding vector(1536),     -- Vector de 1536 dimensiones
    created_at TIMESTAMP DEFAULT NOW()
);

-- Crear índice HNSW para búsqueda eficiente
-- m = 16: conexiones por nodo en el grafo HNSW (default 16, rango típico 12-48)
-- ef_construction = 200: nodos candidatos durante construcción (más alto = mejor recall, más lento)
CREATE INDEX ON documents
    USING hnsw (embedding vector_cosine_ops)   -- vector_cosine_ops: usar distancia coseno para el índice
    WITH (m = 16, ef_construction = 200);

-- Insertar
INSERT INTO documents (content, source, embedding)
VALUES ('JWT authentication...', 'api-docs.md', '[0.12, -0.45, ...]');

-- Buscar por similitud coseno
-- <=> es el operador de distancia coseno (no similitud)
-- 1 - distancia = similitud (rango: -1 a 1, donde 1 = idénticos)
SELECT content, source,
       1 - (embedding <=> $1::vector) AS similarity
FROM documents
WHERE source = 'api-docs.md'
ORDER BY embedding <=> $1::vector
LIMIT 5;
# Uso con SQLAlchemy
from pgvector.sqlalchemy import Vector
from sqlalchemy import Column, Integer, String, Text, create_engine
from sqlalchemy.orm import declarative_base, Session

Base = declarative_base()

class Document(Base):
    __tablename__ = "documents"
    id = Column(Integer, primary_key=True)
    content = Column(Text)
    source = Column(String(255))
    embedding = Column(Vector(1536))

# Buscar
with Session(engine) as session:
    results = session.query(Document).order_by(
        Document.embedding.cosine_distance(query_vector)
    ).limit(5).all()

Pros: Sin infraestructura adicional, SQL nativo, ACID, joins con datos relacionales Contras: Menos rendimiento a gran escala, sin búsqueda híbrida nativa

Comparativa de Vector Databases

Característica Pinecone Weaviate Qdrant pgvector
Hosting Serverless Self/Cloud Self/Cloud Self (Postgres)
Lenguaje Managed Go Rust C (extensión)
Búsqueda Híbrida No Sí (BM25+vector) Sparse vectors No
Filtrado Bueno Bueno Excelente SQL
Escalabilidad Excelente Buena Buena Moderada
Latencia (p99) ~50ms ~30ms ~20ms ~100ms
Costo $$$ $$ (self-hosted) $$ (self-hosted) $ (ya tienes PG)
Ideal para MVP rápido Búsqueda híbrida Alto rendimiento Ya usas Postgres

Estrategias de Indexación por Escala

< 100K docs    → pgvector (simple, económico)
100K - 1M docs → Qdrant o Weaviate self-hosted
1M - 10M docs  → Pinecone serverless o Qdrant Cloud
> 10M docs     → Pinecone + sharding o solución custom

Mejores Prácticas

  1. Siempre incluir metadata rica — fuente, fecha, categoría, idioma
  2. Indexar con namespace/collections — separar por dominio
  3. Monitorear recall — medir calidad de búsqueda regularmente
  4. Quantización — reduce memoria 4x con pérdida mínima
  5. Backup regular — las vector DBs no son inmunes a fallos
  6. Dimensiones justas — no usar 3072 dims si 512 da similar recall

🧠 Preguntas de Repaso

1. ¿Cuál de las siguientes vector databases tiene la menor latencia p99 y está escrita en Rust?

  • A) Pinecone (~50ms, managed)
  • B) Weaviate (~30ms, Go)
  • C) Qdrant (~20ms, Rust)
  • D) pgvector (~100ms, C)

Respuesta: C) — Qdrant, escrita en Rust, ofrece la latencia p99 más baja (~20ms) entre las cuatro options comparadas. Su diseño en Rust le da alto rendimiento y seguridad de memoria.

2. ¿Qué ventaja única ofrece Weaviate sobre las demás vector databases comparadas?

  • A) Es la más económica
  • B) Tiene búsqueda híbrida nativa (vector + BM25 keyword) con parámetro alpha configurable
  • C) Es la única que soporta GPU
  • D) Tiene el mayor límite de documentos

Respuesta: B) — Weaviate ofrece búsqueda híbrida nativa combinando vector search con BM25 keyword search. El parámetro alpha controla el balance: 0 = keyword puro, 1 = vector puro, 0.7 = balance recomendado.

3. Para un proyecto con menos de 100,000 documentos, ¿cuál es la recomendación de vector database?

  • A) Pinecone serverless por su escalabilidad
  • B) pgvector, ya que aprovecha PostgreSQL existente y es la más económica
  • C) Qdrant Cloud por su baja latencia
  • D) Weaviate por su búsqueda híbrida

Respuesta: B) — Para menos de 100K documentos, pgvector es la recomendación porque aprovecha la infraestructura PostgreSQL existente, es la más económica ($), y a esa escala su latencia (~100ms) es aceptable.

4. En el algoritmo HNSW, ¿qué controla el parámetro M?

  • A) El número máximo de resultados retornados
  • B) El número de conexiones por nodo en el grafo: más M = mejor recall pero más memoria
  • C) El tamaño del batch de indexación
  • D) La distancia métrica utilizada (cosine, euclidean, etc.)

Respuesta: B) — El parámetro M en HNSW controla el número de conexiones por nodo en el grafo multi-capa. Valores más altos de M mejoran el recall (calidad de búsqueda) pero aumentan el consumo de memoria.

¿Te gustó esta lección?

Con Pro puedes marcar progreso, hacer ejercicios, tomar quizzes, ganar XP y obtener tu constancia.

Ver planes desde $9/mes