カラム型エンジンを使用してベクトル検索を高速化する

スケーラブルな最近傍(ScaNN)インデックスまたは階層ナビゲーション可能なスモール ワールド(HNSW)インデックスを使用する場合、AlloyDB for PostgreSQL カラム型エンジンを使用してベクトル検索を高速化できます。カラム型エンジンは、これらのベクトル インデックスの読み取り用に最適化されたインメモリ キャッシュとして機能します。

カラム型エンジンにインデックスをキャッシュすると、読み取り用に最適化されたインメモリ表現のインデックスからクエリが直接処理され、データベースがベクトル検索ワークロードで処理できる秒間クエリ数(QPS)が増加します。

HNSW は、PostgreSQL 17 以降を実行している AlloyDB クラスタのカラム型エンジンでのみ使用できます。カラム型エンジンを使用する ScaNN にはこのような制限はありません。

始める前に

  • google_columnar_engine.enabled データベース フラグと google_columnar_engine.enable_index_caching データベース フラグを on に設定して、カラム型エンジンとそのインデックス キャッシュ機能を有効にします。

    gcloud alloydb instances update INSTANCE_ID \
        --database-flags google_columnar_engine.enabled=on,google_columnar_engine.enable_index_caching=on \
        --region=REGION \
        --cluster=CLUSTER_ID \
        --project=PROJECT_ID

    次のように置き換えます。

    • INSTANCE_ID: カラム型エンジンを有効にするインスタンスの ID。
    • REGION: インスタンスが配置されているリージョン(us-central1 など)。
    • CLUSTER_ID: インスタンスが配置されているクラスタの ID。
    • PROJECT_ID: クラスタが配置されているプロジェクトの ID。

    フラグの設定の詳細については、データベース フラグを構成するをご覧ください。

  • データベースに ScaNN インデックスを作成するまたはHNSW インデックスを作成する

カラム型エンジンにインデックスを追加する

カラム型エンジンを有効にしたら、google_columnar_engine_add_index() SQL 関数を使用して、既存のインデックスをキャッシュに追加できます。

カラム型エンジンにインデックスを追加する手順は次のとおりです。

  1. コンソールで、[クラスタ] ページに移動します。 Google Cloud

    クラスタに移動

  2. クラスタの [概要] ページを表示するには、[リソース名] 列で AlloyDB クラスタの名前をクリックします。

  3. ナビゲーション パネルで [AlloyDB Studio] をクリックします。

  4. データベースの名前、ユーザー名、パスワードを使用して AlloyDB Studio にログインします。

  5. [エディタ 1] タブに、次のクエリを入力します。

    SELECT google_columnar_engine_add_index('INDEX_NAME');
    

    INDEX_NAME は、ベクトル インデックスの名前に置き換えます。

    1. [実行] をクリックします。

カラム型エンジンにインデックスを追加すると、このインデックスを使用するすべてのクエリがカラム型エンジンによって自動的に高速化されます。クエリで EXPLAIN (ANALYZE, COLUMNAR_ENGINE) プランを使用すると、ベクトルクエリがカラム型エンジンによって高速化されていることを確認できます。

キャッシュの使用状況を確認する

ベクトルクエリがカラム型エンジンによって高速化されていることを確認するには、クエリで EXPLAIN (ANALYZE, COLUMNAR_ENGINE) プランを使用します。

ScaNN 実行プランの例

次に、カラム型エンジンに追加された ScaNN インデックスを使用するクエリの実行プランの例を示します。

EXPLAIN (ANALYZE TRUE, SCANN TRUE, COSTS FALSE, TIMING FALSE, SUMMARY FALSE, VERBOSE FALSE, COLUMNAR_ENGINE TRUE)
SELECT * FROM t ORDER BY val <=> '[0.5,0.5,0.5,0.5]' LIMIT 100;

--This contains details about ScaNN's usage from the columnar engine. Example:
------------------------------------------------------------------------------------------------------
 Index Scan using scann_idx on t t_1 (actual rows=100 loops=1)
      Order By: (val <=> '[0.5,0.5,0.5,0.5]'::vector)
      Limit: 100
      ScaNN Info: (... columnar engine nodes hit=6...)
      Columnar Engine ScaNN Info: (index found=true)
(5 rows)

出力に columnar engine nodes hitColumnar Engine ScaNN Info: (index found=true) が含まれている場合は、クエリにカラム型エンジンが使用されています。

HNSW 実行プランの例

実行プランには、カラム型エンジンから取得された要素の比率(elements_from_ce)やディスクから取得された要素の比率(elements_from_disk)などの指標を示す、それぞれのインデックスの [Columnar Engine HNSW Info] セクションが表示されます。

次に、カラム型エンジンに追加された HNSW インデックスを使用するクエリの実行プランの例を示します。

EXPLAIN (ANALYZE, COLUMNAR_ENGINE) SELECT * FROM documents ORDER BY embedding <=> '[0.1, 0.2, 0.3, 0.4, 0.5]'::vector LIMIT 5;

--This contains details about HNSW's usage from the columnar engine. Example:
------------------------------------------------------------------------------------------------------
 Limit (actual rows=5 loops=1)
   ->  Index Scan using hnsw_idx on documents (actual rows=5 loops=1)
         Order By: (embedding '[0.1, 0.2, 0.3, 0.4, 0.5]'::vector)
         Columnar Engine HNSW Info: (index found=true elements_from_ce=385 elements_from_disk=0)
         Columnar Check: table is not in the columnar store
(5 rows)

レスポンスは、すべての要素がカラム型エンジンから取得され(elements_from_ce=385)、ディスクから取得された要素がない(elements_from_disk=0)ため、インデックスがカラム型エンジンによって高速化されていることを示しています。

INSERTUPDATEDELETE ステートメントなどのデータ変更によってキャッシュ エントリが無効になると、カラム型エンジンはハイブリッド アプローチを使用して精度とパフォーマンスを維持します。有効なキャッシュ ベクトルをメモリから直接読み取り、変更または新しいベクトルのみをディスクから取得します。

大量のデータを変更すると、キャッシュが更新されるまで、elements_from_disk が一時的に増加し、パフォーマンスが低下する可能性があります。

キャッシュされたインデックスを管理する

キャッシュされたインデックスのライフサイクルを管理する手順は次のとおりです。

  1. コンソールで、[クラスタ] ページに移動します。 Google Cloud

    クラスタに移動

  2. クラスタの [概要] ページを表示するには、[リソース名] 列で AlloyDB クラスタの名前をクリックします。

  3. ナビゲーション パネルで [AlloyDB Studio] をクリックします。

  4. データベースの名前、ユーザー名、パスワードを使用して AlloyDB Studio にログインします。

  5. [エディタ 1] タブに、選択したタスクの SQL コマンドを入力します。

    • キャッシュを手動で更新するには、次のコマンドを実行します。

      SELECT google_columnar_engine_refresh_index('INDEX_NAME');
      
    • インデックスのステータスを確認するには、次のコマンドを実行します。

      SELECT google_columnar_engine_verify('INDEX_NAME');
      
    • キャッシュからインデックスを削除するには、次のコマンドを実行します。

      SELECT google_columnar_engine_drop_index('INDEX_NAME');
      
    • アクティブなインデックスを表示するには、次のコマンドを実行します。

      SELECT * FROM g_columnar_indexes;
      
    • パーティション分割されたインデックスを表示するには、次のコマンドを実行します。

      SELECT * FROM g_columnar_index_partitions;
      

    INDEX_NAME は、インデックスの名前に置き換えます。

  6. [実行] をクリックします。

制限事項

カラム型エンジンで高速化された HNSW インデックスを更新すると、インデックス サイズの最大 2 倍のメモリが一時的に消費されることがあります。

次のステップ