向量搜尋最佳做法

本文提供建議,協助您在 Spanner 中最佳化向量搜尋的效能。

瞭解 Spanner 基本概念

如要有效執行 Spanner 向量搜尋效能測試,請先瞭解 Spanner 基礎知識。舉例來說,由於有快取,立即重新執行相同查詢的速度可能會更快。如要測試主要使用暖資料的應用程式效能,請先執行暖機讀取。

請參閱下列指南:

Spanner 會根據資料庫分割平行處理查詢。使用持續的正式查詢負載進行測試,可啟用以負載為準的分割,藉此提高平行處理能力,進而提升查詢效能。如要提高日後負載的平行處理能力,請考慮預先分割資料庫,尤其是 KNN。

向量搜尋最佳做法

本文將說明下列向量搜尋最佳做法:

為嵌入資料欄加上註解

使用 vector_length 為嵌入欄加上註解。這項註解可針對K 近鄰 (KNN) 搜尋進行效能最佳化,也是近似近鄰 (ANN) 搜尋的必要條件。

使用 top-k 查詢

如要找出最鄰近的項目,請搭配使用 LIMITORDER BY 子句。Top-k 查詢已針對向量搜尋進行高度最佳化。避免在 WHERE 子句中依距離門檻進行篩選。

舉例來說,不建議使用下列做法:

SELECT d.DocId
FROM Documents AS d
WHERE COSINE_DISTANCE(d.DocEmbedding, @vector) < 1;

請改用:

SELECT d.DocId
FROM Documents AS d
ORDER BY COSINE_DISTANCE(d.DocEmbedding, @vector)
LIMIT 10;

使用 top-k 查詢不僅更簡單 (因為不必調整距離門檻),還能針對向量搜尋進行效能最佳化。

LIMIT 子句中使用 SQL 常值

如果 top-k 限制是固定的,請使用 SQL 常值,而非參數。例如,使用 LIMIT 10,而不使用 LIMIT @limit。這會為 Spanner 查詢最佳化工具提供更多資訊,以便選取最佳查詢執行計畫

使用批次導向掃描

向量搜尋查詢會大量掃描資料,如果是 KNN 查詢,請考慮使用scan_method=batch 查詢提示,以批次導向掃描。這是 ANN 查詢的預設掃描方法。

對小型資料集使用 KNN

如果 KNN 足以符合延遲預算,請勿建立向量索引。KNN 更準確,可避免建立索引和維護成本,且在經過任何篩選後,如果輸入資料列數量較少,KNN 的效能可能會優於 ANN。

使用次要索引加快篩選 KNN 的速度

如要提升經過篩選的 KNN 查詢效能,請在篩選資料欄上建立次要索引。例如,請思考以下查詢:

SELECT d.DocId
FROM Documents AS d
WHERE Category = 'toy'
ORDER BY COSINE_DISTANCE(d.DocEmbedding, @vector)
LIMIT 10;

如果每個類別的文件數量少於幾萬份,且應用程式可接受 100 毫秒的查詢延遲時間,請在 Category 欄上建立次要索引。將 DocEmbedding 欄儲存在索引中:

CREATE INDEX ON Documents(Category) STORING (DocEmbedding);

建立這個索引有助於加快篩選查詢的速度。

針對大型資料集使用 ANN

如果評估篩選器後資料列數量龐大,請建立向量索引並使用 ANN 搜尋。有幾種技術可加快 ANN 的篩選速度:

  • 儲存篩選資料欄:如要在遍歷向量搜尋時啟用篩選功能,請在向量索引中儲存篩選資料欄。這樣一來,系統就能在執行作業的早期階段移除不符合條件的資料列。

    CREATE VECTOR INDEX ON Documents(DocEmbedding) STORING(Category);
    
  • 主要篩選資料欄:如要加快篩選速度,請將可移除大量結果的高度選擇性資料欄,整理為向量索引中的其他主要資料欄。如果查詢指定這些額外鍵的完全相等 (使用 = 運算子),加速效果最顯著。針對任何這類額外鍵使用 IN 子句,都無法達到相同的加速程度。

    CREATE VECTOR INDEX ON Documents(DocEmbedding, Category);
    
  • 避免儲存大型資料欄或將其做為鍵:否則可能會稀釋嵌入的資料區塊,進而降低讀取效率。或者,您也可以考慮在索引中使用雜湊資料欄,並在 top-k 之後使用原始大型資料欄做為後置篩選器。

  • 建立經過篩選 (部分) 的向量索引:如果您只查詢資料集的一小部分,且篩選條件定義了該部分 (例如 Category = "Tech"),請建立經過篩選或部分的向量索引