查找近似最近邻 (ANN) 和查询向量嵌入

本页介绍了如何使用 ANN 距离函数查找近似最近邻 (ANN) 并查询向量嵌入。

如果数据集较小,您可以使用 K 最近邻 (KNN) 来查找精确的 k 最近邻向量。不过,随着数据集的增大,KNN 搜索的延迟时间和费用也会增加。您可以使用 ANN 查找近似 k 最近邻,从而显著缩短延迟时间、降低成本。

在 ANN 搜索中,返回的 k 个向量并非真正的 Top-k 最近邻,因为 ANN 搜索会计算近似距离,并且可能不会查看数据集中的所有向量。有时,系统会返回一些并非前 k 个最邻近项的向量。这称为“召回率损失”。您可以接受的召回率损失程度取决于具体用例,但在大多数情况下,牺牲一点召回率来换取数据库性能的提升是可接受的权衡。

如需详细了解 Spanner 中支持的近似距离函数,请参阅以下 GoogleSQL 参考页面:

查询向量嵌入

Spanner 通过使用向量索引来加快近似最近邻 (ANN) 向量搜索的速度。您可以使用向量索引来查询向量嵌入。如需查询向量嵌入,您必须先创建向量索引。然后,您可以使用这三个近似距离函数中的任意一个来查找 ANN。

使用近似距离函数时,存在以下限制:

  • 近似距离函数必须计算嵌入列与常量表达式(例如,参数或字面量)之间的距离。
  • 近似距离函数输出必须在 ORDER BY 子句中用作唯一排序键,并且必须在 ORDER BY 后指定 LIMIT
  • 查询必须明确过滤掉未编入索引的行。在大多数情况下,这意味着查询必须包含与向量索引定义匹配的 WHERE <column_name> IS NOT NULL 子句,除非该列已在表定义中标记为 NOT NULL

如需查看详细的限制列表,请参阅近似距离函数参考页面

示例

假设有一个 Documents 表,其中包含一个 DocEmbedding 列(其中包含来自 DocContents 字节列的预计算文本嵌入)和一个 NullableDocEmbedding 列(其中包含来自其他来源的数据,可能为 null)。

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);

如需搜索与 [1.0, 2.0, 3.0] 最接近的 100 个向量,请执行以下操作:

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

如果嵌入列可以为 null:

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

后续步骤