評估向量查詢的召回率

在 AlloyDB for PostgreSQL 中評估向量查詢喚回度,有助於評估近似最鄰近 (ANN) 索引的搜尋準確度,並調整索引參數。在向量搜尋中,「喚回度」是指索引傳回的真最鄰近項目百分比,與精確搜尋相比。舉例來說,如果查詢 20 個最近鄰點時,傳回 19 個最接近的鄰點,則召回率為 95% (19/20 * 100)。

在向量查詢中,召回率很重要,因為它會評估從搜尋中擷取的相關結果百分比。喚回度可協助您評估近似近鄰 (ANN) 搜尋結果的準確度,並與 K 近鄰 (KNN) 搜尋結果比較。

ANN 演算法會找出與指定查詢點相似的資料點,並找出近似鄰點 (而非實際鄰點),藉此提升速度。使用 ANN 時,您必須在速度和喚回度之間取得平衡。

KNN 是一種演算法,可根據相似度指標,在資料集中找出與指定查詢向量最相似的「k」個向量。k 是您希望查詢傳回的鄰近項目數量。

您可以評估不同向量索引的向量搜尋查詢喚回度,包括:

  • 可擴充的最近鄰 (ScaNN):用於高效率向量相似度搜尋的演算法。
  • Hierarchical Navigable Small World (HNSW):一種圖形演算法,用於在向量資料庫中有效率地搜尋近似最鄰近項目。
  • 倒排檔案與平面壓縮 (IVFFLAT) 和倒排檔案平面 (IVF):用於 ANN 搜尋的向量索引類型,特別是在 PostgreSQL pgvector 擴充功能等資料庫中。

本頁面假設您熟悉 PostgreSQL、AlloyDB 和向量搜尋。

事前準備

  1. 安裝或更新 pgvector 擴充功能。

    1. 如果尚未安裝 pgvector 擴充功能,請安裝 vector 擴充功能 0.8.0.google-3 以上版本,將產生的嵌入內容儲存為 vector 值。vector 擴充功能包含 pgvector 函式和運算子。Google 擴充了這個版本的 pgvector,並針對 AlloyDB 進行最佳化。

      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:SQL 查詢,以 $$.
    • 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
      • ivf.iterative_scan
      • ivf.max_probes
      IVFFLAT
      • ivfflat.probes
      • ivfflat.iterative_scan
      • ivfflat.max_probes

      For more information about ScaNN index methods, see AlloyDB 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)
     括住

    如果結果為 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;
    

後續步驟