Entendendo o Conceito de Schema no Milvus
No Milvus, o Schema representa os metadados que definem a organização de uma Collection (Coleção). Ele funciona de forma análoga ao esquema de uma tabela em bancos de dados relacionais, estabelecendo quais tipos de dados podem ser armazenados.
| Conceito Milvus | Equivalente Relacional (RDBMS) | Descrição |
|---|---|---|
| Schema | Table Schema | Definição estrutural da coleção. |
| Field | Column | Atributo ou campo específico. |
| DataType | Data Type | Tipo de dado (VARCHAR, INT, etc). |
| Primary Key | Primary Key | Identificador único do registro. |
| Vector Field | (N/A) | Campo especializado para busca vetorial. |
| Dynamic Field | (NoSQL/JSON) | Campos flexíveis que não exigem definição prévia. |
from pymilvus import MilvusClient, DataType
# Inicializando um Schema com suporte a campos dinâmicos
meu_esquema = client.create_schema(
enable_dynamic_field=True
)
Tipos de Campos Suportados
Os campos no Milvus são divididos em duas categorias principais: Escalares e Vetoriais.
- Campos Escalares:
- Strings:
VARCHAR - Numéricos:
INT8,INT16,INT32,INT64,FLOAT,DOUBLE,BOOL - Complexos:
JSON,ARRAY - Temporais:
TIMESTAMPTZ - Geométricos:
GEOMETRY
- Strings:
- Campos Vetoriais:
- Densos:
FLOAT_VECTOR,FLOAT16_VECTOR,BFLOAT16_VECTOR,INT8_VECTOR - Esparsos:
SPARSE_FLOAT_VECTOR - Binários:
BINARY_VECTOR
- Densos:
Configuração de Chaves Primárias
O Milvus suporta chaves primárias do tipo INT64 e VARCHAR. É possível configurar a geração automática de IDs ou o fornecimento manual.
# Exemplo de Chave Primária Inteira com Auto-ID
meu_esquema.add_field(
field_name="id_registro",
datatype=DataType.INT64,
is_primary=True,
auto_id=True
)
# Exemplo de Chave Primária String Manual
meu_esquema.add_field(
field_name="codigo_sku",
datatype=DataType.VARCHAR,
max_length=64,
is_primary=True,
auto_id=False
)
Detalhamento de Campos Escalares
Campos de Texto (VARCHAR)
Exigem a definição de max_length. Suportam valores padrão e restrições de nulidade.
meu_esquema.add_field(
field_name="nome_item",
datatype=DataType.VARCHAR,
max_length=200,
nullable=False,
default_value="Desconhecido"
)
Trabalhando com JSON e Indexação
Campos JSON permitem armazenar estruturas variadas. Para otimizar a performance, o Milvus oferece o JSON Shredding, que transforma o armazenamento baseado em linhas em colunas para acelerar consultas.
# Definição do campo JSON
meu_esquema.add_field(
field_name="metadados_tecnicos",
datatype=DataType.JSON
)
# Criando índice em um caminho específico do JSON
parametros_indice = MilvusClient.prepare_index_params()
parametros_indice.add_index(
field_name="metadados_tecnicos",
index_name="idx_cpu_model",
params={
"json_path": 'metadados_tecnicos["hardware"]["cpu"]',
"json_cast_type": "VARCHAR"
}
)
Arrays e Estruturas (STRUCT)
O Milvus permite o uso de Arrays de tipos básicos ou Arrays de Estruturas (objetos complexos com múltiplos campos).
# Definição de uma estrutura para avaliações
esquema_struct = client.create_struct_field_schema()
esquema_struct.add_field(field_name="usuario_id", datatype=DataType.INT64)
esquema_struct.add_field(field_name="nota", datatype=DataType.INT32)
# Adicionando Array de Struct ao Schema principal
meu_esquema.add_field(
field_name="lista_avaliacoes",
datatype=DataType.ARRAY,
element_type=DataType.STRUCT,
max_capacity=50,
element_schema=esquema_struct
)
Campos Vetoriais e Dimensões
Os vetores são o núcleo da busca semântica. A escolha do tipo de vetor impacta diretamente na precisão e no consumo de memória.
| Tipo de Vetor | Precisão | Uso Recomendado | Tamanho por Dimensão |
|---|---|---|---|
| FLOAT_VECTOR | Alta (32-bit) | Busca semântica geral | 4 Bytes |
| FLOAT16_VECTOR | Média (16-bit) | Modelos DL otimizados | 2 Bytes |
| INT8_VECTOR | Quantizada | Alta performence/baixo custo | 1 Byte |
# Adicionando vetor denso para busca por imagem
meu_esquema.add_field(
field_name="vetor_imagem",
datatype=DataType.FLOAT_VECTOR,
dim=512
)
Funcionaliddae de Campos Dinâmicos
Ao ativar enable_dynamic_field=True, qualquer dado enviado que não possua um campo correspondente no schema será automaticamente armazenado em um campo oculto chamado $meta.
# Inserindo dados dinâmicos
dado_exemplo = {
"id_registro": 500,
"vetor_imagem": [0.1, 0.5, ...],
"cor_hex": "#FF5733", # Campo não definido no schema
"peso_kg": 1.5 # Campo não definido no schema
}
# Consulta em campo dinâmico
resultado = client.query(
collection_name="itens",
filter='cor_hex == "#FF5733"',
output_fields=["id_registro", "peso_kg"]
)
Exemplo Completo de Implementação
from pymilvus import MilvusClient, DataType
cliente_milvus = MilvusClient(uri="http://localhost:19530")
# 1. Configuração do Schema
schema_final = cliente_milvus.create_schema(enable_dynamic_field=True)
# 2. Campos Escalares
schema_final.add_field(field_name="pk", datatype=DataType.INT64, is_primary=True, auto_id=True)
schema_final.add_field(field_name="titulo", datatype=DataType.VARCHAR, max_length=150)
schema_final.add_field(field_name="timestamp", datatype=DataType.TIMESTAMPTZ)
# 3. Campo JSON
schema_final.add_field(field_name="detalhes_extras", datatype=DataType.JSON)
# 4. Campo Vetorial
schema_final.add_field(field_name="embedding", datatype=DataType.FLOAT_VECTOR, dim=128)
# 5. Campo de Geometria
schema_final.add_field(field_name="localizacao", datatype=DataType.GEOMETRY, default_value="POINT(0 0)")
print("Estrutura do Schema definida com sucesso.")
Boas Práticas de Design
- Nomenclatura: Utilize
snake_casee evite caracteres especiais ou espaços em nomes de campos. - Dimensões: Certifique-se de que a dimensão do campo vetorial corresponde exatamente à saída do seu modelo de Embedding (ex: 384 para MiniLM, 1536 para modelos OpenAI).
- Indexação: Campos JSON com chaves frequentes devem ser indexados via
json_pathpara evitar varreduras completas da coleção. - Tipos Temporais: Utilize
TIMESTAMPTZem vez de strings simples para garantir consistência em diferentes fusos horários.
Resumo Comparativo: Milvus vs MySQL
Embora o Milvus compartilhe conceitos com o MySQL, sua força reside na flexibilidade. O Milvus combina a rigidez do schema relacional para dados críticos com a maleabilidade do NoSQL (via Dynamic Fields) e a capacidade matemática de lidar com vetores de alta dimensionalidade.