評估向量查詢召回率

本頁說明如何在 AlloyDB for PostgreSQL 中評估向量查詢的召回率。在向量搜尋的脈絡中,「召回率」是指索引傳回的向量中,屬於真正最近鄰的百分比。舉例來說,如果 20 個最鄰近項目的最鄰近項目查詢傳回 19 個最鄰近項目,則召回率為 19/20x100 = 95%。

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

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

KNN 演算法會根據相似度指標,在資料集中找出與指定查詢向量最相似的「k」個向量。k 是指查詢要傳回的鄰近向量數量。

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

  • 可擴充的最近鄰 (ScaNN):可有效搜尋向量相似度的演算法。
  • 階層式可導覽小世界 (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;
    

後續步驟