インデックスとクエリベクトルを作成する

このページでは、AlloyDB for PostgreSQL で保存されたエンベディングを使用してインデックスを生成し、ScaNNIVFIVFFlatHNSW インデックスを使用してエンベディングをクエリする方法について説明します。エンベディングの保存の詳細については、ベクトル エンベディングを保存するをご覧ください。

始める前に

インデックスの作成を開始する前に、次の前提条件を満たす必要があります。

  • AlloyDB データベースのテーブルにエンベディング ベクトルが追加されます

  • pgvector に基づく vector 拡張機能のバージョン 0.5.0 以降がインストールされており、Google が AlloyDB 用に拡張しています。

    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 関数をご覧ください。

インデックス登録の進行状況を確認するには、pg_stat_progress_create_index ビューを使用します。

SELECT * FROM pg_stat_progress_create_index;

phase 列には、インデックス作成の現在のステータスが表示されます。インデックスが作成されると、building index: tree training フェーズは消えます。

目標の再現率と QPS のバランスをとるようにインデックスをチューニングするには、ScaNN インデックスをチューニングするをご覧ください。

クエリの実行

エンベディングをデータベースに保存してインデックスを作成したら、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 VERSION '1.2';
  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-005 英語モデルのいずれかを使用している場合は、モデル バージョンに記載されているバージョンタグのいずれかを指定します。text-embedding-005

    バージョンタグを常に指定することを強くおすすめします。バージョンタグを指定しない場合、AlloyDB は常に最新のモデル バージョンを使用します。これにより、予期しない結果が生じる可能性があります。

  • TEXT: ベクトル エンベディングに変換するテキスト。

次のステップ