Utilizar o mmap
O mapeamento de memória (Mmap) permite o acesso direto à memória de grandes ficheiros no disco, permitindo ao Milvus armazenar índices e dados tanto na memória como nos discos rígidos. Esta abordagem ajuda a otimizar a política de colocação de dados com base na frequência de acesso, expandindo a capacidade de armazenamento das colecções sem afetar significativamente o desempenho da pesquisa. Esta página ajuda-o a compreender como o Milvus utiliza o mmap para permitir um armazenamento e recuperação de dados rápidos e eficientes.
Visão Geral
O Milvus usa coleções para organizar embeddings vetoriais e seus metadados, e cada linha na coleção representa uma entidade. Como se mostra na figura à esquerda, o campo vetorial armazena as incorporações vectoriais e os campos escalares armazenam os respectivos metadados. Quando tiver criado índices em determinados campos e carregado a coleção, o Milvus carrega os índices criados e os dados brutos dos campos para a memória.
Mmap ilustrado
O Milvus é um sistema de base de dados com uso intensivo de memória, e o tamanho da memória disponível determina a capacidade de uma coleção. O carregamento de campos que contêm um grande volume de dados na memória é impossível se o tamanho dos dados exceder a capacidade da memória, o que é o caso habitual das aplicações orientadas para a IA.
Para resolver estes problemas, o Milvus introduz o mmap para equilibrar o carregamento de dados quentes e frios nas colecções. Como mostra a figura à direita, pode configurar o Milvus para mapear na memória os dados brutos em determinados campos, em vez de os carregar totalmente para a memória. Desta forma, pode obter acesso direto à memória dos campos sem se preocupar com problemas de memória e aumentar a capacidade da coleção.
Comparando os procedimentos de colocação de dados nas figuras da esquerda e da direita, pode verificar que a utilização de memória é muito maior na figura da esquerda do que na da direita. Com o mmap ativado, os dados que deveriam ter sido carregados para a memória são descarregados para o disco rígido e colocados em cache na cache de páginas do sistema operativo, reduzindo a ocupação de memória. No entanto, as falhas de acerto do cache podem resultar em degradação do desempenho. Para obter detalhes, consulte este artigo.
Quando se configura o mmap no Milvus, há sempre um princípio que deve ser respeitado: Mantenha sempre os dados e índices frequentemente acedidos totalmente carregados na memória e utilize o mmap para os restantes campos.
Utilizar o mmap no Milvus
O Milvus fornece definições hierárquicas de mmap aos níveis global, de campo, de índice e de coleção, em que os níveis de índice e de campo têm precedência sobre o nível de coleção e o nível de coleção sobre o nível global.
Definições globais de mmap
A definição ao nível do cluster é a definição global e tem a precedência mais baixa. O Milvus fornece várias definições relacionadas com o mmap em milvus.yaml. Essas configurações serão aplicadas a todas as coleções do cluster.
...
queryNode:
mmap:
scalarField: false
scalarIndex: false
vectorField: false
vectorIndex: false
# The following should be a path on a high-performance disk
mmapDirPath: any/valid/path
....
Configurar Item |
Descrição |
Valor por defeito |
|---|---|---|
|
Especifica se os dados brutos de todos os campos escalares devem ser mapeados para a memória. Definir esta opção como |
|
|
Especifica se todos os índices de campos escalares devem ser mapeados na memória. Definir isto como Atualmente, só é suportado o campo escalar que utiliza o seguinte tipo de índice:
|
|
|
Especifica se deve mapear os dados brutos de todos os campos vectoriais para a memória. Definir isto como |
|
|
Especifica se todos os índices de campos vectoriais devem ser mapeados para a memória. Definir este valor como Atualmente, apenas são suportados os campos vectoriais que utilizam os seguintes tipos de índices:
|
|
|
Especifica o caminho para os ficheiros mapeados na memória. Se não for especificado, aplica-se o valor predefinido. O marcador de posição |
|
Para aplicar as definições acima ao seu cluster Milvus, siga os passos em Configurar Milvus com Helm e Configurar Milvus com Milvus Operators.
Por vezes, as definições globais do mmap não são flexíveis quando confrontadas com casos de utilização específicos. Para aplicar definições alternativas a uma coleção específica ou aos seus índices, considere configurar o mmap específico para uma coleção, um campo ou um índice. É necessário libertar e carregar uma coleção antes de as alterações às definições de mmap terem efeito.
Configurações de mmap específicas do campo
Para configurar o mmap específico do campo, é necessário incluir o parâmetro mmap_enabled ao adicionar um campo. Pode ativar o mmap neste campo específico definindo este parâmetro para True.
O exemplo a seguir demonstra como configurar o mmap específico do campo quando você adiciona um campo.
from pymilvus import MilvusClient, DataType
CLUSTER_ENDPOINT="http://localhost:19530"
TOKEN="root:Milvus"
client = MilvusClient(
uri=CLUSTER_ENDPOINT,
token=TOKEN
)
schema = MilvusClient.create_schema()
schema.add_field("id", DataType.INT64, is_primary=True, auto_id=False)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=5)
schema = MilvusClient.create_schema()
# Add a scalar field and enable mmap
schema.add_field(
field_name="doc_chunk",
datatype=DataType.INT64,
is_primary=True,
mmap_enabled=True,
)
# Alter mmap settings on a specific field
# The following assumes that you have a collection named `my_collection`
client.alter_collection_field(
collection_name="my_collection",
field_name="doc_chunk",
field_params={"mmap.enabled": True}
)
import io.milvus.param.Constant;
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.DataType;
import io.milvus.v2.service.collection.request.*;
import java.util.*;
String CLUSTER_ENDPOINT = "http://localhost:19530";
String TOKEN = "root:Milvus";
client = new MilvusClientV2(ConnectConfig.builder()
.uri(CLUSTER_ENDPOINT)
.token(TOKEN)
.build());
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.autoID(false)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
Map<String, String> typeParams = new HashMap<String, String>() {{
put(Constant.MMAP_ENABLED, "false");
}};
schema.addField(AddFieldReq.builder()
.fieldName("doc_chunk")
.dataType(DataType.VarChar)
.maxLength(512)
.typeParams(typeParams)
.build());
CreateCollectionReq req = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.build();
client.createCollection(req);
client.alterCollectionField(AlterCollectionFieldReq.builder()
.collectionName("my_collection")
.fieldName("doc_chunk")
.property(Constant.MMAP_ENABLED, "true")
.build());
import { MilvusClient, DataType } from '@zilliz/milvus2-sdk-node';
const CLUSTER_ENDPOINT="YOUR_CLUSTER_ENDPOINT";
const TOKEN="YOUR_TOKEN";
const client = await MilvusClient({
address: CLUSTER_ENDPOINT,
token: TOKEN
});
const schema = [
{
name: 'vector',
data_type: DataType.FloatVector
},
{
name: "doc_chunk",
data_type: DataType.VarChar,
max_length: 512,
'mmap.enabled': false,
}
];
await client.createCollection({
collection_name: "my_collection",
schema: schema
});
await client.alterCollectionFieldProperties({
collection_name: "my_collection",
field_name: "doc_chunk",
properties: {"mmap_enable": true}
});
// go
#restful
export TOKEN="root:Milvus"
export CLUSTER_ENDPOINT="http://localhost:19530"
export idField='{
"fieldName": "id",
"dataType": "Int64",
"elementTypeParams": {
"max_length": 512
},
"isPrimary": true,
"auto_id": false
}'
export vectorField='{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": 5
}
}'
export docChunkField='{
"fieldName": "doc_chunk",
"dataType": "Int64",
"elementTypeParams": {
"max_length": 512,
"mmap.enabled": false
}
}'
export schema="{
\"autoID\": false,
\"fields\": [
$idField,
$docChunkField,
$vectorField
]
}"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"schema\": $schema
}"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/fields/alter_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"fieldName": "doc_chunk",
"fieldParams":{
"mmap.enabled": true
}
}'
Considere habilitar o mmap para os campos que armazenam dados de grande volume. Tanto os campos escalares quanto os campos vetoriais são suportados.
Em seguida, você pode criar uma coleção usando o esquema criado acima. Ao receber um pedido para carregar a coleção, o Milvus utiliza o mapeamento de memória dos dados brutos do campo doc_chunk para a memória.
Definições de mmap específicas do índice
Para configurar o mmap específico do índice, é necessário incluir a propriedade mmap.enable nos parâmetros do índice quando adiciona o índice. Pode ativar o mmap neste índice específico definindo a propriedade para true.
O exemplo a seguir demonstra como configurar o mmap específico do índice quando você adiciona um índice.
# Add a varchar field
schema.add_field(
field_name="title",
datatype=DataType.VARCHAR,
max_length=512
)
index_params = MilvusClient.prepare_index_params()
# Create index on the varchar field with mmap settings
index_params.add_index(
field_name="title",
index_type="AUTOINDEX",
params={ "mmap.enabled": "false" }
)
# Change mmap settings for an index
# The following assumes that you have a collection named `my_collection`
client.alter_index_properties(
collection_name="my_collection",
index_name="title",
properties={"mmap.enabled": True}
)
schema.addField(AddFieldReq.builder()
.fieldName("title")
.dataType(DataType.VarChar)
.maxLength(512)
.build());
List<IndexParam> indexParams = new ArrayList<>();
Map<String, Object> extraParams = new HashMap<String, Object>() {{
put(Constant.MMAP_ENABLED, false);
}};
indexParams.add(IndexParam.builder()
.fieldName("title")
.indexType(IndexParam.IndexType.AUTOINDEX)
.extraParams(extraParams)
.build());
client.alterIndexProperties(AlterIndexPropertiesReq.builder()
.collectionName("my_collection")
.indexName("title")
.property(Constant.MMAP_ENABLED, "true")
.build());
// Create index on the varchar field with mmap settings
await client.createIndex({
collection_name: "my_collection",
field_name: "title",
params: { "mmap.enabled": false }
});
// Change mmap settings for an index
// The following assumes that you have a collection named `my_collection`
await client.alterIndexProperties({
collection_name: "my_collection",
index_name: "title",
properties:{"mmap.enabled": true}
});
// go
# restful
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexParams": [
{
"fieldName": "doc_chunk",
"params": {
"index_type": "AUTOINDEX",
"mmap.enabled": true
}
}
]
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/alter_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"indexName": "doc_chunk",
"properties": {
"mmap.enabled": false
}
}'
Isso se aplica aos índices dos campos vetoriais e escalares.
Em seguida, é possível referenciar os parâmetros do índice numa coleção. Ao receber um pedido para carregar a coleção, o Milvus mapeia na memória o índice do campo do título.
Definições de mmap específicas da coleção
Para configurar uma estratégia de mmap para toda a coleção, é necessário incluir a propriedade mmap.enabled no pedido de criação de uma coleção. É possível ativar o mmap para uma coleção definindo esta propriedade como true.
O exemplo a seguir demonstra como habilitar o mmap em uma coleção chamada my_collection após sua criação. Ao receber um pedido para carregar a coleção, o Milvus mapeia na memória os dados brutos de todos os campos.
# Enable mmap when creating a collection
client.create_collection(
collection_name="my_collection",
schema=schema,
properties={ "mmap.enabled": "true" }
)
CreateCollectionReq req = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.property(Constant.MMAP_ENABLED, "false")
.build();
client.createCollection(req);
await client.createCollection({
collection_name: "my_collection",
scheme: schema,
properties: { "mmap.enabled": false }
});
// go
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--data "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"params\": {
\"mmap.enabled\": \"false\"
}
}"
Também é possível alterar as definições de mmap de uma coleção existente.
# Release collection before change mmap settings
client.release_collection("my_collection")
# Ensure that the collection has already been released
# and run the following
client.alter_collection_properties(
collection_name="my_collection",
properties={
"mmap.enabled": false
}
)
# Load the collection to make the above change take effect
client.load_collection("my_collection")
client.releaseCollection(ReleaseCollectionReq.builder()
.collectionName("my_collection")
.build());
client.alterCollectionProperties(AlterCollectionPropertiesReq.builder()
.collectionName("my_collection")
.property(Constant.MMAP_ENABLED, "false")
.build());
client.loadCollection(LoadCollectionReq.builder()
.collectionName("my_collection")
.build());
// Release collection before change mmap settings
await client.releaseCollection({
collection_name: "my_collection"
});
// Ensure that the collection has already been released
// and run the following
await client.alterCollectionProperties({
collection_name: "my_collection",
properties: {
"mmap.enabled": false
}
});
// Load the collection to make the above change take effect
await client.loadCollection({
collection_name: "my_collection"
});
// go
# restful
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/release" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection"
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection",
"properties": {
"mmmap.enabled": false
}
}'
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/load" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d '{
"collectionName": "my_collection"
}'
É necessário libertar a coleção para fazer alterações às suas propriedades e recarregar a coleção para que as alterações tenham efeito.