• 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 필드에 대해 다음 필터 패턴의 처리 속도를 높여줍니다. 앵커가 지정된 접두사, 접미사 및 중첩 리터럴은 인덱스에서 정확히 일치하는 결과를 반환하며, 일반적인 및 정규식 패턴은 Milvus가 원본 값과 대조하여 검증하는 후보를 생성합니다. LIKE

  • 접두사 일치

    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배 더 빠릅니다.

시작하기
피드백

이 페이지가 도움이 되었나요?