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]最接近的 5 個鄰居:
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 個最相關的相符項:
以下是使用此 2 步驟方法重新排序的範例:
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:除非明確設定,否則會根據資料表大小自動決定。
此增強功能可讓您跨大型向量資料集進行可調整且有效率的搜尋,同時維持高重新叫用率和精確度。
加速索引建置
有幾種方式建議改善索引建置時間。
使用更多記憶體
若要加速建立索引,您可以增加 Postgres 實例上為索引組建配置的記憶體。 記憶體使用量可以透過 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 資料庫中設定這些參數的其他選項,請參閱 設定伺服器參數。
附註
max_worker_processes參數需要重新啟動伺服器才會生效。
如果這些參數和伺服器上的可用資源設定不允許啟動平行工作者,PostgreSQL 會自動使用非平行模式來建立索引。
組態參數
建立 diskann 索引時,您可以指定各種參數來控制其行為。
索引參數
-
max_neighbors:圖表中每個節點的邊緣數目上限(預設值為32)。 較高的值可以提升召回率,達到特定點。 -
l_value_ib:索引建置期間搜尋清單的大小(預設值為 100)。 較高的值會使建置變慢,但索引品質較高。 -
product_quantized:啟用乘積量化以進行更有效率的搜尋 (預設為 False)。 -
pq_param_num_chunks:產品量化的區塊數(預設值為 0)。 0 表示它會根據內嵌維度自動決定。 建議使用原始內嵌維度的 1/3。 -
pq_param_training_samples:訓練 PQ 樞紐表用的向量數目(預設值為 0)。 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,可讓 diskan 反覆搜尋圖表,直到產生所需的 Tuple 數目為止。 不過,它會確保結果會依距離排序的嚴格順序傳回。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;
若要深入瞭解 CREATE INDEX 或 REINDEX 作業經歷的可能階段,請參閱 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語句。選項 2: 重建索引
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';