• 關於 Milvus
  • 開始使用
  • 概念
  • 使用者指南
  • 資料匯入
  • AI 工具
  • 管理指南
  • 工具
  • 整合
  • 教學
  • 常見問題
  • API Reference

聚類壓縮

聚類壓縮的目的是在大型資料集中改善搜尋效能並降低成本。本指南將協助您瞭解聚類壓縮以及此功能如何改善搜尋效能。

概述

Milvus 將傳入的實體儲存於集合中的區段,並在區段已滿時封閉該區段。如果發生這種情況,就會創建一個新的區段來容納額外的實體。因此,實體會任意地分佈在區段中。這種分佈方式需要 Milvus 搜尋多個區段,以找出與指定查詢向量最近的鄰居。

Without Clustering Compaction 沒有聚類壓縮

如果 Milvus 可以根據特定欄位中的值,將實體分佈在區段中,搜尋範圍就可以限制在一個區段內,進而改善搜尋效能。

聚類壓縮 (Clustering Compaction) 是 Milvus 的一項功能,可根據標量欄位中的值,在集合中的段之間重新分配實體。要啟用此功能,您首先需要選擇標量欄位作為聚類關鍵。這可讓 Milvus 在實體的聚類關鍵值在特定範圍內時,將實體重新分配到段中。當您觸發聚類壓縮時,Milvus 會產生/更新稱為PartitionStats 的全局索引,它會記錄段和聚類關鍵值之間的映射關係。

Clustering Compaction 聚類壓縮

使用PartitionStats作為參考,Milvus 可以在收到帶有聚類關鍵值的搜尋/查詢請求時,修剪不相關的資料,並將搜尋範圍限制在與該值對應的區段內,從而改善搜尋效能。有關效能改善的詳細資訊,請參閱基準測試

使用聚類壓縮

Milvus 的聚類壓縮功能是高度可配置的。您可以選擇手動觸發,或設定為由 Milvus 每隔一段時間自動觸發。要啟用叢集壓縮,請執行下列步驟:

全局設定

您需要修改您的 Milvus 配置文件,如下所示。

dataCoord:
  compaction:
    clustering:
      enable: true 
      autoEnable: false 
      triggerInterval: 600 
      minInterval: 3600 
      maxInterval: 259200 
      newDataSizeThreshold: 512m 
      timeout: 7200
     
queryNode:
  enableSegmentPrune: true 

datanode:
  clusteringCompaction:
    memoryBufferRatio: 0.1 
    workPoolSize: 8  
common:
  usePartitionKeyAsClusteringKey: true 

設定項目

說明

預設值

dataCoord.compaction.clustering

enable

指定是否啟用叢集壓縮。如果您需要為每個有群集鍵的集合啟用此功能,請將此值設定為true

autoEnable

指定是否啟用自動觸發壓縮。將此設定為true 表示 Milvus 會在指定的時間間隔壓縮有聚類關鍵的集合。

triggerInterval

指定 Milvus 開始叢集壓縮的間隔 (毫秒)。這只適用於設定autoEnabletrue 時。

minInterval

以毫秒為單位指定最小間隔。這只在您設定autoEnabletrue 時適用。

將此設定為大於triggerInterval 的整數,有助於避免在短時間內重複壓縮。

maxInterval

以毫秒為單位指定最大間隔。只有當您將autoEnable 設定為true 時才適用。

一旦 Milvus 偵測到一個集合沒有被叢集壓縮的時間超過這個值,它就會強制叢集壓縮。

newDataSizeThreshold

指定觸發聚類壓縮的上臨界值。只有當您將autoEnable 設定為true 時,這才適用。

一旦 Milvus 檢測到資料集中的資料量超過此值,就會啟動叢集壓縮程序。

timeout

指定叢集壓縮的逾時持續時間。如果集群壓縮的執行時間超過此值,則壓縮失敗。

queryNode

enableSegmentPrune

指定 Milvus 是否在收到搜尋/查詢請求時,參考 PartitionStats 來刪除資料。將此設定為true ,以便 Milvus 可以在收到搜尋/查詢請求時,參考 PartitionStats 來修剪資料。

dataNode.clusteringCompaction

memoryBufferRatio

指定集群壓縮任務的記憶體緩衝比率。 當資料大小超過使用此比率計算的分配緩衝區大小時,Milvus 會清除資料。

workPoolSize

指定聚類壓縮任務的工作池大小。

common

usePartitionKeyAsClusteringKey

指定是否使用集合中的分割鍵作為群集鍵。將此設定為 true 會使 Milvus 將集合中的分割區金鑰視為叢集金鑰。

您可以在集合中透過明確設定叢集金鑰來覆寫此設定。

要將上述變更套用到您的 Milvus 叢集,請遵循「使用 Helm 設定 Milvus」和「使用 Milvus Operators 設定 Milvus」中的步驟。

叢集設定

若要在特定的集合中進行聚類壓縮,您應該從集合中選擇一個標量欄位作為聚類關鍵。

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("key", DataType.INT64, is_clustering_key=True)
schema.add_field("var", DataType.VARCHAR, max_length=1000)
schema.add_field("vector", DataType.FLOAT_VECTOR, dim=5)

client.create_collection(
    collection_name="clustering_test",
    schema=schema
)
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());
        
CreateCollectionReq.CollectionSchema schema = client.createSchema();

schema.addField(AddFieldReq.builder()
        .fieldName("id")
        .dataType(DataType.Int64)
        .isPrimaryKey(true)
        .autoID(false)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("key")
        .dataType(DataType.Int64)
        .isClusteringKey(true)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("var")
        .dataType(DataType.VarChar)
        .maxLength(1000)
        .build());

schema.addField(AddFieldReq.builder()
        .fieldName("vector")
        .dataType(DataType.FloatVector)
        .dimension(5)
        .build());

CreateCollectionReq requestCreate = CreateCollectionReq.builder()
        .collectionName("clustering_test")
        .collectionSchema(schema)
        .build();
client.createCollection(requestCreate);
// go
import { MilvusClient, DataType } from '@zilliz/milvus2-sdk-node';

const CLUSTER_ENDPOINT = 'http://localhost:19530';
const TOKEN = 'root:Milvus';
const client = new MilvusClient({
  address: CLUSTER_ENDPOINT,
  token: TOKEN,
});
const schema = [
    {
      name: 'id',
      type: DataType.Int64,
      is_primary_key: true,
      autoID: false,
    },
    {
      name: 'key',
      type: DataType.Int64,
      is_clustering_key: true,
    },
    {
      name: 'var',
      type: DataType.VarChar,
      max_length: 1000,
      is_primary_key: false,
    },
    {
      name: 'vector',
      type: DataType.FloatVector,
      dim: 5,
    },
  ];
  
  await client.createCollection({
    collection_name: 'clustering_test',
    schema: schema,
  });
# restful

您可以使用下列資料類型的標量欄位作為聚類關鍵:Int8,Int16,Int32,Int64,Float,Double, 以及VarChar

觸發聚類壓縮

如果您啟用了自動聚類壓縮,Milvus 會在指定的間隔自動觸發壓縮。或者,您可以按以下方式手動觸發壓縮:

# trigger a manual compaction
job_id = client.compact(
    collection_name="clustering_test", 
    is_clustering=True
)

# get the compaction state
client.get_compaction_state(
    job_id=job_id,
)
import io.milvus.v2.service.utility.request.CompactReq;
import io.milvus.v2.service.utility.request.GetCompactionStateReq;
import io.milvus.v2.service.utility.response.CompactResp;
import io.milvus.v2.service.utility.response.GetCompactionStateResp;

CompactResp compactResp = client.compact(CompactReq.builder()
        .collectionName("clustering_test")
        .isClustering(true)
        .build());

GetCompactionStateResp stateResp = client.getCompactionState(GetCompactionStateReq.builder()
        .compactionID(compactResp.getCompactionID())
        .build());

System.out.println(stateResp.getState());
// go
// trigger a manual compaction
const {compactionID} = await client.compact({
    collection_name: "clustering_test", 
    is_clustering: true
});

// get the compaction state
await client.getCompactionState({
    compactionID: compactionID,
});
# restful

基準測試

資料量與查詢模式的結合決定了叢集壓縮所能帶來的效能改善。一項內部基準測試證明,聚類壓縮在每秒查詢次數上 (QPS) 最多可提升 25 倍。

該基準測試是在一個包含來自 2,000 萬個、768 維 LAION 資料集中的實體的集合上進行的,其中key 欄位被指定為聚類關鍵。在集合中觸發聚類壓縮後,會發送並發搜尋,直到 CPU 使用量達到高水位為止。

搜尋篩選

剪除率

延遲

要求/秒

平均值

最小值

最大值

中位數

TP99

不適用

0%

1685

672

2294

1710

2291

17.75

鍵 > 200 且鍵 < 800

40.2%

1045

47

1828

1085

1617

28.38

鍵 > 200 且鍵 < 600

59.8%

829

45

1483

882

1303

35.78

鍵 > 200 且鍵 < 400

79.5%

550

100

985

584

898

54.00

關鍵字==1000

99%

68

24

1273

70

246

431.41

隨著搜尋篩選器中的搜尋範圍縮小,剪枝比率也會增加。這表示在搜尋過程中,會跳過更多的實體。比較第一行和最後一行的統計資料時,您可以看到沒有進行聚類壓縮的搜尋需要掃描整個集合。另一方面,使用特定關鍵詞進行聚類壓縮的搜尋可達到 25 倍的改善。

最佳實務

以下是一些有效使用聚類壓縮的提示:

  • 對於具有大量資料的集合啟用此功能。

    資料集中的資料量越大,搜尋效能就越高。對於超過 100 萬個實體的資料集,啟用此功能是個不錯的選擇。

  • 選擇適當的群集關鍵字。

    您可以使用常被用作篩選條件的標量欄位作為叢集關鍵。對於包含來自多個租戶資料的集合,您可以使用區別一個租戶與另一個租戶的欄位作為簇集索引鍵。

  • 使用分割區金鑰作為群集金鑰。

    如果您想為 Milvus 實例中的所有集合啟用此功能,或在使用分割區金鑰的大型集合中仍面臨績效問題,則可將common.usePartitionKeyAsClusteringKey 設為true 。這樣做,當您選擇一個集合中的標量欄位作為分割鍵時,您就會有一個群集鍵和一個分割鍵。

    請注意,此設定不會阻止您選擇其他標量欄位作為叢集索引鍵。明確指定的簇集索引鍵總是優先。

免費嘗試托管的 Milvus

Zilliz Cloud 無縫接入,由 Milvus 提供動力,速度提升 10 倍。

開始使用
反饋

這個頁面有幫助嗎?