Skip to content
BotServBotServ
MilvusBase de datos vectorialEscaladoIVFHNSWRAGIA local

Milvus: Base de datos vectorial para gran escala

Milvus: instalación, tipos de índice, escalado y uso en RAG. Búsqueda vectorial de alto rendimiento.

S

schutzgeist

13 min read
Milvus: Base de datos vectorial para gran escala

Milvus: Base de datos vectorial para gran escala

Lo que cubre este artículo

  • Qué es Milvus y por qué destaca para volúmenes de datos grandes
  • Cómo instalar y ejecutar Milvus localmente con Docker
  • Qué tipos de índice existen y cómo elegir el adecuado para tu caso de uso
  • Cómo almacenar, buscar y filtrar datos con pymilvus
  • Cómo se compara Milvus con Chroma y Qdrant, y cuándo es la opción correcta

Introducción

Ya descubriste RAG local y probablemente ya ganaste experiencia con Chroma o Qdrant. Ahora te enfrentas a una pregunta importante: ¿qué sucede cuando tu colección de documentos crece sin parar? ¿Cuando pasas de miles a millones de vectores?

Aquí entra en juego Milvus. Es una base de datos vectorial de código abierto diseñada específicamente para gran escala y alto rendimiento. Soporta varios tipos de índice, puede funcionar de forma distribuida y gestiona volúmenes de datos que empujan a otras bases de datos a sus límites.

Este artículo te guía por la instalación, la selección de índices, el almacenamiento de datos y las consultas de búsqueda. Si aún no conoces los fundamentos de RAG, léelo primero. También es recomendable tener conocimientos sobre modelos de embedding.

¿Por qué necesito Milvus?

Imagina que ejecutas una aplicación RAG para una gran empresa. La base de conocimiento contiene cientos de miles de documentos y cada día se añaden más. La base de datos vectorial no solo debe almacenar todos estos vectores, sino encontrar los más similares en milisegundos.

Con Chroma llegas rápidamente a los límites con estos volúmenes. Qdrant avanza mucho más, pero está principalmente optimizado para nodos individuales. Milvus, en cambio, está construido desde cero para arquitectura distribuida. Puedes trabajar con varios nodos, distribuir datos entre máquinas y aun así obtener resultados de búsqueda rápidos.

Otro punto a favor es la variedad de tipos de índice. Milvus soporta IVF, HNSW, DiskANN y varios más. Cada tipo de índice tiene sus propias fortalezas: algunos son más rápidos de construir, otros usan menos memoria, y algunos son óptimos para volúmenes enormes. Eliges el índice que se ajusta a tu caso de uso en lugar de conformarte con una solución única.

Para configuraciones locales no necesariamente debes construir un cluster distribuido. Milvus Lite y Milvus Standalone son suficientes para la mayoría de proyectos. Pero cuando tu proyecto crece, puedes actualizar a Milvus Distributed sin cambiar de base de datos.

Milvus explicado brevemente

Milvus almacena vectores en lo que se llama Collections, comparables con tablas en una base de datos relacional. Cada Collection tiene un esquema que define los campos y sus tipos de datos. Uno de estos campos es el vector principal, usado para la búsqueda de similitud.

Cuando haces una consulta de búsqueda, Milvus convierte la consulta en un vector y busca en el índice de la Collection. El índice es una estructura de datos que acelera la búsqueda, no comparando cada vector individualmente, sino agrupándolos y prefiltrándolos inteligentemente. La elección del índice afecta la velocidad de búsqueda, el consumo de memoria y la precisión de los resultados.

Milvus funciona en tres modos: Milvus Lite para pruebas directamente en Python, Milvus Standalone como un único contenedor Docker, y Milvus Distributed como cluster con varios nodos. Para proyectos RAG locales recomendamos Milvus Standalone, porque es simple de configurar y ofrece todas las características importantes.

Para quién es este artículo

Este artículo está dirigido a desarrolladores que ya tienen conocimientos básicos de RAG y bases de datos vectoriales. Debes comprender qué es la IA local y cómo funciona RAG. Si probaste Chroma o Qdrant y buscas una solución para volúmenes mayores, este es el siguiente paso correcto. Necesitas conocimientos básicos de Python y debes saber cómo usar Docker.

Términos importantes

TérminoExplicación
CollectionUn contenedor para vectores y metadatos, comparable con una tabla.
SchemaLa definición de los campos, tipos de datos y parámetros vectoriales de una Collection.
IndexUna estructura de datos que acelera la búsqueda vectorial, como IVF o HNSW.
IVFInverted File Index, agrupa vectores en clusters y acelera la búsqueda.
HNSWHierarchical Navigable Small World, un índice basado en grafos para búsquedas muy rápidas.
DiskANNUn índice que mantiene datos en disco y está optimizado para volúmenes muy grandes.
Metric TypeLa métrica de distancia para la búsqueda de similitud, como Cosine, L2 o IP.
PartitionUna subdivisión de una Collection para limitar búsquedas a áreas específicas.
SegmentLa unidad de almacenamiento física en Milvus donde se organizan los datos.

Instalación: Milvus Standalone con Docker

Milvus Standalone es la mejor opción para proyectos locales. Funciona en un único contenedor Docker y requiere etcd y MinIO como dependencias. La forma más sencilla es usar el archivo docker-compose.yml oficial de Milvus.

Descarga el archivo e inicia el servicio:

wget https://github.com/milvus-io/milvus/releases/download/v2.4.0/milvus-standalone-docker-compose.yml -O docker-compose.yml
docker compose up -d

Después del inicio, verifica que todos los contenedores estén corriendo:

docker compose ps

Deberías ver tres contenedores corriendo: milvus, etcd y minio. Milvus es accesible en el puerto 19530. Si aún no instalaste Docker, revisa los fundamentos de Docker.

Alternativamente, puedes usar Milvus Lite, que funciona sin Docker directamente en Python. Es ideal para pruebas pero no recomendado para aplicaciones en producción:

pip install pymilvus

Con Milvus Lite no necesitas un servidor, sino que usas Milvus como una librería embebida. En este artículo usamos Milvus Standalone con Docker porque se asemeja más a un sistema productivo real.

Instalar el cliente Python

El cliente Python para Milvus se llama pymilvus. Instálalo con pip:

pip install pymilvus

Luego te conectas en Python a tu instancia Milvus local:

from pymilvus import MilvusClient

client = MilvusClient(uri="http://localhost:19530")

print(client.list_collections())  # Muestra todas las Collections existentes

Si usas Milvus Lite, especifica una ruta de archivo en lugar de una URI:

client = MilvusClient(uri="./milvus.db")

Crear una Collection y definir el esquema

Antes de almacenar datos, creas una Collection. En Milvus defines los campos del esquema explícitamente. Cada Collection necesita al menos un campo de clave primaria y un campo vectorial.

from pymilvus import MilvusClient, DataType

client.create_collection(
    collection_name="articles",
    fields=[
        {"name": "id", "dtype": DataType.INT64, "is_primary": True},
        {"name": "title", "dtype": DataType.VARCHAR, "max_length": 200},
        {"name": "content", "dtype": DataType.VARCHAR, "max_length": 2000},
        {"name": "source", "dtype": DataType.VARCHAR, "max_length": 100},
        {"name": "vector", "dtype": DataType.FLOAT_VECTOR, "dim": 768}
    ]
)

El campo vectorial vector tiene dimensión 768, que corresponde al output de intfloat/multilingual-e5-large. Si usas un modelo de embedding diferente, ajusta la dimensión accordingly.

Crear un índice

Después de crear la colección, configuras un índice para el campo vectorial. El índice es crucial para la velocidad de búsqueda. Sin él, Milvus tendría que recorrer cada vector individualmente, lo que sería demasiado lento con grandes volúmenes de datos.

client.create_index(
    collection_name="articles",
    field_name="vector",
    index_type="IVF_FLAT",
    metric_type="COSINE",
    params={"nlist": 128}
)

El parámetro nlist especifica en cuántos clusters se agrupan los vectores. Un valor más alto genera clusters más finos y resultados más precisos, pero consume más memoria. Un buen punto de partida es entre 128 y 1024, dependiendo del volumen de datos.

Tipos de índice comparados

Milvus ofrece varios tipos de índice. Aquí está un resumen de los más importantes:

IVF_FLAT: Agrupa vectores en clusters y busca solo en los relevantes. Fácil de configurar, adecuado para volúmenes medianos de datos. El consumo de memoria es moderado y la precisión alta.

IVF_SQ8: Similar a IVF_FLAT, pero con vectores cuantificados. Reduce el consumo de memoria a aproximadamente una cuarta parte, con una precisión ligeramente menor. Ideal cuando el espacio de almacenamiento es limitado.

HNSW: Un índice basado en grafos con múltiples niveles jerárquicos. Búsqueda muy rápida y alta precisión, pero requiere más memoria y tarda más en construirse. Perfecto para aplicaciones donde la velocidad de búsqueda es más importante que el espacio de almacenamiento.

DiskANN: Mantiene el índice en disco en lugar de en RAM. Perfecto para volúmenes muy grandes que no caben en memoria principal. La búsqueda es algo más lenta que con HNSW, pero la eficiencia de almacenamiento es inmejorable.

Para la mayoría de proyectos RAG locales, HNSW es la mejor opción porque proporciona los resultados de búsqueda más rápidos y los volúmenes de datos generalmente caben en RAM. Cuando tus datos crecen y la memoria ya no es suficiente, cambia a DiskANN.

Almacenar datos

Ahora añades datos a la colección. Pasas los vectores junto con los campos de metadatos.

data = [
    {
        "id": 1,
        "title": "¿Qué es la IA local?",
        "content": "La IA local se ejecuta en tu propio ordenador sin servicios en la nube.",
        "source": "blog",
        "vector": [0.12, 0.34, 0.56] + [0.0] * 765  # Rellenado a 768 dimensiones
    },
    {
        "id": 2,
        "title": "RAG explicado",
        "content": "RAG combina la búsqueda de documentos con modelos de lenguaje.",
        "source": "blog",
        "vector": [0.23, 0.45, 0.67] + [0.0] * 765
    }
]

client.insert(collection_name="articles", data=data)

En la práctica, generas los vectores con un modelo de embedding real. Los vectores anteriores son marcadores de posición. Lo importante es que cada vector tenga exactamente la dimensión definida en el esquema.

Realizar consultas de búsqueda

Después de almacenar datos y crear un índice, puedes ejecutar consultas de búsqueda. Milvus carga la colección en memoria previamente:

client.load_collection(collection_name="articles")

results = client.search(
    collection_name="articles",
    data=[[0.15, 0.40, 0.60] + [0.0] * 765],  # Vector de búsqueda
    limit=3,
    output_fields=["title", "content", "source"]
)

for hits in results:
    for hit in hits:
        print(hit["entity"]["title"], hit["distance"])

El parámetro limit especifica cuántos resultados obtienes. output_fields controla qué campos se incluyen en el resultado. La distance muestra qué tan similar es el vector encontrado con respecto al vector de búsqueda.

Filtrado

Milvus admite expresiones de filtro para restringir los resultados de búsqueda. Esto es importante cuando deseas buscar solo en fuentes o categorías específicas.

results = client.search(
    collection_name="articles",
    data=[[0.15, 0.40, 0.60] + [0.0] * 765],
    limit=3,
    filter='source == "blog"',
    output_fields=["title", "content", "source"]
)

for hits in results:
    for hit in hits:
        print(hit["entity"]["title"], hit["entity"]["source"])

Las expresiones de filtro en Milvus utilizan una sintaxis similar a SQL. Puedes combinar comparaciones, operadores lógicos y consultas de rango. Esto es más flexible que los filtros de metadatos simples en otras bases de datos.

Comparación: Milvus vs. Chroma vs. Qdrant

CaracterísticaMilvusChromaQdrant
EscalabilidadMuy alta, distribución posiblePequeña a mediaAlta, nodos individuales
Tipos de índiceIVF, HNSW, DiskANN y másHNSW (internamente)HNSW
ArquitecturaDistribuida, con etcd y MinIOIntegrada o servidorServidor, proceso único
Consumo de recursosMedio a altoBajoBajo a medio
Barrera de entradaMediaMuy bajaBaja
FiltradoExpresiones similares a SQLSimpleMuy potente
RendimientoMuy alto con grandes volúmenesBueno con volúmenes pequeñosMuy alto
Esfuerzo de configuraciónMayor, múltiples contenedoresMínimoBajo

Milvus destaca cuando necesitas gestionar grandes volúmenes de datos y buscas una base de datos que crezca contigo. Chroma es ideal para comenzar rápidamente, Qdrant es un todoterreno robusto. Milvus merece la pena si planeas trabajar a largo plazo con millones de vectores.

Errores comunes

  1. No cargar la colección: Milvus requiere que cargues una colección en memoria (load_collection) antes de poder buscar. Si lo olvidas, obtendrás un error. Después de insertar nuevos datos no necesitas recargar la colección, pero sí después de cambios en el índice.
  2. Dimensión de vector incorrecta: La dimensión en el esquema debe coincidir exactamente con tu modelo de embedding. Un valor incorrecto causa errores al insertar. Verifica la dimensión de tu modelo antes de crear el esquema.
  3. Crear el índice antes de los datos: El índice debe crearse antes de insertar grandes volúmenes de datos. Si insertas datos primero y luego creas el índice, la construcción tarda más.
  4. Confundir el tipo de métrica: Si tu modelo de embedding está optimizado para distancia Cosine pero usas L2, obtendrás malos resultados de búsqueda. Verifica qué métrica recomienda tu modelo.
  5. Olvidar etcd y MinIO: Milvus Standalone necesita etcd y MinIO. Si solo inicias el contenedor Milvus, nada funcionará. Siempre utiliza el archivo docker-compose.yml oficial.
  6. Persistencia no configurada: Por defecto, Milvus almacena datos en volúmenes definidos en el archivo docker-compose.yml. Si modificas este archivo, asegúrate de mantener los volúmenes.
  7. Solicitar demasiados resultados: Con colecciones grandes, un valor alto en limit puede degradar el rendimiento. Comienza con valores pequeños y aumenta solo si es necesario.
  8. No utilizar particiones: Con colecciones muy grandes, puedes usar particiones para restringir las búsquedas a subconjuntos. Esto mejora significativamente el rendimiento, pero a menudo se pasa por alto.

Hardware, costos y seguridad

Milvus Standalone necesita al menos 8 GB de RAM para funcionar correctamente. Para volúmenes de datos más grandes, se recomiendan 16 GB o más. El espacio requerido en disco depende del volumen de datos y del tipo de índice: HNSW consume más memoria que IVF_SQ8, y DiskANN utiliza el disco de manera más eficiente que los índices basados en RAM.

Milvus es de código abierto y gratuito. La edición comunitaria incluye todas las características que necesitas para proyectos RAG locales. También existe una versión comercial en la nube llamada Zilliz Cloud, que no es relevante para configuraciones locales.

En términos de seguridad, aplica lo mismo que para otras bases de datos locales: siempre que Milvus solo sea accesible desde tu propia red, tus datos están protegidos. Si expones Milvus a través de la red, usa un proxy inverso con TLS y habilita la autenticación. Como todos los datos permanecen locales, esto es una ventaja importante frente a las bases de datos vectoriales basadas en la nube, como se explica en el artículo sobre IA local vs. IA en la nube.

Enlaces adicionales

Preguntas frecuentes

¿Necesito crear un cluster distribuido para usar Milvus?

No. Milvus Standalone es completamente suficiente para la mayoría de proyectos locales. El modo distribuido solo es necesario si tus volúmenes de datos son tan grandes que un único nodo no puede manejarlos.

¿Cuál es la diferencia entre Milvus Lite y Milvus Standalone?

Milvus Lite se ejecuta directamente en Python sin Docker y es ideal para pruebas. Milvus Standalone funciona como un setup Docker con etcd y MinIO, más cercano a un sistema en producción. Para proyectos serios, utiliza Milvus Standalone.

¿Es Milvus gratuito?

Sí, la versión Open Source es gratuita. Existe una versión comercial en la nube llamada Zilliz Cloud, que no es necesaria para configuraciones locales.

¿Cuántos vectores soporta Milvus localmente?

Depende de la RAM y el espacio de almacenamiento. Milvus está diseñado para millones de vectores. Con DiskANN puedes procesar volúmenes de datos que no caben en RAM.

¿Puedo conectar Milvus con Ollama?

Sí. Ollama proporciona el modelo de lenguaje, Milvus la base de datos vectorial. Tu script Python conecta ambos: Milvus encuentra los documentos relevantes, Ollama genera la respuesta.

¿Qué tipo de índice debo elegir?

Para la mayoría de proyectos RAG locales, HNSW es la mejor opción porque ofrece los resultados de búsqueda más rápidos. Si la RAM no es suficiente, cambia a DiskANN. Para volúmenes de datos pequeños, IVF_FLAT es suficiente.

¿Necesito Docker para Milvus?

Para Milvus Standalone sí, porque etcd y MinIO se ejecutan como contenedores adicionales. Para pruebas puedes usar Milvus Lite sin Docker.

¿Soporta Milvus búsqueda híbrida?

Sí, a partir de la versión 2.4 Milvus soporta búsqueda híbrida con vectores dispersos. Puedes combinar vectores densos y dispersos para unir búsqueda semántica y basada en palabras clave. Más información en el artículo sobre búsqueda híbrida.

¿Puedo ejecutar Milvus en un NAS?

Sí, con Docker. Asegúrate de tener suficiente RAM y almacenamiento rápido. Milvus se beneficia mucho del almacenamiento SSD, especialmente con índices HNSW.

¿Cuál es la diferencia entre Milvus y Qdrant?

Qdrant es más ligero y simple de configurar, ideal para volúmenes de datos medianos. Milvus es más complejo en la configuración, pero más adecuado para volúmenes de datos muy grandes y arquitectura distribuida.

¿Cuánta RAM necesito para Milvus?

Mínimo 8 GB para Milvus Standalone. Para volúmenes de datos más grandes con HNSW se recomiendan 16 GB o más. Con DiskANN puedes reducir el requisito de RAM, porque el índice reside en disco.

Fuentes

  • Sitio web oficial de Milvus: milvus.io
  • Documentación de Milvus: milvus.io/docs
  • pymilvus en GitHub: github.com/milvus-io/pymilvus
  • Repositorio GitHub de Milvus: github.com/milvus-io/milvus
  • Artículo sobre bases de datos vectoriales en esta serie
  • Artículo sobre búsqueda híbrida en esta serie
Volver al blog
Share:

Entradas relacionadas