AnalyticDB PostgreSQL版提供完全按照相似性距離排序的精確檢索(搜尋速度較慢)和使用HNSW索引的近似索引檢索(搜尋速度快)兩種向量檢索方式。
精確檢索
完全按照相似性距離排序的暴力搜尋。此方式需要比較每一個向量,因此它的搜尋速度較慢,但是召回率可以達到百分之百。
歐氏距離、內積距離,餘弦相似性三種距離相似性的精確檢索使用方式如下:
歐氏距離
SELECT ID, l2_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY l2_squared_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) LIMIT <TOPK>;
內積距離
SELECT ID, inner_product_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY negative_inner_product_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) LIMIT <TOPK>;
餘弦相似性
SELECT ID, cosine_similarity(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY cosine_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) LIMIT <TOPK>;
各欄位說明:
score:在三種檢索方式中的score分別表示歐氏距離,內積距離和餘弦相似性,並且分別按歐氏距離從小到大排序,按點積距離從大到小排序,按餘弦相似性從大到小排序。
<VECTOR_COLUMN_NAME>:向量列名稱。
<TABLE_NAME>:向量表名稱。
<TOPK>:需要檢索的結果集topk。
近似的索引檢索
通過使用HNSW索引的方式進行搜尋,此方式搜尋速度較快,但得到的結果是一個近似的結果,一般召回率都可以達到99%以上。
文法
歐氏距離、內積距離,餘弦相似性三種距離相似性的近似的索引檢索使用方式如下:
內積距離和餘弦相似性在v6.3.10.18及以上版本支援,使用時請確保核心版本滿足要求。查看及升級核心版本請參見版本升級。
歐氏距離
SELECT ID, l2_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY <VECTOR_COLUMN_NAME> <-> array[1,2,3...N]::float4[] LIMIT <TOPK>;
內積距離
SELECT ID, inner_product_distance(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY <VECTOR_COLUMN_NAME> <#> array[1,2,3...N]::float4[] LIMIT <TOPK>;
餘弦相似性
SELECT ID, cosine_similarity(<VECTOR_COLUMN_NAME>, array[1,2,3...N]::float4[]) as score FROM <TABLE_NAME> ORDER BY <VECTOR_COLUMN_NAME> <=> array[1,2,3...N]::float4[] LIMIT <TOPK>;
上述三種近似的索引檢索方式中的各欄位說明和精確檢索方式中的欄位說明相同。
如果沒有建立索引,或者FastANN向量檢索引擎相關的核心參數沒有設定時,上述近似的索引檢索將退化為精確檢索。
在使用向量索引時,配合向量查詢的ORDER BY排序方向必須為ASC或不填。如果需要根據距離降序排序,或在使用向量索引後,再根據其他列排序輸出,請將向量查詢作為子查詢,在父查詢中添加需要的ORDER BY語句。
在使用向量索引時,ORDER BY語句必須包含
<->
、<#>
或<=>
等操作符,否則不能有效使用向量索引的加速能力。同時<->
、<#>
或<=>
等操作符必須有對應距離度量的向量索引存在,否則也不能使用向量索引的加速能力。支援的操作符及其用法,請參見建立向量索引。
樣本
以文本知識庫為例,如果我們要通過文本搜尋它的來源文章,那麼我們就可以直接通過向量索引檢索進行尋找,具體SQL如下:
SELECT id, chunk, intime, url FROM chunks
ORDER BY
feature <=> array[10,2.0,…, 1536.0]::real[]
LIMIT 100;
您也可以通過添加EXPLAIN的方式來檢查該查詢的執行計畫。
例如如下檢查執行計畫結果中,可以看到關鍵詞Ann Index Scan
,則表明執行計畫使用的是向量索引。
QUERY PLAN
-------------------------------------------------
Limit
-> Gather Motion 3:1 (slice1; segments: 3)
Merge Key: ((feature <=> $0))
-> Limit
-> Ann Index Scan using feature_idx on chunks
Order By: (feature <=> $0)
Optimizer: Postgres query optimizer
如果您的需求是尋找最近一個月以內的某個文本的來源文章。那麼可以直接通過融合檢索進行尋找,具體SQL如下:
SELECT id, chunk, intime, url FROM chunks WHERE
intime > '2023-04-01' AND intime <= '2023-05-01'
ORDER BY
feature <=> array[10,2.0,…, 1536.0]::real[]
LIMIT 100;
相關參考
向量檢索的SQL最佳化
通過下文樣本介紹向量檢索的SQL最佳化。例如,建立向量表如下,向量索引目前支援一個向量列上建立多個向量索引,可以根據需求建立所需的索引,但一定要保證查詢的SQL和索引能匹配上。如<->
操作符只能使用採用歐氏距離構建的索引;<#>
操作符只能使用採用內積距離構建的索引;<=>
操作符只能使用採用餘弦相似性構建的索引。
CREATE TABLE test_table (
id serial primary key,
feature real[]
) distributed by (id);
CREATE INDEX idx_test_table_feature_l2 ON test_table USING ann(feature) WITH (dim=768, distancemeasure=l2, hnsw_m=64, pq_enable=1);
CREATE INDEX idx_test_table_feature_ip ON test_table USING ann(feature) WITH (dim=768, distancemeasure=ip, hnsw_m=64, pq_enable=1);
CREATE INDEX idx_test_table_feature_cosine ON test_table USING ann(feature) WITH (dim=768, distancemeasure=cosine, hnsw_m=64, pq_enable=1);
當不需要返迴向量距離的score值時,您可以採用以下SQL進行查詢:
-- 按歐氏距離排序的向量檢索。 SELECT id FROM test_table ORDER BY feature <-> array[1,2,3 ... 768]::real[] LIMIT topk; -- 按內積距離排序的向量檢索。 SELECT id FROM test_table ORDER BY feature <#> array[1,2,3 ... 768]::real[] LIMIT topk; -- 按餘弦相似性排序的向量檢索。 SELECT id FROM test_table ORDER BY feature <=> array[1,2,3 ... 768]::real[] LIMIT topk;
當需要返迴向量距離的score值時,您可以利用向量索引返回的排序值進行二次計算得到真實的向量距離score,而避免做完整的向量距離計算,以減少計算耗時。具體SQL如下:
-- 按歐氏距離排序的向量檢索。 SELECT t.id as id, sqrt(t.score) as score FROM (SELECT id,feature <-> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t; -- 按內積距離排序的向量檢索。 SELECT t.id as id, (-1 * t.score) as score FROM (SELECT id, feature <#> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t; -- 按餘弦相似性排序的向量檢索。 SELECT t.id as id, (1.0 - t.score) as score FROM (SELECT id, feature <=> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t;
當需要根據score的範圍進行過濾並返回結果時,您可以使用下面的SQL來實現,該SQL利用了向量索引的排序值進行計算得到最終的score,節省了大量的計算耗時,具體樣本如下:
-- 按歐氏距離排序的向量檢索。 SELECT t.id as id, sqrt(t.score) as score FROM (SELECT id,feature <-> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t WHERE score < 100; -- 按內積距離排序的向量檢索。 SELECT t.id as id, (-1 * t.score) as score FROM (SELECT id, feature <#> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t WHERE score > 10; -- 按餘弦相似性排序的向量檢索。 SELECT t.id as id, (1.0 - t.score) as score FROM (SELECT id, feature <=> array[1,2,3 ... 768]::real[] as score FROM test_table ORDER BY score LIMIT topk) t WHERE score > 0.5;
向量檢索相關的核心參數
向量檢索相關的核心參數 | 功能說明 | 預設值 | 取值範圍 |
fastann.build_parallel_processes | 向量索引並行構建的進程數, 會根據資料庫規格做不同設定。 | 4 | [1, 64] |
fastann.pq_amp | 在使用PQ向量降維的最佳化時,向量檢索的結果集放大係數,可用於召回率測試。 | 10 | [1, 1000] |
fastann.hnsw_max_scan_points | 在HNSW索引中做向量檢索時,最大掃描點個數,用於提前結束搜尋,可用於召回率測試。 | 6000 | [1, 6000000] |
fastann.hnsw_ef_search | 在HNSW索引中做向量檢索時,搜尋候選集大小,可用於召回率測試。 | 400 | [10, 10000] |
上述核心參數可以在會話層級設定生效。