• 关于 Milvus
  • 开始使用
  • 概念
  • 用户指南
  • 数据导入
  • AI 工具
  • 管理指南
  • 工具
  • 集成
  • 教程
  • 常见问题解答
  • API Reference

BITMAP

位图索引是一种高效的索引技术,旨在提高低基数标量字段的查询性能。基数是指字段中不同值的数量。不同元素较少的字段被视为低基数字段。

该索引类型通过将字段值表示为紧凑的二进制格式,并对它们执行高效的位运算,从而有助于缩短标量查询的检索时间。与其他类型的索引相比,在处理低基数字段时,位图索引通常具有更高的空间利用率,且查询速度更快。

概述

“位图”(Bitmap) 一词由“位”(Bit) 和“映射”(Map)两个词组合而成。位是计算机中数据的最小单位,只能存储0或1 其中一个值。在此语境下,“映射”是指根据应将何种值分配给 0 和 1 来转换和组织数据的过程。

位图索引由两个主要组成部分构成:位图和键。键代表索引字段中的唯一值。每个唯一值都对应一个位图。这些位图的长度等于Collection中的记录数。 位图中的每个位对应Collection中的一条记录。如果某条记录中索引字段的值与键匹配,则对应的位被设为1;否则,设为0。

假设有一个包含“Category”和“Public”字段的文档Collection。我们希望检索属于“Tech”类别且对“Public”开放的文档。在这种情况下,位图索引的键就是“Tech”和“Public”。

Bitmap 位图

如图所示,Category和Public的位图索引分别为:

  • Tech:[1, 0, 1, 0, 0],这表明只有第 1 和第 3 个文档属于Tech类别。

  • Public:[1, 0, 0, 1, 0],这表明只有第 1 个和第 4 个文档对公众开放。

为了查找同时满足这两个条件的文档,我们对这两个位图执行位与(AND)运算:

  • Tech且Public:[1, 0, 0, 0, 0]

生成的位图 [1, 0, 0, 0, 0] 表明只有第一份文档(ID 1)同时满足这两个条件。通过使用位图索引和高效的位运算,我们可以快速缩小搜索范围,从而无需扫描整个数据集。

创建位图索引

要在 Milvus 中创建位图索引,请使用 `create_index() ` 方法,并将 `index_type ` 参数设置为 `"BITMAP"`。

from pymilvus import MilvusClient

client = MilvusClient(
    uri="http://localhost:19530",
)

index_params = client.prepare_index_params() # Prepare an empty IndexParams object, without having to specify any index parameters
index_params.add_index(
    field_name="category", # Name of the scalar field to be indexed
    index_type="BITMAP", # Type of index to be created
    index_name="category_bitmap_index" # Name of the index to be created
)

client.create_index(
    collection_name="my_collection", # Specify the collection name
    index_params=index_params
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.common.IndexParam;
import io.milvus.v2.service.index.request.CreateIndexReq;
import java.util.Collections;

MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
        .uri("http://localhost:19530")
        .build());

client.createIndex(CreateIndexReq.builder()
        .collectionName("my_collection")
        .indexParams(Collections.singletonList(IndexParam.builder()
                .fieldName("category")
                .indexType(IndexParam.IndexType.BITMAP)
                .indexName("category_bitmap_index")
                .build()))
        .build());
import (
    "context"
    "log"

    "github.com/milvus-io/milvus/client/v3/index"
    "github.com/milvus-io/milvus/client/v3/milvusclient"
)

ctx := context.Background()

cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address: "http://localhost:19530",
})

if err != nil {
    log.Fatal("failed to connect to milvus server: ", err.Error())
}

_, err = cli.CreateIndex(ctx, milvusclient.NewCreateIndexOption("my_collection", "category", index.NewBitmapIndex()).WithIndexName("category_bitmap_index"))

if err != nil {
    log.Fatal("failed to create index: ", err.Error())
}
use milvus::v2::prelude::*;

let config = ConnectConfig::new().uri("http://localhost:19530");

let client = ClientV2::new(&config).await?;

client
    .create_index(
        CreateIndexRequest::builder()
            .collection_name("my_collection")
            .index_param(
                IndexParam::new()
                    .field_name("category")
                    .index_type(IndexType::Bitmap)
                    .index_name("category_bitmap_index"),
            )
            .build()?,
    )
    .await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();

auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));

if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

status = client->CreateIndex(milvus::CreateIndexRequest().WithCollectionName("my_collection")
        .AddIndex(milvus::IndexDesc("category", "category_bitmap_index", milvus::IndexType::BITMAP)));

if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";

const client = new MilvusClient({ address: "http://localhost:19530" });

await client.createIndex({
    collection_name: "my_collection",
    field_name: "category",
    index_type: "BITMAP",
    index_name: "category_bitmap_index",
});
using Milvus.Client.V2;
using Milvus.Client.V2.Requests.Index;
using Milvus.Client.V2.Types;

var config = new ConnectConfig
{
    Uri = "http://localhost:19530"
};
using var client = new MilvusClientV2(config);
await client.ConnectAsync();

// Prepare index building params
var indexParam = new IndexParam(
    fieldName: "category",
    indexType: IndexType.Bitmap,
    indexName: "category_bitmap_index");

await client.CreateIndexAsync(new CreateIndexReq
{
    CollectionName = "my_collection",
    Indexes = [indexParam]
});
export CLUSTER_ENDPOINT="http://localhost:19530"
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": "category",
            "indexName": "category_bitmap_index",
            "indexType": "BITMAP"
        }
    ]
}'

# {
#     "code": 0,
#     "data": {}
# }

在此示例中,我们针对my_collection Collection的category 字段创建了一个位图索引。通过add_index() 方法指定字段名、索引类型和索引名称。

创建位图索引后,您可以在查询操作中使用filter 参数,根据已建立索引的字段执行标量过滤。这使您能够利用位图索引高效地缩小搜索结果范围。有关更多信息,请参阅《过滤原理说明》。

删除索引

使用drop_index() 方法从 Collection 中删除现有索引。

  • 在v2.6.3及更早版本中,在删除标量索引之前,必须先释放 Collection。

  • 从v2.6.4及更高版本开始,一旦不再需要标量索引,即可直接删除,无需先释放 Collection。

client.drop_index(
    collection_name="my_collection",   # Name of the collection
    index_name="category_bitmap_index" # Name of the index to drop
)
import io.milvus.v2.client.ConnectConfig;
import io.milvus.v2.client.MilvusClientV2;
import io.milvus.v2.service.index.request.DropIndexReq;

MilvusClientV2 client = new MilvusClientV2(ConnectConfig.builder()
        .uri("http://localhost:19530")
        .build());

client.dropIndex(DropIndexReq.builder()
        .collectionName("my_collection")
        .indexName("category_bitmap_index")
        .build());
import (
    "context"
    "log"

    "github.com/milvus-io/milvus/client/v3/milvusclient"
)

ctx := context.Background()

cli, err := milvusclient.New(ctx, &milvusclient.ClientConfig{
    Address: "http://localhost:19530",
})

if err != nil {
    log.Fatal("failed to connect to milvus server: ", err.Error())
}

err = cli.DropIndex(ctx, milvusclient.NewDropIndexOption("my_collection", "category_bitmap_index"))

if err != nil {
    log.Fatal("failed to drop index: ", err.Error())
}
use milvus::v2::prelude::*;

let config = ConnectConfig::new().uri("http://localhost:19530");

let client = ClientV2::new(&config).await?;

client
    .drop_index(
        DropIndexRequest::builder()
            .collection_name("my_collection")
            .index_name("category_bitmap_index")
            .build()?,
    )
    .await?;
#include <iostream>
#include "milvus/MilvusClientV2.h"

auto client = milvus::MilvusClientV2::Create();

auto status = client->Connect(milvus::ConnectParam("http://localhost:19530"));

if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}

status = client->DropIndex(milvus::DropIndexRequest()
        .WithCollectionName("my_collection")
        .WithIndexName("category_bitmap_index"));

if (!status.IsOk()) {
    std::cout << status.Message() << std::endl;
}
import { MilvusClient } from "@zilliz/milvus2-sdk-node";

const client = new MilvusClient({ address: "http://localhost:19530" });

await client.dropIndex({
    collection_name: "my_collection",
    index_name: "category_bitmap_index",
});
using Milvus.Client.V2.Requests.Index;

await client.DropIndexAsync(new DropIndexReq
{
    CollectionName = "my_collection", // Name of the collection
    IndexName = "category_bitmap_index" // Name of the index to drop
});
export CLUSTER_ENDPOINT="http://localhost:19530"
export TOKEN="root:Milvus"

curl --request POST \
--url "${CLUSTER_ENDPOINT}/v2/vectordb/indexes/drop" \
--header "Authorization: Bearer ${TOKEN}" \
--header "Content-Type: application/json" \
--header "Request-Timeout: 10" \
-d '{
    "collectionName": "my_collection",
    "indexName": "category_bitmap_index"
}'

# {
#     "code": 0,
#     "data": {}
# }

限制

  • 仅支持非主键的标量字段使用位图索引。

  • 该字段的数据类型必须是以下之一:

    • BOOL,INT8,INT16,INT32,INT64,VARCHAR

    • ARRAY (元素必须是以下类型之一:BOOL 、INT8 、INT16 、INT32 、INT64 、VARCHAR )

  • 位图索引不支持以下数据类型:

    • FLOAT,DOUBLE :浮点类型与位图索引的二进制特性不兼容。

    • JSON:JSON 数据类型具有复杂的结构,无法通过位图索引进行高效表示。

  • 位图索引不适用于高基数字段(即具有大量不同值的字段)。

    • 作为一般准则,当字段的基数小于 500 时,位图索引最为有效。

    • 当基数超过此阈值时,位图索引的性能优势会减弱,且存储开销会变得很大。

    • 对于高Cardinal数字段,请根据您的具体用例和查询要求,考虑使用其他索引技术,例如倒排索引。

翻译自DeepL

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

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

免费试用 Zilliz Cloud
反馈

此页对您是否有帮助?