向量檢索
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] |
上述內核參數可以在會話級別設置生效。