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 可以將更多資料保留在記憶體中,減少存取較慢記憶體的需求,以及在比較壓縮向量時使用較少的計算。 使用大量數據時,這會產生更佳的效能和大幅節省成本(> 100 萬個數據列)
若要存取產品量化(PQ) 功能,請註冊預覽版
加速索引建置
有幾種方式建議改善索引建置時間。
使用更多記憶體
若要加速建立索引,您可以增加 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)。 較高的值會使建置變慢,但索引品質較高。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,
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 | 查詢時間 | diskann.l_value_is |
100 |
>50M | 索引組建 | l_value_ib |
100 |
>50M | 索引組建 | max_neighbors |
96 |
>50M | 查詢時間 | 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';