本頁說明如何使用 ANN 距離函式,找出近似最近鄰 (ANN) 並查詢向量嵌入。
如果資料集較小,可以使用 K 近鄰 (KNN) 找出確切的 k 個最鄰近向量。不過,隨著資料集擴大,KNN 搜尋的延遲時間和費用也會增加。您可以使用 ANN 找出近似的 k 個最鄰近項目,大幅縮短延遲時間並降低成本。
在 ANN 搜尋中,傳回的 k 個向量並非真正的 k 個最近鄰,因為 ANN 搜尋會計算近似距離,且可能不會查看資料集中的所有向量。有時,系統會傳回幾個不在前 k 個最鄰近向量中的向量。這就是所謂的召回率損失。 可接受的喚回度損失程度取決於用途,但在大多數情況下,為了提升資料庫效能而損失一些喚回度,是可接受的取捨。
如要進一步瞭解 Spanner 支援的近似距離函式,請參閱下列資料庫方言的參考頁面:
- GoogleSQL
- PostgreSQL
查詢向量嵌入
Spanner 會使用向量索引,加快近似最鄰近 (ANN) 向量搜尋的速度。您可以使用向量索引查詢向量嵌入。如要查詢向量嵌入,請先建立向量索引。接著,您可以使用任一概略距離函式尋找 ANN。
使用概略距離函式時的限制包括:
- 近似距離函式必須計算嵌入資料欄和常數運算式 (例如參數或常值) 之間的距離。
- 概略距離函式輸出內容必須在
ORDER BY子句中做為唯一的排序鍵,且ORDER BY後方必須指定LIMIT。 - 查詢必須明確篩除未建立索引的資料列。在大多數情況下,這表示查詢必須包含與向量索引定義相符的
WHERE <column_name> IS NOT NULL子句,除非資料欄已在資料表定義中標示為NOT NULL。
如需詳細限制清單,請參閱約略距離函式參考頁面。
範例
假設 Documents 資料表有 DocContents 位元組資料欄的預先計算文字嵌入 DocEmbedding 資料欄,以及從其他來源填入的 NullableDocEmbedding 資料欄 (可能為空值)。
GoogleSQL
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING(1024),
DocContents BYTES(MAX),
DocEmbedding ARRAY<FLOAT32> NOT NULL,
NullableDocEmbedding ARRAY<FLOAT32>,
WordCount INT64
) PRIMARY KEY (UserId, DocId);
PostgreSQL
CREATE TABLE documents (
user_id bigint not null,
doc_id bigint not null,
author varchar(1024),
doc_contents bytea,
doc_embedding float4[] not null,
nullable_doc_embedding float4[],
word_count bigint,
PRIMARY KEY (user_id, doc_id)
);
如要搜尋最接近 [1.0, 2.0, 3.0] 的 100 個向量,請在約略距離函式中指定下列其中一個搜尋選項:
num_leaves_to_search:要搜尋的葉節點數量。此值必須是正整數。pct_leaves_to_search:要搜尋的葉節點百分比。值必須是介於0.0和100.0之間的雙精度浮點數,且必須包含明確的小數點 (例如10.0)。2025 年 11 月前建立的向量索引可能不支援這項搜尋選項。
您無法在同一個概略距離函式中指定這兩個選項。
選項 1:使用搜尋選項 num_leaves_to_search
GoogleSQL
SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;
選項 2:使用搜尋選項 pct_leaves_to_search
GoogleSQL
SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
options => JSON '{"pct_leaves_to_search": 10.0}')
LIMIT 100
PostgreSQL
SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
options=>jsonb'{"pct_leaves_to_search": 10.0}'
)
LIMIT 100;
如要搜尋最接近 SQL 運算式所產生嵌入的 100 個向量,請使用下列模式。在本例中,查詢會找出與 UserId = 1 和 DocId = 1 嵌入最相似的文件:
GoogleSQL
WITH emb AS (
SELECT DocEmbedding AS value
FROM Documents
WHERE UserId = 1 AND DocId = 1
LIMIT 1
)
SELECT DocId
FROM Documents, emb
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
emb.value, DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT documents.doc_id
FROM
documents,
(
SELECT doc_embedding AS value
FROM documents
WHERE user_id = 1 AND doc_id = 1
LIMIT 1
) vector
WHERE documents.doc_embedding IS NOT NULL
ORDER BY spanner.APPROX_EUCLIDEAN_DISTANCE(documents.doc_embedding,
vector.value, options=>'{"num_leaves_to_search": 10}'::jsonb)
LIMIT 100
如果嵌入資料欄可為空值:
GoogleSQL
SELECT DocId
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
PostgreSQL
SELECT doc_id
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;
在查詢結果中加入距離
在先前的範例中,ANN 距離用於排序查詢結果,但不會顯示在這些結果中。如要將距離新增至結果位置,請將距離函式放在 SELECT 子句中並為其建立別名,然後在 ORDER BY 子句中將該別名做為唯一的排序鍵。
範例
GoogleSQL
SELECT DocId,
APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
options => JSON '{"num_leaves_to_search": 10}') AS distance
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
ORDER BY distance
LIMIT 100
PostgreSQL
SELECT doc_id,
spanner.approx_euclidean_distance(
ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
options=>jsonb'{"num_leaves_to_search": 10}'
) AS distance
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY distance
LIMIT 100;
後續步驟
進一步瞭解 Spanner 向量索引。
進一步瞭解 GoogleSQL 和 PostgreSQL 中的近似距離函式。
進一步瞭解 GoogleSQL
VECTOR INDEX和 PostgreSQLINDEX的索引陳述式。進一步瞭解向量索引最佳做法。
如需使用 ANN 的逐步範例,請參閱「開始使用 Spanner 執行向量搜尋」。