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

FMINDEX

Milvus 中的FMINDEX 索引是针对VARCHAR 字段的精确字节级子字符串索引。它可响应带有前缀、中缀或后缀匹配的锚定LIKE 查询,并返回精确匹配结果,无需对候选结果进行重新检查。

FMINDEX 如果您经常运行子字符串过滤操作,例如:

  • title LIKE "vector%" (前缀)

  • title LIKE "%database" (后缀)

  • title LIKE "%vector database%" (中缀/子字符串)

与先缩小候选集再进行重新检查的NGRAM 不同,FMINDEX 可直接从索引中解析锚定前缀、后缀和插入模式。

支持的数据类型

FMINDEX 仅在VARCHAR 字段上受支持。它不支持JSON 字段,也不支持转换为VARCHAR 的JSON 路径。

工作原理

FMINDEX 是一种全文 FM 索引,其结构由拼接后的字段值的 Burrows-Wheeler 变换(BWT)构建而成,并包含一个采样后缀数组和用于秩查询的小波树。 这种布局支持向后搜索:给定一个模式,Milvus 会从该模式的最后一个字符向第一个字符遍历,以查找文本中包含该模式的实体的精确范围。

在查询时,Milvus 使用该索引来:

  1. 定位从LIKE 模式中提取的锚定字面量所匹配的实体。

  2. 返回前缀、后缀和插缀字面量的精确实体 ID,而无需重新检查原始值。

对于包含多个非相邻字面量(通用LIKE )或复杂正则表达式的模式,FMINDEX 可能会生成候选结果,随后Milvus会将其与原始值进行核对。

创建 FMINDEX 索引

您可以在VARCHAR 字段上创建FMINDEX 索引。这两个构建参数均为可选;若未设置,则采用服务器默认值。

参数描述允许的值默认值
fm_sa_sample_rate后缀数组采样率。在索引大小与定位延迟之间进行权衡;不影响仅计数查询。4 到 256 之间的整数8
fm_block_bytes按字节计的排名目录块粒度。较大的块可缩小驻留目录的大小。8、16、32、64 或 12864

下面的示例演示了如何在VARCHAR 字段上创建FMINDEX 索引:

from pymilvus import MilvusClient

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

# Assume you have defined a VARCHAR field named "text" in your collection schema

# Prepare index parameters
index_params = client.prepare_index_params()

# Add FMINDEX index on the "text" field
index_params.add_index(
    field_name="text",           # Target VARCHAR field
    index_type="FMINDEX",        # Index type is FMINDEX
    index_name="fmindex_index",  # Custom name for the index
    fm_sa_sample_rate=8,         # Optional: suffix-array sampling rate (4-256, default 8)
    fm_block_bytes=64            # Optional: block granularity in bytes (8/16/32/64/128, default 64)
)

# Create the index on the collection
client.create_index(
    collection_name="log_catalog",
    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.Arrays;
import java.util.HashMap;
import java.util.Map;

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

Map<String, Object> params = new HashMap<>();
params.put("fm_sa_sample_rate", "8");
params.put("fm_block_bytes", "64");

client.createIndex(CreateIndexReq.builder()
        .collectionName("log_catalog")
        .indexParams(Arrays.asList(
                IndexParam.builder().fieldName("text").indexType(IndexParam.IndexType.FMINDEX)
                        .indexName("fmindex_index")
                        .extraParams(params)
                        .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())
}

idx := index.NewFMIndex().WithSaSampleRate(8).WithBlockBytes(64)

_, err = cli.CreateIndex(ctx, milvusclient.NewCreateIndexOption("log_catalog", "text", idx).WithIndexName("fmindex_index"))

if err != nil {
    log.Fatal("failed to create index: ", err.Error())
}
#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;
}

milvus::IndexDesc fmindex_index("text", "fmindex_index", milvus::IndexType::FMINDEX);
fmindex_index.AddExtraParam("fm_sa_sample_rate", "8");
fmindex_index.AddExtraParam("fm_block_bytes", "64");

status = client->CreateIndex(milvus::CreateIndexRequest().WithCollectionName("log_catalog")
        .AddIndex(fmindex_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.createIndex({
    collection_name: "log_catalog",
    field_name: "text",
    index_type: "FMINDEX",
    index_name: "fmindex_index",
    params: { fm_sa_sample_rate: 8, fm_block_bytes: 64 },
});
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": "log_catalog",
    "indexParams": [
        {
            "fieldName": "text",
            "indexName": "fmindex_index",
            "params": {
                "index_type": "FMINDEX",
                "fm_sa_sample_rate": 8,
                "fm_block_bytes": 64
            }
        }
    ]
}'

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

由 FMINDEX 加速的查询

FMINDEX 可加速对VARCHAR 字段的以下过滤模式:锚定前缀、后缀和插缀字面量可从索引中精确解析;一般的LIKE 和正则表达式模式会生成候选结果,Milvus会将其与原始值进行验证。

  • 前缀匹配

    filter = 'text LIKE "vector%"'
    
  • 后缀匹配

    filter = 'text LIKE "%database"'
    
  • 中缀/子字符串匹配

    filter = 'text LIKE "%vector database%"'
    
  • 通用 LIKE(候选结果)

    filter = 'text LIKE "a%b_c"'
    
  • 正则表达式 (候选结果)

    filter = 'text =~ "error.*timeout"'
    

有关过滤表达式语法的更多信息,请参阅“模式匹配”。

删除索引

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

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

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

client.drop_index(
    collection_name="log_catalog",   # Name of the collection
    index_name="fmindex_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("log_catalog")
        .indexName("fmindex_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("log_catalog", "fmindex_index"))

if err != nil {
    log.Fatal("failed to drop index: ", err.Error())
}
#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("log_catalog")
        .WithIndexName("fmindex_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: "log_catalog",
    index_name: "fmindex_index",
});
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": "log_catalog",
    "indexName": "fmindex_index"
}'

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

使用说明

  • 字段类型:仅适用于VARCHAR 字段。有关数据类型的更多信息,请参阅“字符串字段”。

  • 版本兼容性: FMINDEX 需要标量索引引擎版本 5 或更高。

  • SDK 可用性:Rust v2 SDK 目前尚未包含FMINDEX 索引类型。

  • 精确匹配:带锚点的LIKE 前缀、后缀和中缀字面量将返回精确匹配结果,且无需对候选结果进行重新验证。

  • 候选项:通用LIKE 和正则表达式模式可能会生成候选项,Milvus 会将这些候选项与原始值进行验证。当模式提供的过滤效果有限,或者解析成本过高时,Milvus 可能会转而扫描字段。

  • 不可变性: fm_sa_sample_rate 和fm_block_bytes 无法就地修改——需重建索引才能调整它们。

最佳实践

  • 对于长VARCHAR 字段,请使用FMINDEX 进行精确子字符串搜索,尤其是在NGRAM 候选结果重新验证成本较高时。

  • 对于大多数工作负载,请将fm_block_bytes 保持在默认值 64;当内存紧张时,可将其增大以缩小驻留目录。

  • 降低fm_sa_sample_rate 值可改善定位延迟,但会以索引变大为代价;当查询主要为计数查询时,提高该值可减小索引大小。

翻译自DeepL

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

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

免费试用 Zilliz Cloud
反馈

此页对您是否有帮助?