¿Qué es un esquema dinámico?
Esta publicación está escrita conjuntamente por Yujian Tang y Zhenshan Cao.
Toda base de datos tiene un esquema, pero no todas son dinámicas. Las bases de datos SQL tienen esquemas predefinidos, que normalmente no cambian. Cuando lo creas, le indicas a la base de datos cómo quieres que sea cada tabla y haces cumplir que cada entrada se ajuste al esquema de esa tabla. Las bases de datos NoSQL suelen tener un esquema dinámico (o pueden no tener esquema). Los atributos de cada objeto no tienen que definirse cuando creas tus bases de datos.
Para la base de datos vectorial Milvus, el esquema dinámico es uno que cambia a medida que añades datos. Por ejemplo, el soporte de esquema dinámico significa que puedes tratar la entrada de datos como lo harías con una base de datos NoSQL y añadir datos en formato JSON. Anteriormente, Milvus tenía un esquema estrictamente aplicado. Lanzamos una opción de esquema dinámico en Milvus 2.2.9 hace unos meses e hicimos que fuera fácil de implementar.
En este artículo, cubriremos:
- ¿Qué es un esquema de base de datos?
- ¿Qué es un esquema de base de datos vectorial?
- Cómo usar el esquema dinámico con la base de datos vectorial Milvus
- Cómo se implementa la función de esquema dinámico en Milvus
Ventajas y desventajas de los esquemas dinámicos
Resumen de los esquemas dinámicos para bases de datos vectoriales
¿Qué es un esquema de base de datos?
Los esquemas estructuran cómo se insertan y almacenan los datos en una base de datos. El ejemplo anterior muestra cómo podrías crear un esquema de base de datos normalizado para una base de datos relacional. En el ejemplo anterior, la tabla central tiene cuatro columnas. Esta base de datos tendría cuatro tablas y un esquema para cada tabla.
Tres tablas tendrían esquemas de dos columnas, y la central tendría un esquema de cuatro columnas. Los esquemas de las columnas también incluirían definiciones de datos. Las columnas “Employee”, “Title” y “DeptName” serían todas cadenas, o VARCHAR. Lo más probable es que “CourseID” también lo fuera. “EmpID” y “DeptID” serían enteros, y “Date” podría ser un tipo de fecha o también un tipo VARCHAR.
¿Qué es un esquema de base de datos vectorial?
La imagen a continuación muestra una entrada en una instancia de Zilliz, el servicio de base de datos vectorial completamente administrado de Milvus, que uso para mi proyecto Chat Towards Data Science. Si lo definiéramos como un esquema de base de datos relacional, tendríamos 11 columnas. Habría seis columnas de cadena o VARCHAR: “id”, “paragraph”, “subtitle”, “publication”, “article_url” y “title”. Tres de las otras cinco columnas serían algún tipo de dato INT: “reading_time”, “responses” y “claps”. Las dos columnas restantes serían un tipo DATE, “date”, y lo que llamamos un “FLOAT_VECTOR”, el vector de incrustación.
¿Cómo usar el esquema dinámico con la base de datos vectorial Milvus?
Milvus es una popular base de datos vectorial de código abierto creada para ofrecer rendimiento, escalabilidad y fiabilidad. Lanzamos una opción de esquema dinámico en Milvus 2.2.9 hace unos meses e hicimos que fuera fácil de implementar.
El siguiente fragmento de código demuestra cómo habilitar y utilizar la función de esquema dinámico en Milvus y cómo insertar datos en campos dinámicos y realizar búsquedas filtradas.
from pymilvus import (
connections,
FieldSchema, CollectionSchema, DataType,
Collection,
)
DIMENSION = 8
COLLECTION_NAME = "books"
connections.connect("default", host="localhost", port="19530")
fields = [
FieldSchema(name='id', dtype=DataType.INT64, is_primary=True),
FieldSchema(name='title', dtype=DataType.VARCHAR, max_length=200),
FieldSchema(name='embeddings', dtype=DataType.FLOAT_VECTOR, dim=DIMENSION)
]
schema = CollectionSchema(fields=fields, enable_dynamic_field=True)
collection = Collection(name=COLLECTION_NAME, schema=schema)```
data_rows = [
{"id": 1, "title": "Lord of the Flies",
"embeddings": [0.64, 0.44, 0.13, 0.47, 0.74, 0.03, 0.32, 0.6],
"isbn": "978-0399501487"},
{"id": 2, "title": "The Great Gatsby",
"embeddings": [0.9, 0.45, 0.18, 0.43, 0.4, 0.4, 0.7, 0.24],
"author": "F. Scott Fitzgerald"},
{"id": 3, "title": "The Catcher in the Rye",
"embeddings": [0.43, 0.57, 0.43, 0.88, 0.84, 0.69, 0.27, 0.98],
"claps": 100},
]
collection.insert(data_rows)
collection.create_index("embeddings", {"index_type": "FLAT", "metric_type": "L2"})
collection.load()
vector_to_search = [0.57, 0.94, 0.19, 0.38, 0.32, 0.28, 0.61, 0.07]
result = collection.search(
data=[vector_to_search],
anns_field="embeddings",
param={},
limit=3,
expr="claps > 30 || title =='The Great Gatsby'",
output_fields=["title", "author", "claps", "isbn"],
consistency_level="Strong")
for hits in result:
for hit in hits:
print(hit.to_dict())
En la colección creada "books," definimos un esquema con tres campos: id, title y embeddings. El id es la clave primaria, un identificador único de cada fila, y está en el formato de INT64. El title representa el nombre del libro con el tipo VARCHAR, y el embedding es una columna vectorial de 8 dimensiones. En esta publicación, los datos vectoriales se establecen aleatoriamente en el código con fines de demostración.
schema = CollectionSchema(fields=fields, enable_dynamic_field=True)
collection = Collection(name=COLLECTION_NAME, schema=schema)
Habilitamos el esquema dinámico pasando un campo al objeto CollectionSchema en la definición. Todo lo que hacemos es agregar el esquema enable_dynamic_field y establecerlo en True.
data_rows = [
{"id": 1, "title": "Lord of the Flies",
"embeddings": [0.64, 0.44, 0.13, 0.47, 0.74, 0.03, 0.32, 0.6],
"isbn": "978-0399501487"},
{"id": 2, "title": "The Great Gatsby",
"embeddings": [0.9, 0.45, 0.18, 0.43, 0.4, 0.4, 0.7, 0.24],
"author": "F. Scott Fitzgerald"},
{"id": 3, "title": "The Catcher in the Rye",
"embeddings": [0.43, 0.57, 0.43, 0.88, 0.84, 0.69, 0.27, 0.98],
"claps": 100},
]
En el código anterior, insertamos tres filas de datos. Los datos para id=1 incluyen el campo dinámico isbn, id=2 incluye author, y id=3 incluye claps. Estos campos dinámicos tienen diferentes tipos, incluidos tipos de cadena (isbn y author) y tipos enteros (claps).
result = collection.search(
data=[vector_to_search],
anns_field="embeddings",
param={},
limit=3,
expr="claps > 30 || title =='The Great Gatsby'",
output_fields=["title", "author", "claps", "isbn"],
consistency_level="Strong")
En el código anterior, realizamos una búsqueda híbrida que combina la búsqueda ANNS (vecinos más cercanos aproximados) con el filtrado basado en campos dinámicos. La consulta tiene como objetivo recuperar datos de filas que satisfacen las condiciones especificadas en el parámetro expr. La salida incluye los campos title, author, claps e isbn si están presentes. El parámetro expr permite filtrar según campos del esquema (title) y campos dinámicos (claps).
Después de ejecutar el código, los resultados de salida son los siguientes:
{'id': 2, 'distance': 0.40939998626708984, 'entity': {'title': 'The Great Gatsby', 'author': 'F. Scott Fitzgerald'}}
{'id': 3, 'distance': 1.8463000059127808, 'entity': {'title': 'The Catcher in the Rye', 'claps': 100}}
¿Cómo se implementa la característica de esquema dinámico en Milvus?
El kernel de Milvus permite a los usuarios agregar campos dinámicos con diferentes nombres y tipos de datos a cada fila de datos utilizando una metacolumna oculta. Cuando los usuarios crean una tabla y habilitan los campos dinámicos, se crea una columna oculta llamada $meta junto con la tabla. La columna oculta utiliza JSON como tipo de dato porque es un formato de datos independiente del lenguaje ampliamente compatible con los lenguajes de programación modernos para generar y analizar datos en formato JSON.
Milvus organiza los datos en una estructura columnar. Durante la inserción, los datos de los campos dinámicos en cada fila se empaquetan en una pieza de datos JSON, y todas las filas de datos JSON juntas forman la columna oculta $meta.
¿Cuáles son las ventajas y desventajas de Dynamic Schema?
Los esquemas dinámicos ofrecen ventajas e inconvenientes, atendiendo a diferentes necesidades en el modelado de datos.
Ventajas
- Los esquemas dinámicos son fáciles de configurar, lo que los hace accesibles para una amplia base de usuarios sin requerir configuraciones complejas.
- Los esquemas dinámicos admiten cambios en los modelos de datos con el tiempo, lo que permite a los desarrolladores ajustarlos sin una reestructuración significativa.
Desventajas:
- La búsqueda filtrada con esquemas dinámicos es mucho más lenta que con esquemas fijos.
- La inserción masiva en un esquema dinámico es complicada.
Para abordar estos desafíos, Milvus ha integrado un modelo de ejecución vectorizado para aumentar la eficiencia de la búsqueda filtrada. A diferencia del modelo volcano convencional, que procesa una fila de datos a la vez mediante operadores invocados, el modelo de ejecución vectorizado maneja lotes completos de datos simultáneamente. Este paradigma de computación optimiza la localidad de los datos durante el cálculo, lo que resulta en una mejora significativa del rendimiento general del sistema.
De cara al futuro, seguiremos mejorando las capacidades de indexación escalar en Milvus 2.4. Esta mejora tiene como objetivo acelerar la búsqueda filtrada mediante indexación invertida para campos estáticos y dinámicos, prometiendo un mejor rendimiento y eficiencia en la gestión y consulta de esquemas dinámicos.
Resumen de los esquemas dinámicos para bases de datos vectoriales
En este artículo, analizamos los esquemas de bases de datos. Usamos un esquema de ejemplo de una base de datos relacional para comprender mejor los esquemas. Las bases de datos relacionales tienen esquemas estrictos que deben definirse. Los esquemas deben tener campos definidos, y los campos deben tener tipos de datos definidos. Así es como solía imponerse el esquema de Milvus.
Sin embargo, Milvus en realidad solo necesita saber cómo se definen dos campos. Uno, el ID de la entrada, y dos, el campo de embedding. El resto de los campos no necesitan definirse, pero pueden definirse. Con la introducción del esquema dinámico, pasado mediante el parámetro enable_dynamic_field, Milvus ya no necesita que los demás campos estén definidos.
Los esquemas dinámicos presentan un arma de doble filo, ofreciendo facilidad de configuración, flexibilidad y eficiencia, pero no sin contrapartidas. Por ejemplo, la búsqueda filtrada con esquemas dinámicos es más lenta que con esquemas fijos, y la inserción masiva en esquemas dinámicos es más complicada. Milvus utilizó un modelo de ejecución vectorizado para abordar los desafíos que conllevan los esquemas dinámicos, optimizando el rendimiento general del sistema. También mejoraremos las capacidades de indexación escalar en Milvus 2.4 para mejorar el rendimiento y la eficiencia en la gestión y consulta de esquemas dinámicos.
Sigue leyendo

How to Improve Retrieval Quality for Japanese Text with Sudachi, Milvus/Zilliz, and AWS Bedrock
Learn how Sudachi normalization and Milvus/Zilliz hybrid search improve Japanese RAG accuracy with BM25 + vector fusion, AWS Bedrock embeddings, and practical code examples.

Migrating from S3 Vectors to Zilliz Cloud: Unlocking the Power of Tiered Storage
Learn how Zilliz Cloud bridges cost and performance with tiered storage and enterprise-grade features, and how to migrate data from AWS S3 Vectors to Zilliz Cloud.

Announcing the General Availability of Zilliz Cloud BYOC on Google Cloud Platform
Zilliz Cloud BYOC on GCP offers enterprise vector search with full data sovereignty and seamless integration.



