Bases de Datos Vectoriales
Guia practica de bases de datos vectoriales: embeddings, busqueda por similitud, vecinos aproximados mas cercanos, y elegir entre Pinecone, Weaviate, pgvector y Chroma.
Nota para desarrolladores hispanohablantes: Esta guía incluye ejemplos y convenciones de nomenclatura adaptadas a equipos que trabajan en español. Cuando existen diferencias significativas en terminología técnica entre el inglés y el español, se indican explícitamente para facilitar la comunicación en equipos multiculturales.
Overview
Las bases de datos vectoriales almacenan vectores numericos de alta dimension (embeddings) generados por modelos de machine learning y habilitan busqueda por similitud mediante algoritmos de Vecino Mas Cercano Aproximado (ANN). Potencian busqueda semantica, sistemas de recomendacion, recuperacion de imagenes por contenido, y Generacion Aumentada por Recuperacion (RAG) para LLMs. A diferencia de bases de datos tradicionales que buscan por coincidencia exacta o rango, las bases de datos vectoriales encuentran los vectores “mas cercanos” en el espacio de embeddings — la representacion matematica de significado, caracteristicas de imagen o firmas de audio.
When to Use
-
For alternatives, see Complete Guide to Vector Databases.
-
Necesitas busqueda semantica (encontrar significado similar, no solo coincidencia de palabras clave)
-
Los pipelines RAG de LLMs requieren recuperar chunks de contexto relevantes
-
Sistemas de recomendacion sugieren items similares a preferencias de usuario
-
Recuperacion de imagen, audio o video por similitud de contenido
-
Tienes modelos de embedding pre-entrenados y necesitas almacenamiento vectorial preparado para crecimiento
Como Funciona la Busqueda Vectorial
- Embedding: Un modelo (OpenAI, BERT, CLIP) convierte texto/imagen en un vector denso (ej. 768-1536 dimensiones)
- Indexacion: Los vectores se organizan en un indice ANN (HNSW, IVF, PQ) para recuperacion rapida
- Consulta: La consulta se embebe y el indice retorna los K vecinos mas cercanos
- Filtrado de metadata: Combinar similitud vectorial con filtrado tradicional (fecha, categoria, ID de usuario)
Comparacion
| Base de datos | Despliegue | Indice | Mejor para |
|---|---|---|---|
| Pinecone | Nube gestionada | HNSW, filtros metadata | RAG en produccion, sin overhead de ops |
| Weaviate | Auto-gestionado / nube | HNSW, BM25 hibrido | Multi-modal, interfaz GraphQL |
| pgvector | Extension PostgreSQL | ivfflat, hnsw | Equipos ya en Postgres |
| Chroma | Embebido / local | HNSW | Prototipado, RAG local a pequena escala |
| Milvus/Zilliz | Auto-gestionado / nube | IVF, HNSW, GPU | Gran escala, alto throughput |
Ejemplo pgvector
-- Habilitar extension pgvector
CREATE EXTENSION IF NOT EXISTS vector;
-- Crear tabla con columna vectorial
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
title TEXT NOT NULL,
content TEXT,
embedding vector(1536)
);
-- Crear indice HNSW para busqueda ANN rapida
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);
-- Insertar documento con embedding
INSERT INTO documents (title, content, embedding)
VALUES ('Guia de Bases Vectoriales', 'Una guia sobre bases de datos vectoriales...', '[0.12, -0.03, ...]');
-- Busqueda semantica: encontrar 5 documentos mas similares
SELECT id, title, content,
1 - (embedding <=> '[0.11, -0.02, ...]') as similarity
FROM documents
ORDER BY embedding <=> '[0.11, -0.02, ...]'
LIMIT 5;
Busqueda Hibrida (Vectorial + Palabras Clave)
# Weaviate: combinar similitud vectorial con busqueda BM25
import weaviate
client = weaviate.connect_to_local()
results = client.collections.get("Article").query.hybrid(
query="arquitectura base de datos vectorial",
vector=[0.12, -0.03, ...],
alpha=0.5, # 0 = puro BM25, 1 = puro vectorial
limit=10
)
Ejemplo de Pipeline RAG
from openai import OpenAI
import chromadb
# 1. Cargar y fragmentar documentos
chunks = load_and_chunk_documents("knowledge_base/")
# 2. Embeber y almacenar en Chroma
client = chromadb.Client()
collection = client.create_collection("docs")
embeddings = openai_client.embeddings.create(input=chunks, model="text-embedding-3-small")
collection.add(ids=ids, documents=chunks, embeddings=[e.embedding for e in embeddings.data])
# 3. Recuperar chunks relevantes para una consulta
query_embedding = openai_client.embeddings.create(input="Como funcionan los indices vectoriales?", model="text-embedding-3-small")
results = collection.query(query_embeddings=[query_embedding.data[0].embedding], n_results=5)
# 4. Aumentar prompt del LLM con contexto recuperado
context = "\n".join([r["document"] for r in results["documents"][0]])
prompt = f"Contexto:\n{context}\n\nPregunta: Como funcionan los indices vectoriales?"
response = openai_client.chat.completions.create(model="gpt-4o", messages=[{"role": "user", "content": prompt}])
Algoritmos ANN
| Algoritmo | Tipo | Velocidad | Memoria | Mejor para |
|---|---|---|---|---|
| HNSW | Basado en grafos | Rapido | Alta | Proposito general, alta recall |
| IVF | Clustering | Media | Media | Grandes datasets, limitado de memoria |
| PQ | Cuantizacion | Rapido | Baja | Billones de vectores, recall aceptable |
Common Mistakes
- Metrica de distancia incorrecta — similitud coseno para texto semantico, euclidiana para caracteristicas de imagen, producto punto para embeddings normalizados
- Sin filtrado de metadata — busqueda puramente vectorial retorna resultados irrelevantes; siempre combinar con filtros de metadata
- Ignorar ajuste de indice — parametros HNSW por defecto pueden no ajustarse a tus requisitos de recall/latencia
- Almacenar vectores raw sin indice — escaneo completo de fuerza bruta es O(n) e inusable a escala
- Usar una base vectorial para consultas estructuradas — combinar con una base relacional; las bases vectoriales son malas en agregacion y joins
Troubleshooting
- Query is slow after an index change: check execution plans and cardinality estimates. Rebuild statistics and verify the index is being used.
- Replication lag grows: monitor network, disk I/O, and long transactions. Split large writes and consider parallel replication.
- Connections exhausted: review connection pool size, idle timeouts, and leaked connections. Use prepared statements and close connections in finally blocks.
- Backup takes too long: enable compression, incremental backups, and off-peak scheduling. Test restore times against RTO targets.
- Deadlocks in high concurrency: access tables and rows in a consistent order. Keep transactions short and retry deadlocked operations.
FAQ
Necesito una base de datos vectorial dedicada o puedo usar Postgres?
Para escala pequena a media (< 1M vectores) y equipos ya en Postgres, pgvector es suficiente. Para alta escala, multi-tenant o gestionada, Pinecone o Weaviate son mejores.
Como elijo dimensiones de embedding? Usa la dimension de salida de tu modelo elegido (OpenAI text-embedding-3-small = 1536, BERT-base = 768). No reduzcas dimensiones arbitrariamente sin entrenamiento consciente de cuantizacion.
Puedo actualizar vectores en su lugar? Si, pero puede requerir re-indexacion dependiendo de la base de datos y tipo de indice. Algunos sistemas soportan actualizaciones incrementales; otros requieren reconstruccion completa.
¿Cómo empiezo con esto en un proyecto existente?
Empieza con una parte pequeña y aislada de tu codebase. Aplica los conceptos de esta guía a un módulo o servicio. Mide el impacto, luego expande a otras áreas.
¿Qué herramientas necesito?
Las herramientas mencionadas throughout esta guía se listan en cada sección. La mayoría son open-source y ampliamente adoptadas. Consulta los recursos relacionados para instrucciones de setup.
¿Cómo mido el éxito después de implementar esto?
Define métricas claras antes de empezar: benchmarks de rendimiento, tasas de error o indicadores de mantenibilidad. Compara antes y después. Itera basándote en datos, no en suposiciones.
Temas Avanzados
Escenario Detallado: Sistema RAG para Documentacion Tecnica
Sistema: Chatbot RAG sobre 50,000 paginas de documentacion tecnica
Stack: OpenAI text-embedding-3-small (1536 dim) + pgvector + GPT-4o
Requisitos: Respuestas precisas con citas, latencia < 3s
Pipeline:
1. Cargar documentos (PDF, Markdown, HTML)
2. Fragmentar en chunks de ~500 tokens con overlap de 50
3. Generar embeddings con OpenAI
4. Almacenar en PostgreSQL con pgvector
5. En consulta: embeber pregunta, buscar chunks similares, aumentar LLM
Esquema pgvector:
CREATE EXTENSION IF NOT EXISTS vector;
CREATE TABLE doc_chunks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
doc_id VARCHAR(100) NOT NULL,
chunk_index INT NOT NULL,
content TEXT NOT NULL,
embedding vector(1536) NOT NULL,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Indice HNSW para busqueda ANN
CREATE INDEX idx_doc_chunks_embedding
ON doc_chunks USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);
-- Indice para filtrado por documento
CREATE INDEX idx_doc_chunks_doc ON doc_chunks(doc_id);
Ingestion (Python):
from openai import OpenAI
import psycopg2
client = OpenAI()
conn = psycopg2.connect("dbname=ragdb")
def embed_text(text: str) -> list[float]:
resp = client.embeddings.create(
input=text, model="text-embedding-3-small"
)
return resp.data[0].embedding
def ingest_document(doc_id: str, chunks: list[str]):
for i, chunk in enumerate(chunks):
emb = embed_text(chunk)
with conn.cursor() as cur:
cur.execute(
"INSERT INTO doc_chunks (doc_id, chunk_index, content, embedding) "
"VALUES (%s, %s, %s, %s)",
(doc_id, i, chunk, emb)
)
conn.commit()
Consulta RAG:
def rag_query(question: str, top_k: int = 5) -> str:
q_emb = embed_text(question)
with conn.cursor() as cur:
cur.execute(
"SELECT content, doc_id, chunk_index, "
"1 - (embedding <=> %s) AS similarity "
"FROM doc_chunks "
"ORDER BY embedding <=> %s "
"LIMIT %s",
(q_emb, q_emb, top_k)
)
results = cur.fetchall()
context = "\n\n".join([r[0] for r in results])
sources = [f"doc:{r[1]} chunk:{r[2]} sim:{r[3]:.3f}" for r in results]
prompt = (
f"Contexto:\n{context}\n\n"
f"Pregunta: {question}\n"
f"Responde basandote en el contexto. Cita la fuente."
)
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}]
)
return response.choices[0].message.content + "\n\nFuentes: " + ", ".join(sources)
Resultados:
| Metrica | Valor |
|---------|-------|
| Tiempo de embedding | 200ms |
| Tiempo de busqueda vectorial | 15ms |
| Tiempo de LLM | 1.5s |
| Latencia total | ~1.7s |
| Recall@5 | 92% |
| Precision de respuestas | 87% (con citas correctas) |
Optimizacion de indice HNSW:
- m=16: balance entre recall y memoria (default)
- ef_construction=64: calidad de construccion (mayor = mejor, mas lento)
- ef_search=40: ajustar en consulta para trade-off recall/latencia
- Para 50K vectores: 50MB de indice, busqueda < 20ms
Lecciones aprendidas:
- pgvector es suficiente para < 1M vectores
- El tamano de chunk afecta la calidad: 500 tokens con overlap funciona bien
- Filtrar por metadata antes de la busqueda vectorial mejora relevancia
- HNSW supera a IVF en recall para datasets pequenos-medianos
Como manejo actualizaciones de embeddings cuando cambia el modelo?
Versiona los embeddings: almacena el modelo y la version en metadata. Cuando cambies de modelo, re-embebe todos los documentos en una nueva columna o tabla. Manten ambas versiones durante la transicion. Actualiza las consultas para usar la nueva version. Elimina la vieja cuando no haya trafico. Programa re-embedding en lotes durante horas de baja carga para evitar impactar latencia.
End of document. Review and update quarterly.
Errores Comunes en Producción
- Tratar la guía como un checklist para completar una vez en lugar de una práctica por evolucionar.
- Adoptar cada recomendación de golpe en lugar de comenzar con un cambio medido.
- Saltar la evaluación de madurez e imponer prácticas avanzadas a un equipo no preparado.
- No actualizar runbooks y expectativas de guardia al introducir nuevas prácticas.
- Ignorar datos reales de incidentes al priorizar qué partes de la guía aplicar primero.
- No asignar un responsable que revise decisiones trimestralmente.
- Copiar ejemplos sin adaptarlos a las herramientas y restricciones reales del equipo.
- Olvidar medir resultados antes de agregar la siguiente mejora.
Recursos Relacionados
Bases de Datos de Grafos
Guia practica de bases de datos de grafos: modelo de grafo de propiedades, lenguaje Cypher, patrones de modelado y cuando elegir Neo4j sobre bases relacionales.
GuidePatrones de Modelado NoSQL
Guia practica de modelado NoSQL: embebido vs referenciado, diseno basado en patrones de acceso, y patrones para MongoDB, DynamoDB, Cassandra y Redis.
RecipeAnálisis de Sentimiento con Python y NLTK
Puntúa el sentimiento de texto usando NLTK VADER y léxicos personalizados en Python.