ベクトル検索の再現率を測定する

ドキュメントのバージョンを選択してください。

このページでは、AlloyDB Omni でベクトルクエリの再現率を測定する方法について説明します。ベクトル検索のコンテキストにおける「再現率」とは、インデックスから返されたベクトルのうち、真の最近傍であるものの割合を指します。たとえば、20 個の最近傍に対する最近傍のクエリで、グラウンド トゥルースの最近傍が 19 個返された場合、再現率は 19 ÷ 20 × 100 = 95% となります。

ベクトルクエリでは、検索から取得された関連する結果の割合を測定するため、再現率が重要になります。再現率は、近似最近傍(ANN)検索の結果の精度を、K 近傍(KNN)検索の結果と比較して評価する際に役立ちます。

ANN は、指定されたクエリポイントに類似するデータポイントを見つけるアルゴリズムで、実際の近傍ではなく近似近傍を見つけることで速度を高めます。ANN を使用すると、速度と再現率のバランスを取ることができます。

KNN は、類似度指標に基づいて、データセット内の特定のクエリベクトルに最も類似する「k」個のベクトルを見つけるアルゴリズムです。k は、クエリで返す近傍の数です。

次のようなさまざまなベクトル インデックスについて、ベクトル検索クエリの再現率を測定できます。

  • Scalable Nearest Neighbors(ScaNN): 効率的なベクトル類似検索を行うためのアルゴリズム。
  • Hierarchical Navigable Small World(HNSW): ベクトル データベースで効率的な近似最近傍探索を行うために使用されるグラフベースのアルゴリズム。
  • Inverted File with Flat Compression(IVFFLAT)と Inverted File Flat(IVF): ANN 検索に使用されるベクトル インデックスのタイプ(特に PostgreSQL といったデータベースの pgvector 拡張機能で使用)。

このページの内容は、PostgreSQL、AlloyDB Omni、ベクトル検索の知識がある方向けです。

始める前に

  1. pgvector 拡張機能をインストールまたは更新します。

    1. pgvector 拡張機能がインストールされていない場合は、vector 拡張機能のバージョン 0.8.0.google-3 以降をインストールして、生成されたエンベディングを vector 値として保存します。vector 拡張機能には、pgvector 関数と演算子が含まれています。Google は、AlloyDB Omni 用に最適化を加えて、この pgvector のバージョンを拡張しています。

      CREATE EXTENSION IF NOT EXISTS vector WITH VERSION '0.8.0.google-3';
      

      詳細については、ベクトルの保存、インデックス登録、クエリをご覧ください。

    2. pgvector 拡張機能がすでにインストールされている場合は、vector 拡張機能をバージョン 0.8.0.google-3 以降にアップグレードして、再現率評価ツールを利用できるようにします。

      ALTER EXTENSION vector UPDATE TO '0.8.0.google-3';
      
  2. ScaNN インデックスを作成するには、alloydb_scann 拡張機能をインストールします。

    CREATE EXTENSION IF NOT EXISTS alloydb_scann;
    

ベクトル インデックスでベクトルクエリの再現率を評価する

特定の構成のベクトル インデックスに対するベクトルクエリの再現率は evaluate_query_recall 関数で確認できます。この関数を使用すると、目的のベクトルクエリの再現率を達成するようにパラメータをチューニングできます。再現率は検索品質に使用される指標で、クエリベクトルに客観的に最も近い結果が返された割合として定義されます。evaluate_query_recall 関数はデフォルトでオンになっています。

ベクトルクエリの再現率を確認する

  1. AlloyDB Studio で SQL エディタを開くか、psql クライアントを開きます。
  2. ScaNN、HNSW、IVFFLAT のいずれかのベクトル インデックスを作成します

  3. enable_indexscan フラグがオンになっていることを確認します。フラグがオフの場合、インデックス スキャンは選択されず、すべてのインデックスの再現率は 1 になります。

  4. evaluate_query_recall 関数を実行します。この関数はクエリをパラメータとして受け取り、次の再現率を返します。

    SELECT * FROM evaluate_query_recall( QUERY_TEXT, QUERY_TIME_CONFIGURATIONS, INDEX_METHODS )
    

    このコマンドを実行する前に、次のように置き換えます。

    • QUERY_TEXT: $$.
    • QUERY_TIME_CONFIGURATIONS: Optional: the configuration that you can set for the ANN query. This must be in JSON format. The default value is NULL.
    • INDEX_METHODS: Optional: a text array that contains different vector index methods for which you want to calculate the recall. If you set an index method for which a corresponding index doesn't exist, the recall is 1. The input must be a subset of {scann, hnsw, ivf, ivfflat}. If no value is provided, the ScaNN method is used.

      To view differences between query recall and execution time, change the query time parameters for your index.

      The following table lists query time parameters for ScaNN, HNSW, and IVF/IVFFLAT index methods. The parameters are formatted as {"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10, "hnsw.ef_search": 1}.

      Index type Parameters
      ScaNN
      • scann.num_leaves_to_search
      • scann.pre_reordering_num_neighbors
      • scann.pct_leaves_to_search
      • scann.num_search_threads
      HNSW
      • hnsw.ef_search
      • hnsw.iterative_scan
      • hnsw.max_scan_tuples
      • hnsw.scan_mem_multiplier
      IVF
      • ivf.probes
      IVFFLAT
      • ivfflat.probes
      • ivfflat.iterative_scan
      • ivfflat.max_probes

      For more information about ScaNN index methods, see AlloyDB Omni ScaNN Index reference. For more information about HNSW and IVF/IVFFLAT index methods, see pgvector.

  5. Optional: You can also add configurations from pg_settings to the QUERY_TIME_CONFIGURATIONS. For example, to run a query with columnar engine scan enabled, add the following config from pg_settings as {"google_columnar_engine.enable_columnar_scan" : on}.

    The configurations are set locally in the function. Adding these configurations doesn't impact the configurations that you set in your session. If you don't set any configurations, AlloyDB uses all of the configurations that you set in the session. You can also set only those configurations that are best suited for your use case.

  6. Optional: To view the default configuration settings, run the SHOW command or view the pg_settings.

  7. Optional: If you have a ScaNN index for which you want to tune the recall, see the tuning parameters in ScaNN index reference.

    The following is an example output, where ann_execution_time is the time that it takes a vector query to execute using index scans. ground_truth_execution_time is the time that it takes the query to run using a sequential scan.

    ann_execution_time and ground_truth_execution_time are different from but directly dependent on Execution time in the query plan. Execution time is the total time to execute the query from the client.

    t=# SELECT * FROM evaluate_query_recall( $$ SELECT id FROM t1 ORDER BY val <=> '[1000,1000,49000]' LIMIT 10 $$, '{"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10, "hnsw.ef_search": 1}', ARRAY['scann', 'hnsw']);
    NOTICE:  Recall is 1. This might mean that the vector index is not present on the table or index scan not chosen during query execution.
    id|               query                                               |                                         configurations                                         |  recall |ann_execution_time | ground_truth_execution_time |  index_type
    ----+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------+--------+--------------------+-----------------------------+------------
    1 |  SELECT id FROM t1 ORDER BY val <=> '[1000,1000,49000]' LIMIT 10  | {"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10, "hnsw.ef_search": 1} |    0.5 |               4.23 |                     118.211 | scann
    2 |  SELECT id FROM t1 ORDER BY val <=> '[1000,1000,49000]' LIMIT 10  | {"scann.num_leaves_to_search":1, "scann.pre_reordering_num_neighbors":10, "hnsw.ef_search": 1} |      1 |            107.198 |                     118.211 | hnsw
    (2 rows)
     で囲まれた SQL クエリ。

    結果が Recall is 1 の場合(クエリの再現率が 1 の場合)、ベクトル インデックスがテーブルに存在しないか、クエリの実行中にベクトル インデックスが選択されなかった可能性があります。これは、テーブルにベクトル インデックスがない場合、またはプランナーがベクトル インデックス スキャンを選択していない場合に発生します。

    クエリが select id, name from table order by embedding <->'[1,2,3]' LIMIT 10;. で、予期される列名の値が NULL の場合は、クエリを次のいずれかに変更します。

    select id, COALESCE(name, 'NULL') as name from table order by embedding <-> '[1,2,3]' LIMIT 10;
    

    または

    select id from table order by embedding <-> '[1,2,3]' LIMIT 10;
    

次のステップ