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

使用 mmap

記憶體映射 (Mmap) 可以直接存取磁碟上的大型檔案,讓 Milvus 可以同時在記憶體和硬碟中儲存索引和資料。這種方法有助於根據存取頻率優化資料放置政策,在不嚴重影響搜尋效能的情況下,擴大資料集的儲存容量。本頁可協助您瞭解 Milvus 如何使用 mmap 來實現快速、高效的資料儲存和檢索。

概述

Milvus 使用集合來組織向量嵌入及其元資料,集合中的每一行代表一個實體。如下左圖所示,向量欄位儲存向量嵌入,標量欄位儲存其元資料。當您在某些欄位建立索引並載入集合後,Milvus 會將建立的索引和欄位原始資料載入記憶體。

Mmap Illustrated Mmap 圖解

Milvus 是一個記憶體密集的資料庫系統,可用的記憶體大小決定了資料集的容量。如果資料大小超過記憶體容量,將包含大量資料的欄位載入記憶體是不可能的,這是 AI 驅動應用程式的通常情況。

為了解決這樣的問題,Milvus 引進了 mmap 來平衡集合中熱資料和冷資料的載入。如上右圖所示,您可以設定 Milvus 對某些欄位中的原始資料進行記憶體映射,而不是將其完全載入記憶體。如此一來,您就可以直接取得欄位的記憶體存取權,而不必擔心記憶體問題,並可擴充集合的容量。

比較左右兩圖的資料放置程序,您可以發現左圖的記憶體使用量遠高於右圖。啟用 mmap 後,原本應該載入記憶體的資料會被卸載到硬碟,並快取到作業系統的頁面快取記憶體中,減少記憶體佔用量。不過,快取記憶體命中失敗可能會導致效能下降。如需詳細資訊,請參閱本文

當您在 Milvus 上設定 mmap 時,總有一個原則需要您遵守:永遠保持經常存取的資料和索引完全載入記憶體,並在剩餘的欄位中使用 mmap 來處理這些資料和索引。

在 Milvus 中使用 mmap

Milvus 在全局、欄位、索引和集合層級提供分層的 mmap 設定,其中索引和欄位層級優先於集合層級,而集合層級優先於全局層級。

全局 mmap 設定

集群層級設定是全局設定,具有最低的優先順序。Milvus 在milvus.yaml 中提供了幾個 mmap 相關的設定。這些設定將適用於群集中的所有集合。

...
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 
....

設定項目

說明

預設值

queryNode.mmap.scalarField

指定是否將所有標量欄位的原始資料映射到記憶體。將此設定為true 會使 Milvus 將集合的標量欄位資料的原始資料映射到記憶體,而不是在收到針對此集合的載入請求時完全載入。

false

queryNode.mmap.scalarIndex

指定是否將所有標量欄位索引映射到記憶體。將此設定為true 會使 Milvus 在收到針對此集合的載入請求時,將集合的標量欄位索引映射到記憶體中,而不是完全載入它們。

目前,只支援使用下列索引類型的標量欄位:

  • INVERTED

false

queryNode.mmap.vectorField

指定是否將所有向量欄位的原始資料映射到記憶體。將此設定為true 會使 Milvus 在收到針對此集合的載入請求時,將集合向量欄位資料的原始資料映射到記憶體,而不是完全載入。

false

queryNode.mmap.vectorIndex

指定是否將所有向量欄位索引映射到記憶體。將此設定為true 會使 Milvus 在收到針對此集合的載入請求時,將集合的向量欄位索引映射到記憶體中,而不是完全載入。

目前,只支援使用下列索引類型的向量欄位:

  • FLAT

  • IVF_FLAT

  • IVF_SQ8

  • IVF_PQ

  • BIN_FLAT

  • BIN_IVF_FLAT

  • HNSW

  • SCANN

  • sparse_inverted_index

  • SPARSE_WAND

false

queryNode.mmap.mmapDirPath

指定記憶體映射檔案的路徑。如果未指定,則採用預設值。

預設值中的localStorage.path 占位符表示 Milvus QueryNodes 的硬碟。確保您的 QueryNodes 具有高效能硬碟,以獲得最佳的 mmap 優勢。

{localStorage.path}/mmap

要將上述設定套用到您的 Milvus 叢集,請依照Configure Milvus with HelmConfigure Milvus with Milvus Operators 的步驟。

有時候,全局 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" \
--header "Request-Timeout: 10" \
--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" \
--header "Request-Timeout: 10" \
-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" \
--header "Request-Timeout: 10" \
-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" \
--header "Request-Timeout: 10" \
-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" \
--header "Request-Timeout: 10" \
--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" \
--header "Request-Timeout: 10" \
-d '{
    "collectionName": "my_collection"
}'

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/collections/alter_properties" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-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" \
--header "Request-Timeout: 10" \
-d '{
    "collectionName": "my_collection"
}'

您需要釋放集合以變更其屬性,並重新載入集合使變更生效。

免費嘗試托管的 Milvus

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

開始使用
反饋

這個頁面有幫助嗎?