Comparativa de bases de datos vectoriales: cuándo realmente necesitas una
La última vez, Rae aprendió qué son los embeddings —cómo convierten el texto en coordenadas que capturan el significado y por qué superan a la búsqueda por palabras clave para los documentos de ayuda de su bot de soporte—. Vio que la similitud del coseno podía hacer coincidir la pregunta de un cliente con el artículo de ayuda correcto incluso cuando no compartían ninguna palabra. Pero se quedó con un problema práctico: con miles de fragmentos de documentos de ayuda para buscar, ¿cómo almacena y consulta todos estos vectores rápidamente?
Digamos que Rae está construyendo una biblioteca para la documentación del producto de su empresa. En una biblioteca tradicional, los libros se archivan por título o autor. Quieres “El gran Gatsby”, vas a la sección ‘F’ de Fitzgerald. Así es como funcionan las bases de datos SQL: coincidencias exactas o rangos específicos.
Pero, ¿qué pasa si un cliente entra y dice: “Quiero un libro que transmita la sensación de una tarde de lluvia solitaria en París”? Un índice estándar no te puede ayudar en ese caso. Necesitas entender el significado detrás de la solicitud. Este es el mundo de los embeddings y las bases de datos vectoriales, y es el siguiente problema que Rae necesita resolver para sus miles de fragmentos embebidos de documentos de ayuda.
1. El problema: por qué tu base de datos normal se siente lenta
Los embeddings convierten texto o imágenes en listas largas de números — vectores. Para encontrar el elemento más similar, calculas la distancia entre tu vector de búsqueda y cada vector en la base de datos.
Las bases de datos SQL estándar no están diseñadas para esto. Un índice B-Tree maneja price < 20 bien, pero no tiene idea de qué hacer con un vector de 1536 dimensiones. Sin un índice especializado, la base de datos recurre a un Full Table Scan.
Aquí hay una búsqueda ingenua en solo 10,000 elementos en Python estándar.
import numpy as np
import time
# Create 10,000 random vectors (1536 dimensions, like OpenAI embeddings)
data = np.random.rand(10000, 1536).astype('float32')
query_vector = np.random.rand(1536).astype('float32')
def naive_search(query, library):
# Calculate cosine similarity manually for every item
# This is an O(n) operation
similarities = np.dot(library, query) / (np.linalg.norm(library, axis=1) * np.linalg.norm(query))
return np.argsort(similarities)[-5:]
start = time.time()
results = naive_search(query_vector, data)
end = time.time()
print(f"Search took: {(end - start) * 1000:.2f} ms")
En mi máquina, esto se ejecuta en aproximadamente 40-60ms — no está mal para 10,000 elementos. Pero escala a 1 millón y estarás viendo de 4 a 6 segundos. ¿Tienes 1,000 usuarios buscando a la vez? Tu servidor se derrite. La matemática detrás de la búsqueda de vectores es simple; la escala es lo que duele.
2. Qué hacen realmente las bases de datos vectoriales
Una base de datos vectorial no es simplemente un depósito de almacenamiento. Es un motor especializado que hace tres cosas:
- Almacenamiento: Almacena arreglos numéricos densos de manera eficiente.
- Indexación: Utiliza algoritmos de “Approximate Nearest Neighbor” (ANN) como HNSW (Hierarchical Navigable Small World). Piensa en un mapa de metro que te permite saltarte paradas para llegar rápido cerca de tu destino.
- Filtrado de metadatos: Te permite decir: “Encuéntrame imágenes similares, pero SOLO de la categoría ‘Naturaleza’”.
Así es como consultarías una base de datos vectorial frente a una base de datos convencional con la extensión pgvector.
# Hypothetical comparison of API complexity
# 1. pgvector (SQL approach)
# "SELECT * FROM items ORDER BY embedding <=> '[0.1, 0.2...]' LIMIT 5 WHERE category = 'books'"
# 2. Qdrant (Vector DB approach)
# client.search(
# collection_name="my_items",
# query_vector=[0.1, 0.2, ...],
# query_filter=Filter(must=[FieldCondition(key="category", match=MatchValue(value="books"))]),
# limit=5
# )
Las bases de datos vectoriales manejan la cláusula “Where” y la búsqueda de similitud al mismo tiempo. Las bases de datos convencionales a menudo tienen dificultades para optimizar ambos en conjunto.
3. Los compromisos: velocidad vs. simplicidad vs. costo
Tienes tres caminos principales. Los números cuentan la historia.
| Característica | En memoria (FAISS) | PostgreSQL (pgvector) | Base de datos vectorial (Qdrant/Pinecone) |
|---|---|---|---|
| Latencia | < 1ms | 100-500ms | 10-50ms |
| Complejidad | Baja (solo un archivo) | Media (base de datos existente) | Alta (nuevo servicio) |
| Escala | Diminuta (limitada por RAM) | Media (Millones) | Masiva (Miles de millones) |
Aquí tienes una rápida simulación de benchmark que compara los tres.
# Simulating the latency trade-offs
results = {
"FAISS (In-Memory)": "0.8ms - Blazing fast, but loses data if script crashes",
"pgvector (Postgres)": "120ms - Convenient, uses your existing database",
"Qdrant (Dedicated)": "15ms - Optimized for high-speed production use"
}
for system, stat in results.items():
print(f"{system}: {stat}")
4. Cuándo vale la pena una base de datos vectorial
No compres un camión semi-remolque para mover una sola caja. Con menos de 100,000 documentos, probablemente no necesites una base de datos vectorial especializada.
Vale la pena si:
- Necesitas latencias inferiores a 100ms: Cuando tu aplicación se siente lenta, es posible que Postgres sea el cuello de botella.
- Alto volumen de consultas: Miles de personas buscando al mismo tiempo.
- Metadatos complejos: Necesitas filtrar por 10 atributos diferentes mientras buscas por similitud.
5. Un ejemplo real: construyendo una función de búsqueda semántica
Digamos que estamos construyendo un buscador para una aplicación de recetas.
Etapa 1: El Prototipo (FAISS) Comienzas con 5,000 recetas. FAISS es gratuito y vive directamente en tu script de Python. Es rápido. Pero añadir una receta significa reconstruir todo el índice.
Etapa 2: Crecimiento (pgvector)
Llegas a 50,000 recetas y quieres una base de datos real. Añades pgvector a tu instancia de Postgres. Ahora tienes copias de seguridad y transacciones. Sin embargo, al superar 100,000, el uso de tu CPU se dispara durante las búsquedas.
Etapa 3: Las Grandes Ligas (Qdrant/Pinecone) Tienes 1 millón de recetas y 100,000 usuarios. Es momento de una base de datos vectorial dedicada.
# Example of how a recommendation recommendation changes based on scale
def recommend_storage(doc_count, queries_per_sec):
if doc_count < 10000 and queries_per_sec < 5:
return "Use FAISS or simple Numpy"
elif doc_count < 100000:
return "Use pgvector (Postgres)"
else:
return "Use a dedicated Vector DB (Qdrant/Weaviate/Pinecone)"
print(f"Recommendation for 500k docs: {recommend_storage(500000, 50)}")
6. Panorama de bases de datos vectoriales: ¿cuál elegir?
- Pinecone: El “botón fácil”. Es totalmente administrado, pero los costos pueden escalar rápidamente.
- Qdrant: Rápido y de código abierto. Una opción sólida si quieres autohospedarlo.
- Weaviate: Construido sobre GraphQL, y una buena opción para estructuras de datos complejas.
- pgvector: La opción natural si ya estás en Postgres y aún no tienes una escala masiva.
¿Qué almacenamiento vectorial debería usar Rae en una startup pequeña?
FAISS (en memoria, archivo local) — Usa esto para la creación de prototipos y el desarrollo local. Si Rae está probando su pipeline de recuperación en su laptop con unos pocos cientos de fragmentos, FAISS es perfecto: cero infraestructura, búsquedas submilisegundo, sin dependencias más allá de pip install faiss-cpu. Pero vive en la RAM: si su script falla, el índice desaparece. Sin filtrado de metadatos, sin persistencia, sin concurrencia.
pgvector (extensión de Postgres) — El punto ideal para la mayoría de las startups en fase inicial, incluida Rae ahora mismo. Si ella ya tiene una base de datos de Postgres (y la mayoría de las startups la tienen), pgvector añade búsqueda de similitud vectorial sin levantar un nuevo servicio. Obtiene transacciones, copias de seguridad, joins con sus tablas existentes y la familiar interfaz SQL. El compromiso: con alrededor de 100k–500k vectores y una carga de consultas pesada, las búsquedas se ralentizan a 100–500ms porque Postgres no fue diseñado para cargas de trabajo ANN de alta dimensionalidad.
Qdrant / Pinecone / Weaviate (base de datos vectorial dedicada) — Recurre a estas opciones cuando pgvector comience a ceder bajo la carga—generalmente cuando superas los ~500k vectores, necesitas una latencia sub-50ms con alta concurrencia, o quieres funciones integradas como búsqueda híbrida y sharding. Pinecone es totalmente administrado (sin DevOps) pero se vuelve caro rápidamente. Qdrant es de código abierto y autohospedable, lo que se ajusta al presupuesto de Rae pero requiere que alguien cuide la infraestructura. Weaviate ofrece consultas basadas en GraphQL para esquemas complejos.
Recomendación actual de Rae: Comienza con pgvector. Ella ya ejecuta Postgres para los datos de usuario de su aplicación, así que añadir una columna vectorial no implica nueva infraestructura. Si el tráfico de su bot tiene picos y pgvector no da abasto, puede migrar a Qdrant (autohospedado, gratuito) sin cambiar su pipeline de embeddings—solo la capa de almacenamiento.
Cuándo evitar por completo una base de datos vectorial dedicada:
- Si tienes menos de 100k vectores y un volumen de consultas modesto—pgvector es más simple y económico.
- Si no tienes personal de DevOps—gestionar un servicio de base de datos independiente es un costo oculto.
- Si necesitas transacciones ACID en tus datos vectoriales y relacionales—dividirlos en dos almacenes introduce los problemas de sincronización descritos en la Sección 7.
7. Los inconvenientes que nadie menciona
Las bases de datos vectoriales no son mágicas. Dos compromisos a tener en cuenta:
- Deriva de embeddings: Cambia de modelos de embeddings —de OpenAI a Cohere, por ejemplo— y tienes que recalcular cada vector en tu base de datos. Eso es una reelaboración importante.
- Sincronización de metadatos: Actualiza el nombre de un usuario en Postgres, y también necesitas actualizarlo en tu base de datos vectorial. Si omites este paso, tus filtros serán incorrectos.
# The Sync Problem
postgres_user = {"id": 1, "status": "inactive"}
vector_db_user = {"id": 1, "status": "active"} # Oops! Out of sync.
if postgres_user['status'] != vector_db_user['status']:
print("Warning: Your Vector DB is returning 'inactive' users because of a sync lag!")
8. Marco de decisión: ¿deberías usar una?
Hazte tres preguntas:
- ¿Tengo más de 100,000 elementos?
- ¿Mi búsqueda tarda más de 200ms?
- ¿Tengo a una persona de DevOps que pueda administrar otra base de datos?
Si las tres respuestas son no, quédate con Postgres o con una búsqueda simple en memoria.
9. Lo que sigue: búsqueda híbrida y más allá
La búsqueda vectorial es excelente para las “vibras” pero tiene problemas con palabras específicas. Busca “iPhone 15” y una búsqueda vectorial podría devolver “Samsung Galaxy” porque son semánticamente similares.
A continuación: Búsqueda híbrida. Combinaremos el “significado” de la búsqueda vectorial con la “exactitud” de la búsqueda por palabras clave.
Lista de verificación resumida:
- Usa FAISS para scripts locales y prototipos pequeños.
- Usa pgvector para la mayoría de las startups en fase inicial.
- Usa Qdrant/Pinecone cuando llegues a millones de filas o necesites velocidad extrema.
Rae ha tomado su decisión: pgvector. Ya ejecuta Postgres para los datos de usuario de su aplicación, así que añadir una columna vectorial supone cero nueva infraestructura. Con el almacenamiento resuelto, está lista para construir el sistema real: no solo recuperación, sino un pipeline RAG completo que divide el manual de su producto en fragmentos, genera los embeddings de cada fragmento, recupera los correctos cuando un cliente hace una pregunta y los alimenta a un LLM para generar una respuesta. Eso es lo que construye a continuación.
Comprueba tu comprensión
Las preguntas a continuación van desde un simple recuerdo hasta un diseño abierto, siguiendo aproximadamente la Taxonomía de Bloom.
Recordar ¿Cuáles son las tres cosas que hace una base de datos vectorial, según la Sección 2 del artículo?
Comprender
En tus propias palabras, explica por qué un índice B-Tree estándar (ideal para price < 20) no puede ayudar con una búsqueda de similitud sobre vectores de 1536 dimensiones.
Aplicar
Usando la función recommend_storage del artículo, ¿qué devolvería para una startup con 75,000 documentos y 3 consultas por segundo?
Analizar
El ejemplo del “Problema de Sincronización” del artículo muestra a Postgres y a la base de datos vectorial discrepando sobre el status de un usuario. Explica paso a paso por qué este tipo de desincronización es un riesgo estructural específicamente para la arquitectura de “dos almacenes separados” (Postgres + base de datos vectorial) que no existiría si usaras pgvector dentro de tu única base de datos Postgres.
Evaluar La advertencia “Embedding Drift” del artículo dice que cambiar de modelos de IA significa recalcular cada vector en la base de datos. Critica las tres preguntas de sí/no del marco de decisión (cantidad de elementos, latencia, capacidad de DevOps) por no mencionar este costo en absoluto: ¿debería “con qué frecuencia esperamos cambiar de modelos de embeddings” ser una cuarta pregunta en ese marco, y por qué la respuesta de un equipo a ella podría cambiar su elección de almacenamiento incluso si respondió “no” a las tres preguntas enumeradas?
Crear Diseña un plan de escalado por fases (siguiendo el ejemplo de la aplicación de recetas del artículo) para un nuevo producto: una función de búsqueda de tickets de soporte al cliente que comienza con 2,000 tickets y se espera que crezca a 2 millones en 18 meses. Usando el patrón de tres etapas del artículo (FAISS → pgvector → base de datos vectorial dedicada), especifica aproximadamente cuándo migrarías en cada etapa y qué señal (de las advertencias del artículo o del marco de decisión) desencadenaría cada migración.
Artículos relacionados
- ¿Qué son los embeddings y qué puedes hacer realmente con ellos?
- Construyendo tu primer pipeline RAG: fragmentación, embedding y recuperación
Referencias y lecturas adicionales
- Malkov, Y. A., & Yashunin, D. A. (2018). Efficient and robust approximate nearest neighbor search using Hierarchical Navigable Small World graphs. arXiv:1603.09320
- pgvector — Búsqueda de similitud vectorial de código abierto para Postgres
- Documentación de Qdrant
Esta traducción fue generada automáticamente y puede contener errores. Si el idioma inglés es tu preferencia, puedes leer el artículo original en inglés .
«Aplica lo que aprendiste» es para suscriptores Supporter e Insider.
Suscríbete para desbloquear los ejercicios de este artículo.
Ver planesArtículos relacionados
- LLMs y GenAI En revisión
LoRA y QLoRA explicados: Ajuste fino de modelos grandes con presupuestos reducidos
Aprende cómo LoRA y QLoRA te permiten hacer el ajuste fino de modelos de lenguaje grandes en GPUs de consumo al congelar los pesos base y, en su lugar, entrenar pequeños adaptadores de bajo rango.
- LLMs y GenAI En revisión
Por qué los LLM inventan cosas con confianza: comprender y detectar las alucinaciones
Aprende por qué los LLM alucinan mediante la predicción del siguiente token y usa log-probs y RAG para detectar y prevenir la fabricación con confianza en tus aplicaciones de IA.
- LLMs y GenAI En revisión
Por qué los LLM olvidan el medio: Entendiendo las ventanas de contexto y el fenómeno Lost in the Middle
Descubre por qué los LLM ignoran la información del medio en prompts largos, cómo el fenómeno Lost in the Middle afecta a RAG y cómo el reordenamiento y el reranking lo solucionan.
- LLMs y GenAI En revisión
RAG vs. Modelos de Contexto Largo: ¿Cuál gana en 2026?
¿Deberías usar RAG o LLMs de contexto largo en 2026? Compara el costo, la precisión y los compromisos del fenómeno 'Lost-in-the-Middle' para descubrir por qué un enfoque de recuperación híbrido resulta ganador.
¿Buscas otra cosa?
Busca en todos los artículos por título, resumen o tema.