• 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() メソッドを使用して、コレクションから既存のインデックスを削除します。

  • v2.6.3以前では、スカラーインデックスを削除する前にコレクションを解放する必要があります。

  • v2.6.4以降では、スカラーインデックスが不要になった時点で、コレクションを解放することなく直接削除できます。

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 を小さくすると、インデックスサイズが大きくなる代わりに locate のレイテンシが改善されます。クエリが主にカウントのみの場合、この値を大きくしてインデックスサイズを縮小してください。

翻訳DeepL

マネージド Milvus を無料で試す

Zilliz Cloud は手間いらず、Milvus を基盤に 10 倍高速です。

始める
フィードバック

このページは役に立ちましたか ?