本文將說明如何調整索引,以加快查詢速度並提升搜尋結果的相關性。
調整 ScaNN
索引
ScaNN 索引會使用以樹狀結構量化為基礎的索引。在樹狀結構量化技術中,索引會與量化 (或雜湊) 函式一起學習搜尋樹狀結構。執行查詢時,搜尋樹會用於剪除搜尋空間,而量化則用於壓縮索引大小。這項修剪作業可加快查詢向量與資料庫向量之間相似度 (即距離) 的評分速度。
如要透過最鄰近查詢達到高每秒查詢次數 (QPS) 和高召回率,您必須以最適合資料和查詢的方式,分割 ScaNN
索引的樹狀結構。
建立 ScaNN
索引前,請先完成下列步驟:
- 確認已建立含有資料的表格。
- 請確認為
maintenance_work_mem
和shared_buffers
旗標設定的值小於機器總記憶體,以免在產生索引時發生問題。
調整參數
下列索引參數和資料庫標記會一併使用,以找出合適的召回率和 QPS 平衡點。所有參數都適用於兩種 ScaNN
索引類型。
調整參數 | 說明 | 參數類型 |
---|---|---|
num_leaves |
要套用至這個索引的分區數量。建立索引時套用的分區數量會影響索引效能。增加一組向量的分區數量,即可建立更精細的索引,進而提升召回率和查詢效能。不過,這樣會導致索引建立時間變長。 由於三層樹狀結構的建構速度比兩層樹狀結構快,因此建立三層樹狀結構索引時,您可以增加 num_leaves_value 來提升效能。
|
建立索引 |
quantizer |
您想用於 K 平均值樹狀結構的量化器類型。預設值為 SQ8 ,可提升查詢效能。如要提升召回率,請將值設為 FLAT 。 |
建立索引 |
enable_pca |
啟用主成分分析 (PCA),這是一種降維技術,可盡可能自動縮減嵌入的大小。這個選項預設為啟用。 如果發現召回率下降,請設為 false 。 |
建立索引 |
scann.num_leaves_to_search |
資料庫旗標可控制喚回率和 QPS 之間的取捨。預設值為 num_leaves 中設定值的 1%。設定的值越高,喚回度就越好,但 QPS 會降低,反之亦然。 |
查詢執行階段 |
scann.max_top_neighbors_buffer_size |
資料庫標記會指定快取大小,用於在記憶體中評分或排序掃描的候選鄰項,而非在磁碟中,藉此提升篩選查詢的效能。預設值為 20000 。設定的值越高,篩選查詢的 QPS 就越好,但記憶體用量也會增加,反之亦然。 |
查詢執行階段 |
scann.pre_reordering_num_neighbors |
設定資料庫標記後,系統會在初始搜尋找出候選項目後,於重新排序階段考慮指定數量的候選鄰點。請將這個值設為大於查詢要傳回的鄰點數量。 較高的值集可提高喚回度,但這種做法會降低 QPS。 |
查詢執行階段 |
max_num_levels |
K-means 分群樹狀結構的層級數量上限。
|
建立索引 |
調整 ScaNN
索引
請參閱以下兩層和三層 ScaNN
索引的範例,瞭解如何設定微調參數:
兩層索引
SET LOCAL scann.num_leaves_to_search = 1;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 1/2)]);
三層索引
SET LOCAL scann.num_leaves_to_search = 10;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 2/3)], max_num_levels = 2);
如果資料表已產生 ScaNN
索引,任何插入或更新作業都會影響學習樹狀結構最佳化索引的方式。如果表格經常更新或插入資料,建議您定期重新建立現有 ScaNN
索引,以提高召回準確度。
您可以監控索引指標,判斷自建立索引以來產生的變動量,然後據此重新建立索引。如要進一步瞭解指標,請參閱「向量索引指標」。
微調的最佳做法
根據您打算使用的ScaNN
索引類型,調整索引的建議也會有所不同。本節提供相關建議,說明如何調整索引參數,在召回率和每秒查詢次數之間取得最佳平衡。
兩層樹狀結構索引
如要套用建議,協助您找出資料集的最佳 num_leaves
和 num_leaves_to_search
值,請按照下列步驟操作:
- 建立
ScaNN
索引,並將num_leaves
設為索引資料表列數的平方根。 - 執行測試查詢,並提高
scann.num_of_leaves_to_search
的值,直到達到目標召回率範圍 (例如 95%) 為止。如要進一步瞭解如何分析查詢,請參閱「分析查詢」。 - 請記下
scann.num_leaves_to_search
和num_leaves
之間的比例,後續步驟會用到。這個比率會提供資料集近似值,協助您達成目標召回率。
如果您使用高維度向量 (500 個以上的維度),並想提高召回率,請嘗試調整scann.pre_reordering_num_neighbors
的值。首先,請將值設為100 * sqrt(K)
,其中K
是您在查詢中設定的限制。 - 如果查詢達到目標召回率後,QPS 仍過低,請按照下列步驟操作:
- 重新建立索引,並根據下列指引增加
num_leaves
和scann.num_leaves_to_search
的值:- 將
num_leaves
設為大於列數平方根的因數。舉例來說,如果索引的num_leaves
設為資料列數的平方根,請嘗試將其設為平方根的兩倍。如果值已是兩倍,請嘗試將值設為平方根的三倍。 - 視需要增加
scann.num_leaves_to_search
,以維持與num_leaves
的比例 (您在步驟 3 中記下)。 - 將
num_leaves
設為小於或等於資料列數除以 100 的值。
- 將
- 再次執行測試查詢。
執行測試查詢時,請嘗試降低
scann.num_leaves_to_search
,找出可提高每秒查詢次數,同時維持高召回率的值。嘗試使用不同的scann.num_leaves_to_search
值,不必重建索引。
- 重新建立索引,並根據下列指引增加
- 重複步驟 4,直到 QPS 和召回範圍都達到可接受的值。
三層樹狀結構索引
除了兩層樹狀結構 ScaNN
索引的建議做法外,請使用下列指引和步驟調整索引:
- 將兩層樹狀結構的
max_num_levels
從1
增加到三層樹狀結構的2
,可大幅縮短建立索引的時間,但會降低召回準確度。請根據下列建議設定max_num_levels
:- 如果向量資料列數超過 1 億列,請將值設為
2
。 - 如果向量資料列數少於 1 千萬列,請將值設為
1
。 - 如果向量列數介於 1 千萬到 1 億列之間,請根據索引建立時間和所需回想準確度的平衡,將值設為
1
或2
。
- 如果向量資料列數超過 1 億列,請將值設為
如要套用建議,找出 num_leaves
和 max_num_levels
索引參數的最佳值,請按照下列步驟操作:
根據資料集建立
ScaNN
索引,並使用下列num_leaves
和max_num_levels
組合:- 向量資料列超過 1 億列:將
max_num_levels
設為2
,並將num_leaves
設為power(rows, ⅔)
。 - 向量資料列少於 1 億列:將
max_num_levels
設為1
,並將num_leaves
設為sqrt(rows)
。 - 向量資料列介於 1 千萬到 1 億列之間:請先將
max_num_levels
設為1
,並將num_leaves
設為sqrt(rows)
。
- 向量資料列超過 1 億列:將
執行測試查詢。如要進一步瞭解如何分析查詢,請參閱「分析查詢」。
如果索引建立時間令人滿意,請保留
max_num_levels
值,並試用num_leaves
值,以達到最佳的召回準確度。如果對索引建立時間不滿意,請執行下列操作:
如果
max_num_levels
值為1
,請捨棄索引。將max_num_levels
值設為2
,然後重建索引。執行查詢並調整
num_leaves
值,以獲得最佳的召回準確度。如果
max_num_levels
值為2
,請捨棄索引。使用相同的max_num_levels
值重建索引,並調整num_leaves
值,以達到最佳的召回準確度。
調整 IVF
索引
調整為 lists
、ivf.probes
和 quantizer
參數設定的值,可能有助於提升應用程式效能:
調整參數 | 說明 | 參數類型 |
---|---|---|
lists |
建立索引期間建立的清單數量。如要設定這個值,最多一百萬列的資料應從 (rows)/1000 開始,超過一百萬列的資料則應從 sqrt(rows) 開始。 |
建立索引 |
quantizer |
您想用於 K 平均值樹狀結構的量化器類型。預設值為 SQ8 ,可提升查詢效能。設為 FLAT 可提高回想率。 |
建立索引 |
ivf.probes |
搜尋期間要探索的最近清單數量。這個值的起點是 sqrt(lists) 。 |
查詢執行階段 |
請參考以下範例,瞭解如何設定調整參數的 IVF
索引:
SET LOCAL ivf.probes = 10;
CREATE INDEX my-ivf-index ON my-table
USING ivf (vector_column cosine)
WITH (lists = 100, quantizer = 'SQ8');
調整 IVFFlat
索引
調整為 lists
和 ivfflat.probes
參數設定的值,有助於提升應用程式效能:
調整參數 | 說明 | 參數類型 |
---|---|---|
lists |
建立索引期間建立的清單數量。如要設定這個值,最多一百萬列的資料應從 (rows)/1000 開始,超過一百萬列的資料則應從 sqrt(rows) 開始。 |
建立索引 |
ivfflat.probes |
搜尋期間要探索的最近清單數量。這個值的起點是 sqrt(lists) 。 |
查詢執行階段 |
建立 IVFFlat
索引前,請確認資料庫的 max_parallel_maintenance_workers
旗標已設為足夠的值,可加快大型資料表的索引建立速度。
請參考以下範例,瞭解如何設定調整參數的 IVFFlat
索引:
SET LOCAL ivfflat.probes = 10;
CREATE INDEX my-ivfflat-index ON my-table
USING ivfflat (vector_column cosine)
WITH (lists = 100);
調整 HNSW
索引
調整為 m
、ef_construction
和 hnsw.ef_search
參數設定的值,有助於提升應用程式效能。
調整參數 | 說明 | 參數類型 |
---|---|---|
m |
圖表中每個節點的連線數量上限。您可以從預設值 16 (預設) 開始,並根據資料集大小嘗試使用較高的值。 |
建立索引 |
ef_construction |
圖表建構期間維護的動態候選清單大小,會不斷更新節點的最近鄰項目前最佳候選項目。將這個值設為大於 m 值的兩倍,例如 64 (預設值)。 |
建立索引 |
ef_search |
搜尋期間使用的動態候選名單大小。您可以先將這個值設為 m 或 ef_construction ,然後在觀察召回率時變更這個值。預設值為 40 。 |
查詢執行階段 |
請參考以下範例,瞭解如何設定調整參數的 hnsw
索引:
SET LOCAL hnsw.ef_search = 40;
CREATE INDEX my-hnsw-index ON my-table
USING hnsw (vector_column cosine)
WITH (m = 16, ef_construction = 200);
分析查詢
使用 EXPLAIN ANALYZE
指令分析查詢洞察,如下列 SQL 查詢範例所示。
EXPLAIN ANALYZE SELECT result-column FROM my-table
ORDER BY EMBEDDING_COLUMN ::vector
USING INDEX my-scann-index
<-> embedding('textembedding-gecko@003', 'What is a database?')
LIMIT 1;
範例回應 QUERY PLAN
包含所花時間、掃描或傳回的資料列數,以及使用的資源等資訊。
Limit (cost=0.42..15.27 rows=1 width=32) (actual time=0.106..0.132 rows=1 loops=1)
-> Index Scan using my-scann-index on my-table (cost=0.42..858027.93 rows=100000 width=32) (actual time=0.105..0.129 rows=1 loops=1)
Order By: (embedding_column <-> embedding('textgecko@003', 'What is a database?')::vector(768))
Limit value: 1
Planning Time: 0.354 ms
Execution Time: 0.141 ms
查看向量索引指標
您可以運用向量索引指標查看向量索引的成效、找出需要改進的地方,並視需要根據指標調整索引。
如要查看所有向量索引指標,請執行下列 SQL 查詢 (使用
pg_stat_ann_indexes
檢視區塊):
SELECT * FROM pg_stat_ann_indexes;
如要進一步瞭解完整的指標清單,請參閱「向量索引指標」。