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

TRIE

Milvus 中的TRIE 索引将VARCHAR 字段的值组织成一个前缀树(Trie)。字符串中的每个字符都对应树中的一条边,且相同的前缀仅存储一次。这种结构使得精确字符串查找和前缀匹配速度很快,无需扫描字段中的每个值。

如果您经常执行以下类型的查询,请使用TRIE 索引:

  • 对字符串值进行精确相等比较,例如category == "books"

  • 前缀过滤,例如name LIKE "abc%"

支持的数据类型

TRIE 仅在VARCHAR 字段上受支持。若要对JSON 字段中的字符串值进行索引,请将路径转换为VARCHAR ,并改用NGRAM索引。

工作原理

Milvus分两阶段实现TRIE :

  1. 构建索引

    • 在数据摄入过程中,Milvus 会读取索引字段的每个值。

    • 这些值会被插入到一个三叉树中:字符存储在边上,每个终端节点记录共享该字符串的实体 ID。

    • 生成的树结构将作为索引持久化存储。

  2. 加速查询

    • 对于相等性查询,Milvus 会逐个字符遍历树,找到与精确值对应的节点,并返回其实体 ID。

    • 对于前缀查询,Milvus 会逐个字符遍历树,找到与前缀完全匹配的节点,并返回该节点的实体 ID。

    • 匹配的实体 ID 会被传递给查询执行器,以进行最终结果的组装。

对于相等性和前缀过滤器,查找成本与字符串长度成正比,而不是与实体数量成正比,这使得这些查询在大型Collection中仍然很快。

创建 TRIE 索引

您可以在VARCHAR 字段上创建TRIE 索引。无需任何额外参数。

以下示例演示了如何在VARCHAR 字段上创建TRIE 索引:

from pymilvus import MilvusClient

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

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

# Prepare index parameters
index_params = client.prepare_index_params()

# Add TRIE index on the "category" field
index_params.add_index(
    field_name="category",     # Target VARCHAR field
    index_type="TRIE",         # Index type is TRIE
    index_name="category_trie" # Optional, name your index
)

# Create the index on the collection
client.create_index(
    collection_name="product_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.Collections;

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

client.createIndex(CreateIndexReq.builder()
        .collectionName("product_catalog")
        .indexParams(Collections.singletonList(IndexParam.builder()
                .fieldName("category")
                .indexType(IndexParam.IndexType.TRIE)
                .indexName("category_trie")
                .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("product_catalog", "category", index.NewTrieIndex()).WithIndexName("category_trie"))

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("product_catalog")
            .index_param(
                IndexParam::new()
                    .field_name("category")
                    .index_type(IndexType::Trie)
                    .index_name("category_trie"),
            )
            .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("product_catalog")
        .AddIndex(milvus::IndexDesc("category", "category_trie", milvus::IndexType::TRIE)));

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: "product_catalog",
    field_name: "category",
    index_type: "TRIE",
    index_name: "category_trie",
});
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": "product_catalog",
    "indexParams": [
        {
            "fieldName": "category",
            "indexName": "category_trie",
            "indexType": "TRIE"
        }
    ]
}'

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

由 TRIE 加速的查询

TRIE 索引可加速VARCHAR 字段上的以下过滤模式:

  • 相等

    filter = 'category == "books"'
    
  • 成员关系

    filter = 'category in ["books", "electronics"]'
    
  • 前缀匹配

    filter = 'category LIKE "elec%"'
    
  • 范围

    filter = 'category >= "a" and category < "m"'
    

    范围评估可能会遍历多个已索引的字符串。

后缀、子字符串和通配符LIKE 模式也可以针对索引字符串进行评估,但可能需要遍历许多不同的值。如果您的工作负载主要涉及子字符串或正则表达式匹配,请考虑改用FMINDEX或NGRAM索引。

删除索引

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

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

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

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

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("product_catalog")
            .index_name("category_trie")
            .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("product_catalog")
        .WithIndexName("category_trie"));

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: "product_catalog",
    index_name: "category_trie",
});
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": "product_catalog",
    "indexName": "category_trie"
}'

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

使用说明

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

  • 参数:无需任何索引参数。

  • 模式匹配:对于相等性和前缀过滤器,TRIE 的处理速度最快。支持范围过滤器,但可能会遍历多个已索引的字符串。后缀、子字符串以及通配符LIKE 模式均可进行评估,但可能需要扫描大量已索引的字符串。

最佳实践

  • 当您的过滤器主要涉及精确查找或前缀匹配时,请使用TRIE 。

  • 如果您的工作负载依赖于子字符串(LIKE "%abc%" )或正则表达式过滤器,请改用FMINDEX进行精确锚定匹配,或使用NGRAM来缩小候选范围。

翻译自DeepL

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

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

免费试用 Zilliz Cloud
反馈

此页对您是否有帮助?