このページでは、AlloyDB for PostgreSQL で保存されたエンベディングを使用してインデックスを生成し、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 アルゴリズムによる非常に効率的な最近傍インデックスを実装しています。
ScaNN
インデックスは、近似最近傍検索用のツリーベースの量子化インデックスです。HNSW
と比較して、インデックスの構築時間が短く、メモリ使用量も小さくなります。また、ワークロードに応じて HNSW
よりも QPS が速くなります。
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~1048576 の任意の値に設定します。この値を決定する方法の詳細については、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
に設定します。
インデックスを作成すると、指定されたテキストで類似クエリを作成する手順に沿って、インデックスを使用する最近傍探索クエリを実行できます。
インデックス パラメータは、QPS とリコールのバランスを適切にとるように設定する必要があります。ScaNN
インデックスのチューニングの詳細については、ScaNN
インデックスをチューニングするをご覧ください。
このインデックスを、vector
ではなく real[]
データ型を使用するエンベディング列に作成するには、列を 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
は、エンベディング列のディメンション幅に置き換えます。ディメンションの確認方法については、ベクトル関数の vector_dims
関数をご覧ください。
一貫した検索エクスペリエンスを実現するには、ScaNN インデックスを作成するときに自動メンテナンスを有効にします。詳細については、ベクトル インデックスを維持するをご覧ください。この機能はプレビュー版でご利用いただけます。
インデックス作成の進行状況を確認するには、pg_stat_progress_create_index
ビューを使用します。
SELECT * FROM pg_stat_progress_create_index;
phase
列には、インデックス作成の現在のステータスが示されます。インデックスが作成されると、building index: tree training
フェーズが消えます。
目標の再現率と QPS のバランスを考慮してインデックスをチューニングするには、ScaNN
インデックスをチューニングするをご覧ください。
インデックスを作成したテーブルを分析する
ScaNN
インデックスを作成したら、ANALYZE
コマンドを実行してデータに関する統計情報を更新する必要があります。
ANALYZE TABLE;
インデックスを並行して構築する
AlloyDB は、データセットと、インデックスをすばやく構築するために選択したインデックスのタイプに応じて、複数の並列ワーカーを自動的に生成する場合があります。
並列インデックス構築は、3 レベルの ScaNN インデックスを作成する場合や、データセットが 1 億行を超える場合にトリガーされます。
AlloyDB は並列ワーカーの数を自動的に最適化しますが、max_parallel_maintenance_workers
、max_parallel_workers
、min_parallel_table_scan_size
PostgreSQL クエリ プランニング パラメータを使用して並列ワーカーをチューニングできます。
pgvector を使用してクエリを実行する
エンベディングをデータベースに保存してインデックスを作成した後は、pgvector
クエリ機能を使用してクエリを開始できます。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
に明示的にキャストする必要があります。
次のステップ
- ベクトル類似性検索を実行する
- ベクトルクエリのパフォーマンスを調整する
- ベクトル インデックス指標
- AlloyDB、pgvector、モデル エンドポイント管理を使用してスマート ショッピング アシスタントを構築する方法について学習する。