このドキュメントでは、保存されたエンベディングを使用してインデックスを生成し、エンベディングをクエリする方法について説明します。エンベディングの保存の詳細については、ベクトル エンベディングを保存するをご覧ください。
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 アルゴリズムによる非常に効率的な最近傍インデックスを実装しています。
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 クエリ機能を使用してクエリを開始できます。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: ベクトル エンベディングに変換するテキスト。