ベクトル検索の概要 - Amazon MemoryDB

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

ベクトル検索の概要

ベクトル検索は、インデックスの作成、メンテナンス、使用を基盤として構築されています。各ベクトル検索オペレーションは単一のインデックスを指定し、そのオペレーションはそのインデックスに限定されます。すなわち、1 つのインデックスに対するオペレーションは、他のインデックスに対するオペレーションの影響を受けません。インデックスの作成および破棄のオペレーションを除き、任意のインデックスに対して任意の数のオペレーションをいつでも発行できます。これは、クラスターレベルでは、複数のインデックスに対する複数のオペレーションが同時に進行する可能性があることを意味します。

個々のインデックスは、一意の名前空間に存在する名前付きオブジェクトであり、キー、関数などの他の Redis OSS 名前空間とは別のものです。各インデックスは、列と行の 2 つの次元で構造化されているという点で、概念的には従来のデータベーステーブルと似ています。テーブルの各行は、Redis OSS キーに対応します。インデックス内の各列は、そのキーのメンバーまたは部分に対応します。このドキュメント内では、キー、行、レコードという用語は同一のものであり、相互互換的に使用されます。同様に、列、フィールド、パス、メンバーという用語は本質的に同一のものであり、これらも相互互換的に使用されます。

インデックス付きデータを追加、削除、変更するための特別なコマンドはありません。むしろ、インデックス内のキーを変更する既存の HASH または JSON コマンドが、インデックスも自動的に更新します。

インデックスと Redis OSS キースペース

インデックスは、Redis OSS キースペースのサブセットにわたって構築および維持されます。複数のインデックスは、Redis OSS キースペースの不結合または重複するサブセットを無制限に選択できます。各インデックスのキースペースは、インデックスの作成時に提供されるキープレフィックスのリストによって定義されます。プレフィックスのリストはオプションであり、省略すると、Redis OSS キースペース全体がそのインデックスに含まれます。また、インデックスは、型が一致するキーのみをカバーするという点で型指定されます。現在、JSON インデックスと HASH インデックスのみがサポートされています。HASH インデックスは、プレフィックスリストによってカバーされる HASH キーのインデックスのみを作成し、同様に、JSON インデックスは、プレフィックスリストによってカバーされる JSON キーのインデックスのみを作成します。インデックスのキースペースプレフィックスリスト内のキーのうち、指定されたタイプを持たないキーは無視され、検索オペレーションに影響を及ぼしません。

HASH または JSON コマンドがインデックスのキースペース内にあるキーを変更すると、そのインデックスが更新されます。このプロセスには、各インデックスについて宣言されたフィールドを抽出し、新しい値でインデックスを更新することが含まれます。更新プロセスはバックグラウンドスレッドで実行されます。これは、インデックスが最終的にキースペースの内容と一致することを意味します。そのため、キーの挿入または更新は、すぐに検索結果に表示されません。システム負荷および/またはデータのミューテーションが多い期間中は、表示できるようになるまでの遅延が長くなる可能性があります。

インデックスの作成は複数のステップからなるプロセスです。最初のステップは、インデックスを定義する FT.CREATE コマンドを実行することです。作成が正常に実行されると、2 番目のステップであるバックフィルが自動的に開始されます。バックフィルプロセスはバックグラウンドスレッドで実行され、Redis OSS キースペースをスキャンして、新しいインデックスのプレフィックスリスト内にあるキーを探します。見つかった各キーはインデックスに追加されます。最終的にはキースペース全体がスキャンされて、インデックス作成プロセスが完了します。バックフィルプロセスの実行中は、インデックス付きキーのミューテーションが許可され、制限はなく、すべてのキーのインデックスが適切に作成されるまではインデックスバックフィルプロセスが完了しないことに留意してください。インデックスのバックフィル中に試行されるクエリオペレーションは許可されず、エラーで終了します。バックフィルプロセスの完了は、そのインデックスについての FT.INFO コマンドの出力 (「backfill_status」) から判断できます。

インデックスフィールドの型

インデックスの各フィールド (列) には、インデックスの作成時に宣言される特定の型と、キー内の場所が含まれます。HASH キーの場合、その場所は HASH 内のフィールド名です。JSON キーの場合、その場所は JSON パスの説明です。キーが変更されると、宣言されたフィールドに関連付けられたデータが抽出され、宣言された型に変換されてインデックスに格納されます。データが欠落している場合、または宣言された型に正常に変換できない場合、そのフィールドはインデックスから省略されます。次で説明するように、フィールドには 4 つのタイプがあります:

  • 数値フィールドには 1 つの数値が含まれます。JSON フィールドの場合、JSON 数値の数値規則に従う必要があります。HASH の場合、フィールドには、固定小数点数または浮動小数点数の標準形式で記述された数値の ASCII テキストが含まれることが想定されます。キー内の表現にかかわらず、このフィールドはインデックス内に格納するために 64 ビットの浮動小数点数に変換されます。数値フィールドは範囲検索演算子とともに使用できます。基になる数値は精度制限のある浮動小数点で格納されるため、浮動小数点数の数値比較に関する通常のルールが適用されます。

  • タグフィールドには、単一の UTF-8 文字列としてコード化された 0 個以上のタグ値が含まれます。文字列は、先頭と末尾の空白が削除された区切り文字 (デフォルトはカンマだが、上書きが可能) を使用してタグ値に解析されます。単一のタグフィールドには、任意の数のタグ値を含めることができます。タグフィールドを使用すると、大文字と小文字を区別する比較または大文字と小文字を区別しない比較で、タグ値の同等性についてクエリをフィルタリングできます。

  • テキストフィールドには、UTF-8 に準拠している必要のないバイトの BLOB が含まれています。テキストフィールドを使用すると、アプリケーションにとって意味のある値でクエリ結果を装飾できます。例えば、URL やドキュメントのコンテンツなどです。

  • ベクトルフィールドには、埋め込みとも呼ばれる数値のベクトルが含まれます。ベクトルフィールドは、指定されたアルゴリズムと距離メトリクスを使用した固定サイズのベクトルの K 最近傍検索 (KNN) をサポートします。HASH インデックスの場合、フィールドにはバイナリ形式 (リトルエンディアンIEEE 754) でエンコードされたベクトル全体が含まれている必要があります。JSON キーの場合、パスは数字が入力されている正しいサイズの配列を参照する必要があります。なお、JSON 配列をベクトルフィールドとして使用すると、JSON キー内の配列の内部表現が、選択したアルゴリズムに必要な形式に変換され、メモリ消費量と精度が削減されます。JSON コマンドを使用した後続の読み取りオペレーションでは、精度の値が小さくなります。

ベクトルインデックスアルゴリズム

2 つのベクトルインデックスアルゴリズムが提供されています。

  • Flat – Flat アルゴリズムは、インデックス内の各ベクトルの総当たり線形処理であり、距離計算の精度の範囲内で正確な答えを生成します。インデックスの線形処理のため、インデックスが大きい場合、このアルゴリズムの実行時間が非常に長くなる可能性があります。

  • HNSW (階層ナビゲーション可能なスモールワールド) — HNSW アルゴリズムは、実行時間を大幅に短縮する代わりに正しい回答を近似する代替手段です。このアルゴリズムは、MEF_CONSTRUCTIONEF_RUNTIME の 3 つのパラメータによって制御されます。最初の 2 つのパラメータはインデックスの作成時に指定され、変更できません。EF_RUNTIME パラメータにはインデックスの作成時に指定されるデフォルト値が含まれていますが、その後の個々のクエリオペレーションで上書きできます。これらの 3 つのパラメータは相互に影響し合って、取り込みおよびクエリオペレーション中のメモリと CPU 消費のバランスを取るだけでなく、正確な KNN 検索の近似値の質 (再現率と呼ばれます) を制御します。

両方のベクトル検索アルゴリズム (Flat および HNSW) は、オプションの INITIAL_CAP パラメータをサポートしています。このパラメータを指定すると、インデックス用にメモリが事前に割り当てられるため、メモリ管理のオーバーヘッドが削減され、ベクトルの取り込み速度が向上します。

HNSW などのベクトル検索アルゴリズムは、以前に挿入されたベクトルの削除または上書きを効率的に処理できない場合があります。これらのオペレーションを使用すると、インデックスメモリが過剰に消費されたり、再現の質が低下したりする可能性があります。インデックスの再作成は、最適なメモリ使用量および/または再現を復元するための 1 つの方法です。

ベクトル検索のクエリ式

FT.SEARCH および FT.AGGREGATE コマンドにはクエリ式が必要です。この式は、1 つ以上の演算子で構成される単一の文字列パラメータです。各演算子はインデックス内の 1 つのフィールドを使用して、インデックス内のキーのサブセットを識別します。ブール結合子や括弧を使用して複数の演算子を結合し、収集されたキーのセット (または結果セット) をさらに拡張または制限できます。

ワイルドカード

ワイルドカード演算子であるアスタリスク (「*」) は、インデックス内のすべてのキーと一致します。

数値範囲

数値範囲演算子の構文は次のとおりです:

<range-search> ::= '@' <numeric-field-name> ':' '[' <bound> <bound> ']' <bound> ::= <number> | '(' <number> <number> ::= <integer> | <fixed-point> | <floating-point> | 'Inf' | '-Inf' | '+Inf'

<numeric-field-name> は、 型の宣言フィールドである必要がありますNUMERIC。デフォルトでは、境界は包括的ですが、先頭の開き括弧 [「(」] を使用して境界を排他的にすることができます。範囲検索は、Inf+Inf、または -Inf を使用して単一のリレーショナル比較 (<、<=、>、>=) に変換できます。指定された数値形式 (整数、固定小数点、浮動小数点、無限大) にかかわらず、数値は比較を実行するために 64 ビットの浮動小数点に変換され、それに応じて精度が低下します。

@numeric-field:[0 10] // 0 <= <value> <= 10 @numeric-field:[(0 10] // 0 < <value> <= 10 @numeric-field:[0 (10] // 0 <= <value> < 10 @numeric-field:[(0 (10] // 0 < <value> < 10 @numeric-field:[1.5 (Inf] // 1.5 <= value

タグ比較

タグ比較演算子の構文は次のとおりです:

<tag-search> ::= '@' <tag-field-name> ':' '{' <tag> [ '|' <tag> ]* '}'

演算子のタグのいずれかがレコードのタグフィールドのタグのいずれかに一致する場合、そのレコードは結果セットに含まれます。<tag-field-name> によって設計されるフィールドは、型 TAG で宣言されたインデックスのフィールドである必要があります。タグ比較の例は次のとおりです:

@tag-field:{ atag } @tag-field: { tag1 | tag2 }

ブール値の組み合わせ

数値演算子またはタグ演算子の結果セットは、次のブール論理を使用して組み合わせることができます: and/or。括弧を使用すると、演算子をグループ化したり、評価順序を変更したりできます。ブール論理演算子の構文は次のとおりです:

<expression> ::= <phrase> | <phrase> '|' <expression> | '(' <expression> ')' <phrase> ::= <term> | <term> <phrase> <term> ::= <range-search> | <tag-search> | '*'

語句に結合された複数の用語は「and」で結合されます。パイプ (「|」) で結合された複数の語句は「or」で結合されます。

ベクトルインデックスは、最近傍と範囲の 2 つの異なる検索方法をサポートします。最近傍検索では、指定された (参照) ベクトルに最も近いインデックス内のベクトルの数 K が検索されます。これは、「K」に最も近い近傍の KNN と呼ぶものです。KNN 検索の構文は次のとおりです。

<vector-knn-search> ::= <expression> '=>[KNN' <k> '@' <vector-field-name> '$' <parameter-name> <modifiers> ']' <modifiers> ::= [ 'EF_RUNTIME' <integer> ] [ 'AS' <distance-field-name>]

ベクトル KNN 検索は、 を満たすベクトルにのみ適用されます。<expression>このベクトルは、ワイルドカード、範囲検索、タグ検索、および/またはそれらのブール値の組み合わせなど、上記で定義された演算子の任意の組み合わせにすることができます。

  • <k> は、返される最近傍ベクトルの数を指定する整数です。

  • <vector-field-name> は、型 VECTOR の宣言されたフィールドを指定する必要があります。

  • <parameter-name> フィールドは、FT.SEARCH または FT.AGGREGATE コマンドの PARAM テーブルのエントリの 1 つを指定します。このパラメータは、距離計算の参照ベクトル値です。ベクトルの値は、リトルエンディアン IEEE 754 バイナリ形式の PARAM の値にエンコードされます (HASH ベクトルフィールドの場合と同じようにエンコードされます)。

  • 型が HNSW であるベクトルインデックスの場合、オプションの EF_RUNTIME 句を使用して、インデックスの作成時に設定された EF_RUNTIME パラメータのデフォルト値を上書きできます。

  • オプションの <distance-field-name> は、参照ベクトルと見つかったキーの間の計算された距離を含む結果セットのフィールド名を提供します。

範囲検索では、指定した距離 (半径) 内のすべてのベクトルが参照ベクトルから検索されます。範囲検索の構文は次のとおりです。

<vector-range-search> ::= ‘@’ <vector-field-name> ‘:’ ‘[’ ‘VECTOR_RANGE’ ( <radius> | ‘$’ <radius-parameter> ) $<reference-vector-parameter> ‘]’ [ ‘=’ ‘>’ ‘{’ <modifiers> ‘}’ ] <modifiers> ::= <modifier> | <modifiers>, <modifier> <modifer> ::= [ ‘$yield_distance_as’ ‘:’ <distance-field-name> ] [ ‘$epsilon’ ‘:’ <epsilon-value> ]

コードの説明は以下のとおりです。

  • <vector-field-name>は、検索するベクトルフィールドの名前です。

  • <radius> or $<radius-parameter> は検索の数値距離制限です。

  • $<reference-vector-parameter> は、参照ベクトルを含むパラメータの名前です。ベクトルの値は、リトルエンディアン IEEE 754 バイナリ形式で PARAM 値にエンコードされます (HASH ベクトルフィールドの場合と同じエンコード)。

  • オプション<distance-field-name>では、結果セットのフィールド名を指定して、参照ベクトルと各キーの間の計算された距離を含めます。

  • オプションは検索オペレーションの境界<epsilon-value> を制御し、距離内のベクトル<radius> * (1.0 + <epsilon-value>) は候補結果を探してトラバースされます。デフォルトは .01 です。

INFO コマンド

ベクトル検索は、Redis OSS INFO コマンドを統計とカウンターの追加セクションで強化します。セクション SEARCH を取得するリクエストは、次のすべてのセクションを取得します:

search_memory セクション

名前 説明
search_used_memory_bytes すべての検索データ構造で消費されるメモリのバイト数
search_used_memory_human 上記の人間が読めるバージョン

search_index_stats セクション

名前 説明
search_number_of_indexes 作成されたインデックスの数
search_num_fulltext_indexes すべてのインデックス内の非ベクトルフィールドの数
search_num_vector_indexes すべてのインデックス内のベクトルフィールドの数
search_num_hash_indexes HASH 型キーのインデックスの数
search_num_json_indexes JSON 型キーのインデックスの数
search_total_indexed_keys すべてのインデックス内のキーの総数
search_total_indexed_vectors すべてのインデックス内のベクトルの総数
search_total_indexed_hash_keys すべてのインデックス内の型が HASH であるキーの総数
search_total_indexed_json_keys すべてのインデックス内の型が JSON であるキーの総数
search_total_index_size すべてのインデックスによって使用されるバイト数
search_total_fulltext_index_size 非ベクトルインデックス構造によって使用されるバイト数
search_total_vector_index_size ベクトルインデックス構造によって使用されるバイト数
search_max_index_lag_ms 最後の取り込みバッチ更新時の取り込みの遅延

search_ingestion セクション

名前 説明
search_background_indexing_status 取り込みのステータス。NO_ACTIVITY はアイドル状態であることを意味します。他の値は、取り込み中のキーがあることを示します。
search_ingestion_paused 再起動中を除き、これは常に「no」である必要があります。

search_backfill セクション

注記

このセクションに記載されているフィールドの一部は、操作しているときにバックフィルが進行中の場合にのみ表示されます。

名前 説明
search_num_active_backfills 現在のバックフィルアクティビティの数
search_backfills_paused メモリ不足の場合を除いて、これは常に「no」である必要があります。
search_current_backfill_progress_percentage 現在のバックフィルの完了率 (0~100)

search_query セクション

名前 説明
search_num_active_queries 現在進行中の FT.SEARCH および FT.AGGREGATE コマンドの数

ベクトル検索のセキュリティ

コマンドアクセスとデータアクセスの両方のための Redis OSS ACL (アクセスコントロールリスト) セキュリティメカニズムが、検索機能を制御するために拡張されています。個々の検索コマンドの ACL コントロールは完全にサポートされています。新しい ACL カテゴリ @search が提供され、既存のカテゴリの多く (@fast@read@write など) が新しいコマンドを含むように更新されます。検索コマンドはキーデータを変更しません。これは、書き込みアクセス用の既存の ACL 機構が保持されることを意味します。HASH および JSON オペレーションのアクセスルールは、インデックスが存在することで変更されることはありません。これらのコマンドには、通常のキーレベルのアクセスコントロールが引き続き適用されます。

インデックスを含む検索コマンドも、Redis OSS ACL を介してアクセスが制御されます。アクセスチェックは、キーごとのレベルではなく、インデックス全体のレベルで実行されます。これは、そのインデックスのキースペースプレフィックスリストに含まれているすべての可能なキーにアクセスするための許可がユーザーに付与されている場合にのみ、インデックスに対するアクセスがユーザーに付与されることを意味します。つまり、インデックスの実際の内容はアクセスを制御しません。むしろ、これは、セキュリティチェックのために使用されるプレフィックスリストによって定義されるインデックスの理論的な内容です。キーに対する読み取りおよび/または書き込みアクセスがユーザーに付与されているにもかかわらず、そのキーを含むインデックスにアクセスできない状況が容易に発生する可能性があります。インデックスの作成または使用にはキースペースに対する読み取りアクセスのみが必要であり、書き込みアクセスの有無は考慮されないことに留意してください。

MemoryDB での ACL の使用の詳細については、「アクセスコントロールリスト (ACL) によるユーザー認証」を参照してください。