mmapの使用
メモリマッピング(Mmap)は、ディスク上の大容量ファイルへの直接メモリアクセスを可能にし、Milvusがインデックスとデータをメモリとハードディスクの両方に格納することを可能にします。このアプローチにより、アクセス頻度に基づいてデータ配置ポリシーを最適化し、検索パフォーマンスに大きな影響を与えることなくコレクションのストレージ容量を拡張することができます。このページは、Milvusがどのようにmmapを使用し、高速で効率的なデータの保存と検索を可能にしているかを理解するのに役立ちます。
概要
Milvusはベクトル埋め込みとそのメタデータを整理するためにコレクションを使用し、コレクション内の各行はエンティティを表します。下の左図に示すように、ベクトルフィールドにはベクトル埋め込みが格納され、スカラーフィールドにはそのメタデータが格納されます。特定のフィールドにインデックスを作成し、コレクションをロードすると、Milvusは作成したインデックスとフィールドの生データをメモリにロードします。
Mmap図解
Milvusはメモリ集約型のデータベースシステムであり、利用可能なメモリサイズがコレクションの容量を決定します。大量のデータを含むフィールドをメモリにロードすることは、データサイズがメモリ容量を超える場合には不可能である。
このような問題を解決するために、Milvusは、コレクション内のホットデータとコールドデータのロードのバランスをとるためのmmapを導入している。上の右図に示すように、Milvusは特定のフィールドの生データを完全にメモリにロードするのではなく、メモリマップするように設定することができる。こうすることで、メモリの問題を心配することなくフィールドに直接メモリアクセスすることができ、コレクションの容量を拡張することができます。
左図と右図のデータ配置手順を比較すると、左図の方が右図よりもメモリ使用量がはるかに多いことがわかる。mmapを有効にすると、メモリにロードされるべきデータがハードディスクにオフロードされ、オペレーティング・システムのページ・キャッシュにキャッシュされるため、メモリ・フットプリントが削減される。ただし、キャッシュ・ヒットに失敗するとパフォーマンスが低下する可能性がある。詳細については、この記事を参照してください。
Milvusでmmapを設定する場合、必ず守るべき原則があります:頻繁にアクセスされるデータとインデックスは常に完全にメモリにロードしておき、残りのフィールドでmmapを使用することです。
Milvusでmmapを使用する
Milvusでは、グローバルレベル、フィールドレベル、インデックスレベル、コレクションレベルの階層的なmmap設定が可能で、インデックスレベルとフィールドレベルはコレクションレベルより優先され、コレクションレベルはグローバルレベルより優先されます。
グローバルmmap設定
クラスタレベルの設定はグローバルな設定であり、最も優先順位が低くなります。Milvusはいくつかのmmap関連の設定をmilvus.yaml 。これらの設定はクラスタ内のすべてのコレクションに適用されます。
...
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
....
設定 項目 |
説明 |
デフォルト値 |
|---|---|---|
|
すべてのスカラ・フィールドの生データをメモリにマップするかどうかを指定します。これを |
|
|
すべてのスカラーフィールドインデックスをメモリにマップするかどうかを指定します。これを 現在、以下のインデックスタイプを使用するスカラーフィールドのみがサポートされています:
|
|
|
すべてのベクトル・フィールドの生データをメモリにマップするかどうかを指定します。これを |
|
|
すべてのベクトルフィールドのインデックスをメモリにマップするかどうかを指定します。これを 現在、以下のインデックスタイプを使用するベクトルフィールドのみがサポートされています:
|
|
|
メモリー・マップド・ファイルへのパスを指定する。未指定の場合はデフォルト値が適用されます。 デフォルト値の |
|
上記の設定をMilvusクラスタに適用するには、HelmによるMilvusの設定およびMilvus OperatorsによるMilvusの設定の手順に従ってください。
特定のユースケースに直面した場合、グローバルなmmap設定が柔軟でないことがあります。特定のコレクションまたはそのインデックスに別の設定を適用するには、コレクション、フィールド、またはインデックスに固有のmmapを構成することを検討してください。mmap設定の変更が有効になる前に、コレクションをリリースしてロードする必要があります。
フィールド固有の mmap 設定
フィールド固有のmmapを構成するには、フィールドを追加するときにmmap_enabled パラメータを含める必要があります。このパラメータをTrue に設定することで、特定のフィールドで mmap を有効にできます。
以下の例は、フィールドを追加するときにフィールド固有のmmapを設定する方法を示している。
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
}
}'
大容量データを格納するフィールドに対してmmapを有効にすることを検討してください。スカラー・フィールドとベクトル・フィールドの両方がサポートされている。
次に、上記で作成したスキーマを使用してコレクションを作成します。Milvusはコレクションのロード要求を受け取ると、doc_chunkフィールドの生データをメモリマップしてメモリに格納します。
インデックス固有のmmap設定
インデックス固有のmmapを設定するには、インデックスを追加する際にインデックスパラメータにmmap.enable プロパティを含める必要があります。このプロパティをtrue に設定することで、この特定のインデックスで mmap を有効にすることができます。
以下の例は、インデックスを追加するときにインデックス固有の mmap を設定する方法を示しています。
# 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
}
}'
これは、ベクトル・フィールドとスカラー・フィールドの両方のインデックスに適用されます。
次に、コレクション内のインデックス・パラメータを参照できます。コレクションをロードするリクエストを受け取ると、milvusはタイトルフィールドのインデックスをメモリにメモリマップします。
コレクション固有のmmap設定
コレクション全体のmmap戦略を設定するには、コレクションを作成するリクエストにmmap.enabled プロパティを含める必要があります。このプロパティをtrue に設定すると、コレクションの mmap を有効にできます。
以下の例では、my_collectionという名前のコレクションを作成するときに mmap を有効にする方法を示します。コレクションをロードするリクエストを受け取ると、milvusはすべてのフィールドの生データをメモリにメモリマップします。
# 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\"
}
}"
既存のコレクションのmmap設定を変更することもできます。
# 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"
}'
コレクションをリリースしてプロパティを変更し、コレクションをリロードして変更を有効にする必要があります。