Utilizar a Chave de Partição
A Chave de partição é uma solução de otimização da pesquisa baseada em partições. Ao designar um campo escalar específico como Chave de Partição e ao especificar condições de filtragem com base na Chave de Partição durante a pesquisa, o âmbito da pesquisa pode ser reduzido a várias partições, melhorando assim a eficiência da pesquisa. Este artigo apresentará como utilizar a Chave de partição e considerações relacionadas.
Visão geral
No Milvus, pode utilizar partições para implementar a segregação de dados e melhorar o desempenho da pesquisa, restringindo o âmbito da pesquisa a partições específicas. Se optar por gerir as partições manualmente, pode criar um máximo de 1024 partições numa coleção e inserir entidades nestas partições com base numa regra específica para que possa limitar o âmbito da pesquisa restringindo as pesquisas dentro de um número específico de partições.
O Milvus introduz a Chave de Partição para que possa reutilizar partições na segregação de dados para ultrapassar o limite do número de partições que pode criar numa coleção. Ao criar uma coleção, pode utilizar um campo escalar como chave de partição. Quando a coleção estiver pronta, o Milvus cria o número especificado de partições dentro da coleção. Ao receber uma entidade inserida, Milvus calcula um valor de hash usando o valor da chave de partição da entidade, executa uma operação de módulo com base no valor de hash e na propriedade partitions_num da coleção para obter o ID da partição de destino, e armazena a entidade na partição de destino.
Partição Vs Chave de Partição
A figura seguinte ilustra a forma como o Milvus processa os pedidos de pesquisa numa coleção com ou sem a funcionalidade Chave de Partição activada.
Se a Chave de Partição estiver desactivada, o Milvus procura as entidades que são mais semelhantes ao vetor de consulta dentro da coleção. Pode limitar o âmbito da pesquisa se souber qual a partição que contém os resultados mais relevantes.
Se a Chave de Partição estiver activada, o Milvus determina o âmbito da pesquisa com base no valor da Chave de Partição especificado num filtro de pesquisa e analisa apenas as entidades dentro das partições que correspondem.
Com e sem chave de partição
Usar chave de partição
Para usar a Chave de Partição, é necessário
Definir o número de partições a serem criadas (Opcional), e
Criar uma condição de filtragem com base na Chave de partição.
Definir chave de partição
Para designar um campo escalar como a Chave de Partição, é necessário definir o atributo is_partition_key como true quando adicionar o campo escalar.
Quando você define um campo escalar como a Chave de partição, os valores do campo não podem estar vazios ou nulos.
from pymilvus import (
MilvusClient, DataType
)
client = MilvusClient(
uri="http://localhost:19530",
token="root:Milvus"
)
schema = client.create_schema()
schema.add_field(field_name="id",
datatype=DataType.INT64,
is_primary=True)
schema.add_field(field_name="vector",
datatype=DataType.FLOAT_VECTOR,
dim=5)
# Add the partition key
schema.add_field(
field_name="my_varchar",
datatype=DataType.VARCHAR,
max_length=512,
is_partition_key=True,
)
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.AddFieldReq;
import io.milvus.v2.service.collection.request.CreateCollectionReq;
MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
.uri("http://localhost:19530")
.token("root:Milvus")
.build());
// Create schema
CreateCollectionReq.CollectionSchema schema = client.createSchema();
schema.addField(AddFieldReq.builder()
.fieldName("id")
.dataType(DataType.Int64)
.isPrimaryKey(true)
.build());
schema.addField(AddFieldReq.builder()
.fieldName("vector")
.dataType(DataType.FloatVector)
.dimension(5)
.build());
// Add the partition key
schema.addField(AddFieldReq.builder()
.fieldName("my_varchar")
.dataType(DataType.VarChar)
.maxLength(512)
.isPartitionKey(true)
.build());
import (
"context"
"fmt"
"github.com/milvus-io/milvus/client/v2/column"
"github.com/milvus-io/milvus/client/v2/entity"
"github.com/milvus-io/milvus/client/v2/index"
"github.com/milvus-io/milvus/client/v2/milvusclient"
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
milvusAddr := "localhost:19530"
client, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
Address: milvusAddr,
})
if err != nil {
fmt.Println(err.Error())
// handle error
}
defer client.Close(ctx)
schema := entity.NewSchema().WithDynamicFieldEnabled(false)
schema.WithField(entity.NewField().
WithName("id").
WithDataType(entity.FieldTypeInt64).
WithIsPrimaryKey(true),
).WithField(entity.NewField().
WithName("my_varchar").
WithDataType(entity.FieldTypeVarChar).
WithIsPartitionKey(true).
WithMaxLength(512),
).WithField(entity.NewField().
WithName("vector").
WithDataType(entity.FieldTypeFloatVector).
WithDim(5),
)
import { MilvusClient, DataType } from "@zilliz/milvus2-sdk-node";
const address = "http://localhost:19530";
const token = "root:Milvus";
const client = new MilvusClient({address, token});
// 3. Create a collection in customized setup mode
// 3.1 Define fields
const fields = [
{
name: "my_varchar",
data_type: DataType.VarChar,
max_length: 512,
is_partition_key: true
}
]
export schema='{
"autoId": true,
"enabledDynamicField": false,
"fields": [
{
"fieldName": "id",
"dataType": "Int64",
"isPrimary": true
},
{
"fieldName": "vector",
"dataType": "FloatVector",
"elementTypeParams": {
"dim": "5"
}
},
{
"fieldName": "my_varchar",
"dataType": "VarChar",
"isPartitionKey": true,
"elementTypeParams": {
"max_length": 512
}
}
]
}'
Definir números de partição
Quando se designa um campo escalar numa coleção como chave de partição, Milvus cria automaticamente 16 partições na coleção. Ao receber uma entidade, o Milvus escolhe uma partição com base no valor da Chave de Partição desta entidade e armazena a entidade na partição, resultando em algumas ou todas as partições contendo entidades com diferentes valores de Chave de Partição.
Também é possível determinar o número de partições a criar juntamente com a coleção. Isso é válido apenas se você tiver um campo escalar designado como a Chave de partição.
client.create_collection(
collection_name="my_collection",
schema=schema,
num_partitions=128
)
import io.milvus.v2.service.collection.request.CreateCollectionReq;
CreateCollectionReq createCollectionReq = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.numPartitions(128)
.build();
client.createCollection(createCollectionReq);
err = client.CreateCollection(ctx,
milvusclient.NewCreateCollectionOption("my_collection", schema).
WithNumPartitions(128))
if err != nil {
fmt.Println(err.Error())
// handle error
}
await client.create_collection({
collection_name: "my_collection",
schema: schema,
num_partitions: 128
})
export params='{
"partitionsNum": 128
}'
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"params\": $params
}"
Criar condição de filtragem
Ao realizar pesquisas ANN em uma coleção com o recurso Chave de partição habilitado, é necessário incluir uma expressão de filtragem envolvendo a Chave de partição na solicitação de pesquisa. Na expressão de filtragem, pode restringir o valor da Chave de partição dentro de um intervalo específico para que o Milvus restrinja o âmbito da pesquisa dentro das partições correspondentes.
Ao efetuar operações de eliminação, é aconselhável incluir uma expressão de filtragem que especifique uma única chave de partição para conseguir uma eliminação mais eficiente. Esta abordagem limita a operação de eliminação a uma partição específica, reduzindo a amplificação da escrita durante a compactação e conservando os recursos para compactação e indexação.
Os exemplos a seguir demonstram a filtragem baseada em chave de partição com base em um valor de chave de partição específico e um conjunto de valores de chave de partição.
# Filter based on a single partition key value, or
filter='partition_key == "x" && <other conditions>'
# Filter based on multiple partition key values
filter='partition_key in ["x", "y", "z"] && <other conditions>'
// Filter based on a single partition key value, or
String filter = "partition_key == 'x' && <other conditions>";
// Filter based on multiple partition key values
String filter = "partition_key in ['x', 'y', 'z'] && <other conditions>";
// Filter based on a single partition key value, or
filter = "partition_key == 'x' && <other conditions>"
// Filter based on multiple partition key values
filter = "partition_key in ['x', 'y', 'z'] && <other conditions>"
// Filter based on a single partition key value, or
const filter = 'partition_key == "x" && <other conditions>'
// Filter based on multiple partition key values
const filter = 'partition_key in ["x", "y", "z"] && <other conditions>'
# Filter based on a single partition key value, or
export filter='partition_key == "x" && <other conditions>'
# Filter based on multiple partition key values
export filter='partition_key in ["x", "y", "z"] && <other conditions>'
É necessário substituir partition_key pelo nome do campo que é designado como chave de partição.
Usar o isolamento da chave de partição
No cenário multilocatário, pode designar o campo escalar relacionado com as identidades dos locatários como a chave de partição e criar um filtro com base num valor específico neste campo escalar. Para melhorar ainda mais o desempenho da pesquisa em cenários semelhantes, o Milvus introduz a funcionalidade Partition Key Isolation.
Isolamento da chave de partição
Como mostra a figura acima, Milvus agrupa as entidades com base no valor da chave de partição e cria um índice separado para cada um desses grupos. Ao receber um pedido de pesquisa, o Milvus localiza o índice com base no valor da Chave de Partição especificado na condição de filtragem e restringe o âmbito da pesquisa às entidades incluídas no índice, evitando assim a pesquisa de entidades irrelevantes durante a pesquisa e melhorando consideravelmente o desempenho da pesquisa.
Uma vez ativado o Isolamento da Chave de Partição, é necessário incluir apenas um valor específico no filtro baseado na Chave de Partição para que o Milvus possa restringir o âmbito da pesquisa dentro das entidades incluídas no índice que correspondem.
Atualmente, a funcionalidade Isolamento da Chave de Partição aplica-se apenas a pesquisas com o tipo de índice definido como HNSW.
Ativar o isolamento da chave de partição
Os exemplos de código a seguir demonstram como habilitar o Isolamento de chave de partição.
client.create_collection(
collection_name="my_collection",
schema=schema,
properties={"partitionkey.isolation": True}
)
import io.milvus.v2.service.collection.request.CreateCollectionReq;
Map<String, String> properties = new HashMap<>();
properties.put("partitionkey.isolation", "true");
CreateCollectionReq createCollectionReq = CreateCollectionReq.builder()
.collectionName("my_collection")
.collectionSchema(schema)
.properties(properties)
.build();
client.createCollection(createCollectionReq);
err = client.CreateCollection(ctx,
milvusclient.NewCreateCollectionOption("my_collection", schema).
WithProperty("partitionkey.isolation", true))
if err != nil {
fmt.Println(err.Error())
// handle error
}
res = await client.alterCollection({
collection_name: "my_collection",
properties: {
"partitionkey.isolation": true
}
})
export params='{
"partitionKeyIsolation": true
}'
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"
curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/create" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
-d "{
\"collectionName\": \"my_collection\",
\"schema\": $schema,
\"params\": $params
}"
Depois de ativar o isolamento da chave de partição, pode ainda definir a chave de partição e o número de partições, conforme descrito em Definir números de partição. Observe que o filtro baseado na Chave de partição deve incluir apenas um valor específico de Chave de partição.