milvus-logo
LFAI
首页
  • 用户指南

管理分区

本指南将指导您如何创建和管理 Collections 中的分区。

分区概述

在 Milvus 中,一个分区代表一个 Collections 的子分区。此功能允许将 Collections 的物理存储划分为多个部分,通过将关注点缩小到较小的数据子集而不是整个集合,有助于提高查询性能。

创建 Collections 时,至少会自动创建一个名为_default的默认分区。在一个 Collection 中最多可以创建 1,024 个分区。

注释

Milvus 引入了一项名为Partition Key 的功能,利用底层分区,根据特定字段的散列值来存储实体。该功能有助于实现多租户,提高搜索性能。有关详细信息,请阅读使用分区密钥

如果在 Collections 中开启了Partition Key功能,Milvus 会负责管理所有分区,从而减轻你的责任。

准备工作

下面的代码片段对现有代码进行了重新利用,以建立与 Milvus 的连接,并在快速设置模式下创建一个 Collection,表示创建时已加载该 Collection。

对于准备工作,使用 MilvusClient连接到 Milvus,并使用 create_collection()以快速设置模式创建 Collections。

对于准备工作,使用 MilvusClientV2连接 Milvus 并使用 createCollection()以快速设置模式创建 Collections。

对于准备工作,使用 MilvusClient连接到 Milvus,并使用 createCollection()以快速设置模式创建 Collections。

from pymilvus import MilvusClient, DataType

# 1. Set up a Milvus client
client = MilvusClient(
    uri="http://localhost:19530"
)

# 2. Create a collection
client.create_collection(
    collection_name="quick_setup",
    dimension=5,
)

import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.collection.request.CreateCollectionReq;

String CLUSTER_ENDPOINT = "http://localhost:19530";

// 1. Connect to Milvus server
ConnectConfig connectConfig = ConnectConfig.builder()
    .uri(CLUSTER_ENDPOINT)
    .build();

MilvusClientV2 client = new MilvusClientV2(connectConfig);

// 2. Create a collection in quick setup mode
CreateCollectionReq quickSetupReq = CreateCollectionReq.builder()
    .collectionName("quick_setup")
    .dimension(5)
    .build();

client.createCollection(quickSetupReq);
const address = "http://localhost:19530"

// 1. Set up a Milvus Client
client = new MilvusClient({address});

// 2. Create a collection in quick setup mode
await client.createCollection({
    collection_name: "quick_setup",
    dimension: 5,
});  

注释

在上述代码片段中,Collection 的索引已与 Collection 一同创建,表明创建时已加载 Collection。

列出分区

一旦集合就绪,就可以列出其分区。

要列出分区,请使用 list_partitions().

要列出分区,请使用 listPartitions().

要列出分区,请使用 listPartitions().

# 3. List partitions
res = client.list_partitions(collection_name="quick_setup")
print(res)

# Output
#
# ["_default"]
import io.milvus.v2.service.partition.request.ListPartitionsReq;

// 3. List all partitions in the collection
ListPartitionsReq listPartitionsReq = ListPartitionsReq.builder()
    .collectionName("quick_setup")
    .build();

List<String> partitionNames = client.listPartitions(listPartitionsReq);

System.out.println(partitionNames);

// Output:
// ["_default"]
// 3. List partitions
res = await client.listPartitions({
    collection_name: "quick_setup"
})

console.log(res.partition_names)

// Output
// 
// [ '_default' ]
// 

上述代码片段的输出包括指定 Collection 内分区的名称。

注释

如果在集合中设置了字段作为分区键,Milvus 会随集合创建至少64 个分区。在列出分区时,结果可能与上述代码片段的输出不同。

详情请参阅使用分区键

创建分区

您可以向 Collection 添加更多分区。一个 Collection 最多可以有 1,024 个分区。

要创建分区,请使用 create_partition().

要创建分区,请使用 createPartition().

要创建分区,请使用 createPartition().

# 4. Create more partitions
client.create_partition(
    collection_name="quick_setup",
    partition_name="partitionA"
)

client.create_partition(
    collection_name="quick_setup",
    partition_name="partitionB"
)

res = client.list_partitions(collection_name="quick_setup")
print(res)

# Output
#
# ["_default", "partitionA", "partitionB"]
import io.milvus.v2.service.partition.request.CreatePartitionReq;

// 4. Create more partitions
CreatePartitionReq createPartitionReq = CreatePartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

client.createPartition(createPartitionReq);

createPartitionReq = CreatePartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionB")
    .build();

client.createPartition(createPartitionReq);

listPartitionsReq = ListPartitionsReq.builder()
    .collectionName("quick_setup")
    .build();

partitionNames = client.listPartitions(listPartitionsReq);

System.out.println(partitionNames);

// Output:
// [
//     "_default",
//     "partitionA",
//     "partitionB"
// ]
// 4. Create more partitions
await client.createPartition({
    collection_name: "quick_setup",
    partition_name: "partitionA"
})

await client.createPartition({
    collection_name: "quick_setup",
    partition_name: "partitionB"
})

res = await client.listPartitions({
    collection_name: "quick_setup"
})

console.log(res.partition_names)

// Output
// 
// [ '_default', 'partitionA', 'partitionB' ]
// 

上面的代码片段在一个 Collection 中创建了一个分区,并列出了该 Collection 的分区。

注释

如果你在一个 Collection 中设置了一个字段作为分区键,Milvus 会负责管理 Collection 中的分区。因此,在尝试创建分区时可能会遇到提示错误。

有关详细信息,请参阅使用分区密钥

检查特定分区

您还可以检查特定分区是否存在。

要检查特定分区,请使用 has_partition().

要检查特定分区,请使用 hasPartition().

要检查特定分区,请使用 hasPartition().

# 5. Check whether a partition exists
res = client.has_partition(
    collection_name="quick_setup",
    partition_name="partitionA"
)
print(res)

# Output
#
# True

res = client.has_partition(
    collection_name="quick_setup",
    partition_name="partitionC"
)
print(res)

# Output
#
# False
import io.milvus.v2.service.partition.request.HasPartitionReq;

// 5. Check whether a partition exists
HasPartitionReq hasPartitionReq = HasPartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

boolean exists = client.hasPartition(hasPartitionReq);

System.out.println(exists);

// Output:
// true

hasPartitionReq = HasPartitionReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionC")
    .build();

exists = client.hasPartition(hasPartitionReq);

System.out.println(exists);

// Output:
// false
// 5. Check whether a partition exists
res = await client.hasPartition({
    collection_name: "quick_setup",
    partition_name: "partitionA"
})

console.log(res.value)

// Output
// 
// true
// 

res = await client.hasPartition({
    collection_name: "quick_setup",
    partition_name: "partitionC"
})

console.log(res.value)

// Output
// 
// false
// 

上面的代码片段会检查 Collection 是否有名为partitionApartitionC 的分区。

加载和释放分区

您可以加载和释放特定分区,使其对搜索和查询可用或不可用。

获取加载状态

要检查 Collections 及其分区的加载状态,请使用 get_load_state().

要检查 Collections 及其分区的加载状态,请使用 getLoadState().

要检查 Collections 及其分区的负载状态,请使用 getLoadState().

# Release the collection
client.release_collection(collection_name="quick_setup")

# Check the load status
res = client.get_load_state(collection_name="quick_setup")
print(res)

# Output
#
# {
#     "state": "<LoadState: Loaded>"
# }

res = client.get_load_state(
    collection_name="quick_setup", 
    partition_name="partitionA"
)

print(res)

# Output
#
# {
#     "state": "<LoadState: Loaded>"
# }

res = client.get_load_state(
    collection_name="quick_setup", 
    partition_name="partitionB"
)

print(res)

# Output
#
# {
#     "state": "<LoadState: NotLoad>"
# }

import io.milvus.v2.service.collection.request.GetLoadStateReq;
import io.milvus.v2.service.collection.request.ReleaseCollectionReq;
import io.milvus.v2.service.partition.request.LoadPartitionsReq;
import io.milvus.v2.service.partition.request.ReleasePartitionsReq;

// 6. Load a partition independantly
// 6.1 Release the collection
ReleaseCollectionReq releaseCollectionReq = ReleaseCollectionReq.builder()
    .collectionName("quick_setup")
    .build();

client.releaseCollection(releaseCollectionReq);

// 6.2 Load partitionA
LoadPartitionsReq loadPartitionsReq = LoadPartitionsReq.builder()
    .collectionName("quick_setup")
    .partitionNames(List.of("partitionA"))
    .build();

client.loadPartitions(loadPartitionsReq);

Thread.sleep(3000);

// 6.3 Check the load status of the collection and its partitions
GetLoadStateReq getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .build();

boolean state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// true

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// true

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionB")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// false
// 6. Load a partition indenpendantly
await client.releaseCollection({
    collection_name: "quick_setup"
})

res = await client.getLoadState({
    collection_name: "quick_setup"
})

console.log(res.state)

// Output
// 
// LoadStateNotLoad
// 

await client.loadPartitions({
    collection_name: "quick_setup",
    partition_names: ["partitionA"]
})

await sleep(3000)

res = await client.getLoadState({
    collection_name: "quick_setup"
})

console.log(res.state)

// Output
// 
// LoadStateLoaded
// 

res = await client.getLoadState({
    collection_name: "quick_setup",
    partition_name: "partitionA"
})

console.log(res.state)

// Output
// 
// LoadStateLoaded
// 

res = await client.getLoadState({
    collection_name: "quick_setup",
    partition_name: "partitionB"
})

console.log(res.state)

// Output
// 
// LoadStateLoaded
// 

可能的加载状态如下

  • 已加载

    如果一个 Collection 的至少一个分区已加载,则该 Collection 会被标记为Loaded

  • 未加载

    如果一个 Collection 的任何分区都未加载,则将其标记为NotLoad

  • 加载中

    如果集合中至少有一个分区处于加载过程中,则该集合会被标记为正在加载。

加载分区

要加载 Collections 的所有分区,只需调用 load_collection().要加载 Collections 的特定分区,可使用 load_partitions().

要加载 Collections 的所有分区,只需调用 loadCollection().要加载 Collections 的特定分区,可使用 loadPartitions().

要加载 Collections 的所有分区,只需调用 loadCollection().要加载 Collections 的特定分区,可使用 loadPartitions().

client.load_partitions(
    collection_name="quick_setup",
    partition_names=["partitionA"]
)

res = client.get_load_state(collection_name="quick_setup")
print(res)

# Output
#
# {
#     "state": "<LoadState: Loaded>"
# }
LoadPartitionsReq loadPartitionsReq = LoadPartitionsReq.builder()
    .collectionName("quick_setup")
    .partitionNames(List.of("partitionA"))
    .build();

client.loadPartitions(loadPartitionsReq);

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// true
await client.loadPartitions({
    collection_name: "quick_setup",
    partition_names: ["partitionA"]
})

res = await client.getLoadState({
    collection_name: "quick_setup",
    partition_name: "partitionA"
})

console.log(res.state)

// Output
// 
// LoadStateLoaded
//

要一次加载多个分区,请按以下步骤操作:

client.load_partitions(
    collection_name="quick_setup",
    partition_names=["partitionA", "partitionB"]
)

res = client.get_load_state(
    collection_name="quick_setup",
    partition_name="partitionA"
)

# Output
#
# {
#     "state": "<LoadState: Loaded>"
# }

res = client.get_load_state(
    collection_name="quick_setup",
    partition_name="partitionB"
)

# Output
#
# {
#     "state": "<LoadState: Loaded>"
# }
LoadPartitionsReq loadPartitionsReq = LoadPartitionsReq.builder()
    .collectionName("quick_setup")
    .partitionNames(List.of("partitionA", "partitionB"))
    .build();

client.loadPartitions(loadPartitionsReq);

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// true

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionB")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// true
await client.loadPartitions({
    collection_name: "quick_setup",
    partition_names: ["partitionA", "partitionB"]
})

res = await client.getLoadState({
    collection_name: "quick_setup",
    partition_name: "partitionA"
})

console.log(res)

// Output
// 
// LoadStateLoaded
// 

res = await client.getLoadState({
    collection_name: "quick_setup",
    partition_name: "partitionB"
})

console.log(res)

// Output
// 
// LoadStateLoaded
// 

要加载一个或多个分区中的指定字段,请执行以下操作:

client.load_partitions(
    collection_name="quick_setup",
    partition_names=["partitionA"],
    load_fields=["id", "vector"],
    skip_load_dynamic_field=True
)

请注意,只有load_fields 中列出的字段才能用作搜索和查询中的筛选条件和输出字段。列表中应始终包含主键。不加载的字段名将不能用于筛选或输出。

可以使用skip_load_dynamic_field=True 跳过加载动态字段。Milvus 将动态字段视为单个字段,因此动态字段中的所有键将一起被包含或排除。

释放分区

要释放 Collections 的所有分区,只需调用 release_collection().要释放 Collections 的特定分区,可使用 release_partitions().

要释放 Collections 的所有分区,只需调用 releaseCollection().要释放集合的特定分区,可使用 releasePartitions().

要释放 Collection 的所有分区,只需调用 . releaseCollection().要释放集合的特定分区,可使用 releasePartitions().

# 7. Release a partition
client.release_partitions(
    collection_name="quick_setup",
    partition_names=["partitionA"]
)

res = client.get_load_state(
    collection_name="quick_setup", 
    partition_name="partitionA"
)

print(res)

# Output
#
# {
#     "state": "<LoadState: NotLoad>"
# }

import io.milvus.v2.service.partition.request.ReleasePartitionsReq;

// 7. Release a partition
ReleasePartitionsReq releasePartitionsReq = ReleasePartitionsReq.builder()
    .collectionName("quick_setup")
    .partitionNames(List.of("partitionA"))
    .build();

client.releasePartitions(releasePartitionsReq);

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .partitionName("partitionA")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// false
// 7. Release a partition
await client.releasePartitions({
    collection_name: "quick_setup",
    partition_names: ["partitionA"]
})

res = await client.getLoadState({
    collection_name: "quick_setup"
})

console.log(res.state)

// Output
// 
// LoadStateNotLoad
// 

要同时释放多个分区,请按以下步骤操作:

client.release_partitions(
    collection_name="quick_setup",
    partition_names=["_default", "partitionA", "partitionB"]
)

res = client.get_load_state(
    collection_name="quick_setup",
)

# Output
#
# {
#     "state": "<LoadState: NotLoad>"
# }

丢弃分区

释放分区后,如果不再需要该分区,就可以将其丢弃。

要丢弃分区,请使用 drop_partition().

要放弃一个分区,请使用 dropPartition().

要下拉分区,请使用 dropPartition().

# 8. Drop a partition
client.drop_partition(
    collection_name="quick_setup",
    partition_name="partitionB"
)

res = client.list_partitions(collection_name="quick_setup")
print(res)

# Output
#
# ["_default", "partitionA"]
import io.milvus.v2.service.partition.request.ReleasePartitionsReq;

ReleasePartitionsReq releasePartitionsReq = ReleasePartitionsReq.builder()
    .collectionName("quick_setup")
    .partitionNames(List.of("_default", "partitionA", "partitionB"))
    .build();

client.releasePartitions(releasePartitionsReq);

getLoadStateReq = GetLoadStateReq.builder()
    .collectionName("quick_setup")
    .build();

state = client.getLoadState(getLoadStateReq);

System.out.println(state);

// Output:
// false

await client.releasePartitions({
    collection_name: "quick_setup",
    partition_names: ["_default", "partitionA", "partitionB"]
})

res = await client.getLoadState({
    collection_name: "quick_setup"
})

console.log(res)

// Output
// 
// {
//   status: {
//     error_code: 'Success',
//     reason: '',
//     code: 0,
//     retriable: false,
//     detail: ''
//   },
//   state: 'LoadStateNotLoad'
// }
// 

注意事项

在丢弃分区之前,需要将其从内存中释放。

常见问题

  • 分区中可以存储多少数据?

    建议在一个分区中存储少于 1B 的数据。

  • 最多可以创建多少个分区?

    默认情况下,Milvus 最多允许创建 1,024 个分区。您可以通过配置rootCoord.maxPartitionNum 来调整分区的最大数量。有关详情,请参阅系统配置

  • 如何区分分区和分区 Key?

    分区是物理存储单元,而分区密钥是逻辑概念,可根据指定列自动将数据分配到特定分区。

    例如,在 Milvus 中,如果你的 Collections 的分区键定义为color 字段,系统会根据每个实体的color 字段的散列值自动将数据分配到分区。这一自动化流程免除了用户在插入或搜索数据时手动指定分区的责任。

    另一方面,在手动创建分区时,需要根据分区 Key 的标准为每个分区分配数据。如果你有一个带有color 字段的 Collections,你会手动将color 值为red 的实体分配到partition A ,将color 值为blue 的实体分配到partition B 。这种手动管理需要更多的精力。

    总之,分区和分区 Key 都是用来优化数据计算和提高查询效率的。必须认识到,启用分区键意味着放弃对分区数据插入和加载的人工管理控制,因为这些过程完全由 Milvus 自动处理。

翻译自DeepL

想要更快、更简单、更好用的 Milvus SaaS服务 ?

Zilliz Cloud是基于Milvus的全托管向量数据库,拥有更高性能,更易扩展,以及卓越性价比

免费试用 Zilliz Cloud
反馈

此页对您是否有帮助?