このドキュメントでは、保存されたエンベディングを使用してインデックスを生成し、エンベディングをクエリする方法について説明します。エンベディングの保存の詳細については、ベクトル エンベディングを保存するをご覧ください。
AlloyDB では、ScaNN、IVF、IVFFlat、HNSW インデックスを作成できます。
始める前に
インデックスの作成を開始する前に、以下の前提条件を整える必要があります。
AlloyDB データベースのテーブルにエンベディング ベクトルが追加されている。
Google が AlloyDB 用に拡張した
pgvectorに基づくvector拡張機能のバージョン0.5.0以降がインストールされている。CREATE EXTENSION IF NOT EXISTS vector;ScaNNインデックスを作成するには、vector拡張機能に加えてalloydb_scann拡張機能をインストールしてください。CREATE EXTENSION IF NOT EXISTS alloydb_scann;
インデックスの作成
データベース内のテーブルには、次のいずれかのインデックス タイプを作成できます。
ScaNN インデックスを作成する
AlloyDB の alloydb_scann は、
Google が開発した PostgreSQL 拡張機能で、
[ScaNN
アルゴリズム](https://github.com/google-research/google-research/blob/master/scann/docs/algorithms.md)を活用した、効率性の高い最近傍検索インデックスを実装しています。
ScaNN インデックスは、近似最近傍検索用の
ツリーベースの量子化インデックスです。
HNSW と比較して、インデックス構築時間が速く、メモリ使用量が少なくなります。また、ワークロードによっては、
HNSW と比べてより高速な QPS を提供します。
AlloyDB データベース内のテーブルにエンベディング ベクトルを追加しておいてください。空のテーブルやパーティション分割テーブルに対して ScaNN インデックスを生成しようとすると、
問題が発生する可能性があります。発生するエラーの詳細については、
ScaNN インデックス エラーのトラブルシューティングをご覧ください。
2 レベルツリー ScaNN インデックス
保存されたベクトル エンベディングを含む列に、ScaNN アルゴリズムを使用した 2 レベルのツリー インデックスを適用するには、
次の DDL クエリを実行します。
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE);
次のように置き換えます。
INDEX_NAME: 作成するインデックスの名前。たとえば
my-scann-indexのように指定します。このインデックス名はデータベース全体で共有されます。各インデックス名は、
データベース内の各テーブルで一意となるようにしてください。
TABLE: インデックスを追加するテーブル。EMBEDDING_COLUMN:vectorデータを格納する列。
DISTANCE_FUNCTION: このインデックスで使用する距離関数。次のいずれかを選択します。
L2 距離:
l2ドット積:
dot_productコサイン距離:
cosine
NUM_LEAVES_VALUE: このインデックスに適用するパーティションの数。1~1,048,576 の任意の値に設定します。この値を決める方法について詳しくは、
ScaNNインデックスをチューニングするをご覧ください。
3 レベルのツリー ScaNN インデックス
保存されたベクトル エンベディングを含む列に、ScaNN アルゴリズムを使用した 3 レベルのツリー インデックスを作成するには、
次の DDL クエリを実行します。
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);
次のように置き換えます。
MAX_NUM_LEVELS: K 平均法クラスタリング ツリーの最大レベル数。2 レベルのツリーベースの量子化にはデフォルトの
1を設定し、3 レベルのツリーベースの量子化には
2を設定します。
インデックスを作成した後は、
作成したインデックスを利用した最近傍検索クエリを実行できます。詳しい手順は、[テキストを指定した
最近傍クエリの実行](#query)の説明をご覧ください。
インデックス パラメータは、QPS とリコールのバランスを適切にとるように
設定する必要があります。ScaNN インデックスのチューニングの詳細については、[ScaNN インデックスの
チューニングに関する記事](/alloydb/omni/kubernetes/15.7.0/docs/ai/tune-indexes)をご覧ください。
real[] データ型を使用している
(vector 型ではなく)エンベディング列に対してこのインデックスを作成する場合は、列を vector データ型にキャストしてください。
CREATE INDEX INDEX_NAME ON TABLE
USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);
DIMENSIONS は、エンベディング列の次元数に
置き換えてください。次元数を確認する方法について詳しくは、
[ベクトル関数](https://github.com/pgvector/pgvector?tab=readme-ov-file#vector-functions)にある vector_dims 関数を
ご覧ください。
インデックス作成の進行状況を確認するには、pg_stat_progress_create_index ビューを使用します。
SELECT * FROM pg_stat_progress_create_index;
phase 列には、インデックス作成の現在のステータスが表示されます。
インデックスが作成されると、building index: tree training フェーズが消えます。
目標の再現率と QPS のバランスを考慮してインデックスをチューニングするには、ScaNN インデックスをチューニングするをご覧ください。
インデックスを作成したテーブルを分析する
ScaNN インデックスの作成後、ANALYZE コマンドを実行してデータに関する統計情報を更新します。
ANALYZE TABLE;
クエリの実行
データベースにエンベディングを保存してインデックス化したら、
[pgvector のクエリ
機能](https://github.com/pgvector/pgvector#querying)を使用してクエリを開始できます。一括検索クエリは
alloydb_scann 拡張機能では実行できません。
エンベディング ベクトルに対して最も近いセマンティック近傍を見つけるには、
次のサンプルクエリを実行します。その際、インデックスの作成時に使用したのと
同じ距離関数を設定してください。
SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
LIMIT ROW_COUNT
次のように置き換えます。
TABLE: テキストと比較するエンベディングを含むテーブル。
INDEX_NAME: 使用するインデックスの名前。たとえば、
my-scann-indexのように指定します。EMBEDDING_COLUMN: 保存されているエンベディングを含む列。
DISTANCE_FUNCTION_QUERY: このクエリで使用する距離関数。インデックス作成時に使用した距離関数に応じて、
次の中から選択してください。
L2 距離:
<->内積:
<#>コサイン距離:
<=>
EMBEDDING: 保存されているセマンティック近傍の中で最も近いものを見つけるエンベディング ベクトル。
ROW_COUNT: 返される行数。最も適合する 1 件のみを取得したい場合は、
1を指定してください。
他のクエリの例について詳しくは、
クエリに関するページをご覧ください。
embedding() 関数を使用してテキストをベクトルに
変換することもできます。ベクトルを
pgvector の最近傍演算子 <->(L2 距離用)に適用すると、
意味的に最も類似したエンベディングを持つデータベース行を見つけることができます。
embedding() は real 配列を返すため、
pgvector でこれらの値を使用するには、embedding() の呼び出し結果を明示的に vector 型に
キャストする必要があります。
CREATE EXTENSION IF NOT EXISTS google_ml_integration;
CREATE EXTENSION IF NOT EXISTS vector;
SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN::vector
<-> embedding('MODEL_IDVERSION_TAG', 'TEXT')
LIMIT ROW_COUNT
次のように置き換えます。
MODEL_ID: クエリするモデルの ID。Vertex AI Model Garden を使用している場合は、モデル ID として
text-embedding-005を指定します。これらは、AlloyDB がテキスト エンベディングに使用できるクラウドベースのモデルです。詳細については、テキスト エンベディングをご覧ください。省略可:
VERSION_TAG: クエリするモデルのバージョンタグ。タグの前に@を付けます。Vertex AI で
text-embedding英語モデルのいずれかを使用している場合は、モデル バージョンに記載されているバージョンタグのいずれかを指定します(例:text-embedding-005)。バージョンタグは常に指定することを強くおすすめします。バージョンタグを指定しない場合、AlloyDB は常に最新のモデル バージョンを使用します。これにより、予期しない結果が生じる可能性があります。
TEXT: ベクトル エンベディングに変換するテキスト。