クラスタリング・コンパクション
クラスタリング・コンパクションは、大規模なコレクションの検索パフォーマンスを向上させ、コストを削減するために設計されています。このガイドでは、クラスタリング・コンパクションと、この機能による検索パフォーマンスの向上について説明します。
概要
Milvusは入力されたエンティティをコレクション内のセグメントに格納し、セグメントが一杯になるとそのセグメントを封印します。この場合、追加のエンティティを収容するために新しいセグメントが作成されます。その結果、エンティティはセグメント間で任意に分散される。この分散により、Milvus は複数のセグメントを検索して、与えられたクエリベクトルに最も近いものを見つける必要がある。
クラスタリングコンパクションなし
もし Milvus が特定のフィールドの値に基づいてセグメント間でエンティティを分散させることができれば、検索範囲をセグメント内に制限することができ、検索性能が向上します。
クラスタリングコンパクションはMilvusの機能で、スカラーフィールドの値に基づいてコレクション内のセグメント間でエンティティを再分配します。この機能を有効にするには、まずクラスタリングキーとしてスカラーフィールドを選択する必要があります。これにより、Milvusはクラスタリングキーの値が特定の範囲内にあるエンティティをセグメントに再分配することができます。クラスタリングコンパクションをトリガーすると、MilvusはPartitionStatsというグローバルインデックスを生成/更新し、セグメントとクラスタリングキー値のマッピング関係を記録します。
クラスタリングコンパクション
PartitionStatsを参照として、Milvusはクラスタリングキー値を持つ検索/クエリリクエストを受信した際に無関係なデータを刈り込み、その値にマッピングされたセグメント内で検索範囲を制限することで、検索パフォーマンスを向上させることができます。性能向上の詳細については、ベンチマークテストを参照してください。
クラスタリング・コンパクションの使用
MilvusのClustering Compaction機能は高度な設定が可能です。手動で起動させることも、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
設定項目 |
設定項目 |
デフォルト値 |
|---|---|---|
|
||
|
クラスタリングコンパクションを有効にするかどうかを指定します。クラスタリングキーを持つすべてのコレクションでこの機能を有効にする必要がある場合、 |
false |
|
自動的にトリガーされるコンパクションを有効にするかどうかを指定します。これを |
false |
|
Milvusがクラスタリング圧縮を開始する間隔をミリ秒単位で指定します。これは、 |
|
|
最小間隔をミリ秒単位で指定します。これは これを |
|
|
最大間隔をミリ秒単位で指定します。 Milvusは、コレクションがこの値より長い期間クラスタリング圧縮されていないことを検出すると、強制的にクラスタリング圧縮を行います。 |
|
|
クラスタリング圧縮をトリガする上限しきい値を指定します。これは、 Milvusは、コレクション内のデータ量がこの値を超えたことを検出すると、クラスタリングコンパクション処理を開始します。 |
|
|
クラスタリングコンパクションのタイムアウト時間を指定します。実行時間がこの値を超えると、クラスタリング圧縮は失敗します。 |
|
|
||
|
Milvusが検索/クエリ要求を受信したときに、PartitionStatsを参照してデータをプルーンするかどうかを指定します。これを |
|
|
||
|
クラスタリング・コンパクション・タスクのメモリ・バッファ比率を指定します。 Milvusは、データサイズがこの比率を使用して計算された割り当てバッファサイズを超えると、データをフラッシュします。 |
|
|
クラスタリング・コンパクション・タスクのワーカープールサイズを指定します。 |
|
|
||
|
コレクション内のパーティション・キーをクラスタリング・キーとして使用するかどうかを指定します。これを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
ベンチマークテスト
データ量とクエリパターンの組み合わせによって、クラスタリングコンパクションがもたらすパフォーマンスの向上が決まります。社内のベンチマーク・テストでは、クラスタリング・コンパクションによって1秒あたりのクエリー数(QPS)が最大25倍向上することが実証されています。
ベンチマークテストは、key フィールドをクラスタリングキーとして指定した、2,000 万、768 次元の LAION データセットのエンティティを含むコレクションを対象としている。コレクションでクラスタリング圧縮がトリガーされた後、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に設定できます。そうすることで、コレクション内のスカラーフィールドをパーティションキーとして選択した場合、クラスタリングキーとパーティションキーを持つことになります。この設定は、別のスカラー・フィールドをクラスタリング・キーとして選択することを妨げるものではありません。明示的に指定されたクラスタリング・キーが常に優先されます。