DiskANN 是可調整的近似近鄰搜尋演算法,可在任何規模上有效率地進行向量搜尋。 它可帶來高重新叫用率、高每秒查詢數和低查詢延遲,即使是數十億個資料集亦然。 這些特性使其成為處理大量數據的強大工具。
若要深入了解 DiskANN,請參閱 DiskANN:適用於大規模網頁搜尋和推薦的向量搜尋。
此 pg_diskann 延伸模組新增了使用 DiskANN 進行有效率的向量索引編製和搜尋的支援。
啟用pg_diskann
要在你的 適用於 PostgreSQL 的 Azure 資料庫 彈性伺服器上使用pg_diskann這個擴充功能,你需要在伺服器層級允許這個擴充功能。 接著,您必須在想要使用擴充功能的每個資料庫上 建立擴充 功能。
由於 pg_diskann 相依於 vector 擴充功能,因此您可以在相同的資料庫中 允許 和 建立vector 擴充功能,然後執行下列命令:
CREATE EXTENSION IF NOT EXISTS pg_diskann;
或者,您可以不要明確允許和建立 vector 延伸模組,而將先前的命令附加 CASCADE 子句來執行。 該子句會使 PostgreSQL 自動在其所依賴的擴充功能上執行 CREATE EXTENSION。 若要這樣做,請執行下列命令:
CREATE EXTENSION IF NOT EXISTS pg_diskann CASCADE;
若要從您目前連線的資料庫卸除延伸模組,請執行下列命令:
DROP EXTENSION IF EXISTS pg_diskann;
使用 DiskANN 索引存取方法
安裝擴充功能後,你可以在包含向量資料的資料表欄位建立 diskann 索引。 例如,若要在 embedding 資料表的 demo 資料行上建立索引,請使用下列命令:
CREATE TABLE demo (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
embedding public.vector(3)
-- other columns
);
-- insert dummy data
INSERT INTO demo (embedding) VALUES
('[1.0, 2.0, 3.0]'),
('[4.0, 5.0, 6.0]'),
('[7.0, 8.0, 9.0]');
-- create a diskann index by using Cosine distance operator
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)
建立索引後,你可以執行查詢來尋找最近鄰。
以下查詢可找出向量 [2.0, 3.0, 4.0]的五個最近鄰:
SELECT id, embedding
FROM demo
ORDER BY embedding <=> '[2.0, 3.0, 4.0]'
LIMIT 5;
Postgres 會自動決定何時使用 DiskANN 索引。 如果它在你希望它使用索引的情況下選擇不使用索引,請執行以下指令:
-- Explicit Transcation block to force use for DiskANN index.
BEGIN;
SET LOCAL enable_seqscan TO OFF;
-- Similarity search queries
COMMIT;
這很重要
設定 enable_seqscan 為關閉會讓規劃者不願使用查詢規劃器所採用的順序掃描計畫(如果有其他方法)。 因為使用 SET LOCAL 指令會停用該設定,因此該設定只會對當前交易生效。 在 COMMIT 或 ROLLBACK 之後,會話層級設定會再次生效。 若查詢涉及其他資料表,設定也會不鼓勵在所有資料表中使用順序掃描。
有效利用量化技術擴展規模(預覽)
DiskANN 使用產品量化 (PQ) 大幅減少向量記憶體使用量。 與其他量化技術不同,PQ 演算法可以更有效地壓縮向量,大幅改善效能。 透過使用 PQ,DiskANN 能在記憶體中保留更多資料,減少存取較慢儲存空間的需求,並在比較壓縮向量時節省計算量。 這可在處理大量資料 (> 1 百萬個資料列) 時帶來更好的效能和顯著的成本節省。
這很重要
DiskANN 中的乘積量化支援從 pg_diskann v0.6 及更高版本開始提供。
若要縮小索引大小並容納更多資料到記憶體,請使用 PQ:
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann(embedding vector_cosine_ops)
WITH(
product_quantized=true
);
提高將 PQ 與向量重新排序一起使用時的正確性
使用完整向量重新排序是近似最鄰近項目 (ANN) 搜尋系統 (如具有乘積量化 (PQ) 的 DiskANN) 中使用的一種技術,其透過使用原始的未壓縮 (全精確度) 向量對前 N 個已擷取的候選項目進行重新排序來提高結果正確性。 此重新排序技術純粹基於精確的向量相似度指標(例如餘弦相似度或歐氏距離)。 此技術與使用排名模型重新排序 (英文) 不同。
為了在向量相似性搜尋中取得速度與精確度的平衡,建議在使用 DiskANN 查詢時實施兩步驟重新排序策略,並以產品量化提升準確度。
初始近似搜尋:內部查詢使用 DiskANN 根據儲存的內嵌和查詢向量之間的餘弦距離來擷取前 50 個近似最鄰近項目。 此步驟快又有效率,因為它利用了 DiskANN 的索引編製功能。
精確重新排序:外部查詢會依實際計算的距離重新排序那 50 個結果,並傳回前 10 個最相關的相符項:
以下是使用這種兩步驟方法重新排名的範例:
SELECT id
FROM (
SELECT id, embedding <=> %s::vector AS distance
FROM demo
ORDER BY embedding <=> %s::vector asc
LIMIT 50
) AS t
ORDER BY t.distance
LIMIT 10;
備註
用查詢向量替換 %s 。 您可以使用 azure_ai 直接在 Postgres 中建立查詢向量。
這種方法平衡了速度 (透過近似搜尋) 和正確性 (透過完整的向量重新排序),進而確保高品質的結果,而無需掃描整個資料集。
支援高維內嵌
進階生成式 AI 應用程式通常依賴高維內嵌模型 (例如 text-embedding-3-large) 來達成卓越的正確性。 不過,傳統的索引編製方法 (如 pgvector 中的 HNSW) 受限於最多 2,000 個維度的向量,這使得您無法使用這些強大的模型。
從 pg_diskann v0.6 及以後版本開始,DiskANN 支援最高 16,000 維度的索引向量,大幅擴展了高精度 AI 工作負載的範圍。
這很重要
開啟產品量化以發揮高維度支援。
建議的設定:
-
product_quantized:設定為 true -
pq_param_num_chunks:設定為內嵌維度的三分之一,以獲得最佳效能。 -
pq_param_training_samples:除非明確設定,否則會根據資料表大小自動決定。
此增強功能可讓您跨大型向量資料集進行可調整且有效率的搜尋,同時維持高重新叫用率和精確度。
加速索引建置
為了提升你的 Index 建立時間,請試試以下建議。
使用更多記憶體
為了加快索引建立,請增加 PostgreSQL 伺服器上用於索引建置的記憶體。 透過參數 maintenance_work_mem 指定記憶體使用量。
-- Set the parameters
SET maintenance_work_mem = '8GB'; -- Depending on your resources
CREATE INDEX 命令會視可用資源而定,使用指定的工作記憶體來建立索引。
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)
小提示
在建立索引時先擴充記憶體資源以提升索引速度,完成索引後再縮減回去。
使用平行處理
為了加快索引的建立,可以使用平行工作者。 在建立資料表時,透過 parallel_workers 敘述的 CREATE TABLE 儲存參數指定工作者數量。 你可以之後用 SET 陳述中的 ALTER TABLE 條款來調整這個數字。
CREATE TABLE demo (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
embedding public.vector(3)
) WITH (parallel_workers = 4);
ALTER TABLE demo SET (parallel_workers = 8);
CREATE INDEX 命令會視可用資源而定,使用指定數量的平行工作者來建立索引。
CREATE INDEX demo_embedding_diskann_idx ON demo USING diskann (embedding vector_cosine_ops)
這很重要
領導者流程無法參與平行索引建置。
如果你想用平行工作者來建立索引,請相應設定 max_parallel_workers、 max_worker_processes和 max_parallel_maintenance_workers 參數。 如需這些參數的詳細資訊,請參閱 控制資源使用量和異步行為的參數。
將這些參數設定在不同的粒度層級。 例如,要在會話層級設定它們,執行以下語句:
-- Set the parameters
SET max_parallel_workers = 8;
SET max_worker_processes = 8; -- Note: Requires server restart
SET max_parallel_maintenance_workers = 4;
欲了解在適用於 PostgreSQL 的 Azure 資料庫靈活伺服器中配置這些參數的其他選項,請參見 Configure parameters。
備註
該 max_worker_processes 參數需要重新啟動伺服器才能生效。
如果這些參數和伺服器上的可用資源設定不允許啟動平行工作者,PostgreSQL 會自動使用非平行模式來建立索引。
組態參數
建立 diskann 索引時,請指定各種參數來控制其運作。
索引參數
-
max_neighbors:圖形中每個節點的邊緣數目上限。 預設值為 32。 較高的值可以提升召回率,達到特定點。 -
l_value_ib:索引建置時搜尋清單的大小。 預設值是 100。 數值越高,製作速度越慢,但指數品質較高。 -
product_quantized:啟用乘積量化,讓搜尋更有效率。 預設值為 false。 -
pq_param_num_chunks:產物量化的區塊數。 預設值為 0,表示系統會根據嵌入維度自動決定該值。 使用原始嵌入尺寸的三分之一。 -
pq_param_training_samples:用於訓練 PQ 樞紐表的向量數量。 預設值為 0,表示系統會根據資料表大小自動決定該值。
CREATE INDEX demo_embedding_diskann_custom_idx ON demo USING diskann (embedding vector_cosine_ops)
WITH (
max_neighbors = 48,
l_value_ib = 100,
product_quantized=true,
pq_param_num_chunks = 0,
pq_param_training_samples = 0
);
擴充參數
diskann.iterative_search:控制搜尋行為。diskann.iterative_search的設定:relaxed_order(預設值):讓 diskann 以diskann.l_value_is為批次反覆搜尋圖形,直到得到所需數量的 Tuple (可能受限於LIMIT子句) 為止。 此選項可能導致結果順序不符。strict_order:與 類似relaxed_order,但確保結果以嚴格順序返回,並依距離排序。off:使用非迭代搜尋功能。 它嘗試一次擷取diskann.l_value_is元組。 非反覆搜尋最多只能為一個查詢傳回diskann.l_value_is個向量,無論LIMIT子句或符合查詢的 Tuple 數目為何。
要將搜尋行為更改為
strict_order對當前會話中執行的所有查詢,請執行以下陳述句:SET diskann.iterative_search TO 'strict_order';若要變更它,使其只會影響目前交易中執行的所有查詢,請執行下列語句:
BEGIN; SET LOCAL diskann.iterative_search TO 'strict_order'; -- All your queries COMMIT;diskann.l_value_is: L 值用於索引掃描(預設為 100)。 增加值可改善召回率,但可能會讓查詢變慢。要將當前會話中執行的所有查詢的索引掃描 L 值改為 20,請執行以下陳述句:
SET diskann.l_value_is TO 20;若要變更它,使其只會影響目前交易中執行的所有查詢,請執行下列語句:
BEGIN; SET LOCAL diskann.l_value_is TO 20; -- All your queries COMMIT;
建議的參數設定
| 資料集大小(資料行) | 參數類型 | 名稱 | 建議值 |
|---|---|---|---|
| <100萬 | 索引組建 | l_value_ib |
100 |
| <100萬 | 索引組建 | max_neighbors |
32 |
| <100萬 | 查詢時間 | diskann.l_value_is |
100 |
| 1M-50M | 索引組建 | l_value_ib |
100 |
| 1M-50M | 索引組建 | max_neighbors |
64 |
| 1M-50M | 索引組建 | product_quantized |
true |
| 1M-50M | 查詢時間 | diskann.l_value_is |
100 |
| >5,000 萬 | 索引組建 | l_value_ib |
100 |
| >5,000 萬 | 索引組建 | max_neighbors |
96 |
| >5,000 萬 | 索引組建 | product_quantized |
true |
| >5,000 萬 | 查詢時間 | diskann.l_value_is |
100 |
備註
這些參數可能會根據特定的數據集和使用案例而有所不同。 你可能需要嘗試不同的參數值,找出最適合你情境的最佳設定。
CREATE INDEX 和 REINDEX 進度
從 PostgreSQL 12 開始,你可以用來 pg_stat_progress_create_index 檢查 CREATE INDEX 或 REINDEX 操作的進度。
SELECT phase, round(100.0 * blocks_done / nullif(blocks_total, 0), 1) AS "%" FROM pg_stat_progress_create_index;
欲了解更多建立索引或重新索引操作可能經歷的階段,請參閱建立索引階段。
選取索引存取函式
向量類型支援三種對儲存向量的搜尋方式。 為您的索引選擇正確的存取功能,讓資料庫在執行查詢時能考慮您的索引。
pg_diskann 支援以下距離運算子:
-
vector_l2_ops:<->Euclidean 距離 -
vector_cosine_ops:<=>餘弦距離 -
vector_ip_ops:<#>內積
故障排除
錯誤: : assertion left == right failed left: 40 right: 0
DiskANN GA 版本 v0.6.x 引進 了索引元數據格式的重大變更。 以 v0.5.x 建立的索引與 v0.6.x 插入操作不相容。 如果你嘗試插入索引過時的資料表,即使索引看起來有效,也會收到錯誤。
遇到此錯誤時,請 用以下方式解決:
選項 1: 在索引上執行
REINDEX或REDINDEX CONCURRENTLY語句。選項二: 重建索引。
DROP INDEX your_index_name; CREATE INDEX your_index_name ON your_table USING diskann(your_vector_column vector_cosine_ops);
錯誤: : diskann index needs to be upgraded to version 2...
- 遇到此錯誤時,請用以下方式解決:
選項 1: 在索引上執行
REINDEX或REDINDEX CONCURRENTLY語句。選項 2: 由於
REINDEX可能需要很長的時間,因此擴充功能也提供了一個稱為upgrade_diskann_index()的使用者定義函式,當可能時,能夠更快速地升級您的索引。若要升級索引,請執行下列語句:
SELECT upgrade_diskann_index('demo_embedding_diskann_custom_idx');若要將資料庫中的所有 diskann 索引升級為目前版本,請執行下列語句:
SELECT upgrade_diskann_index(pg_class.oid) FROM pg_class JOIN pg_am ON (pg_class.relam = pg_am.oid) WHERE pg_am.amname = 'diskann';