通过查找 K 最近邻项在 Spanner 中执行相似向量搜索

本页面介绍了如何在 Google Cloud 中执行相似性向量搜索, Spanner(使用余弦距离、欧几里得距离和点) 产品向量函数来查找 K 最近邻。在阅读本页内容之前, 请务必了解以下概念:

  • 欧几里得距离: 测量两个向量之间的最短距离。
  • 余弦距离: 测量两个向量之间角度的余弦。
  • 点积:计算 角度的余弦与对应向量的乘积 震级。如果您知道数据集中的所有向量嵌入 那么可以使用 DOT_PRODUCT() 作为距离函数。
  • K 最近邻 (KNN): 一种用于解决分类问题的监督式机器学习算法, 回归问题。

您可以使用矢量距离函数执行 K 最近邻 (KNN)。 向量搜索,用于相似性搜索或检索增强 。Spanner 支持 COSINE_DISTANCE()EUCLIDEAN_DISTANCE()DOT_PRODUCT() 函数,它们作用于矢量 用于找出输入嵌入的 KNN。

例如,在生成并保存可操作的 Spanner 之后 将数据作为向量嵌入进行转换,然后 在查询中提供这些向量嵌入作为输入参数, N 维空间中最接近的向量,以搜索 相关项。

所有三个距离函数都采用 vector1vector2 参数, 类型为array<>,必须由相同的尺寸组成,且具有 相同长度的如需详细了解这些函数,请参阅:

示例

以下示例展示了 KNN 搜索、KNN 对分区数据的搜索,以及 将二级索引与 KNN 结合起来使用。

示例均使用 EUCLIDEAN_DISTANCE()。您还可以使用 COSINE_DISTANCE().此外,如果数据集中的所有向量嵌入 标准化,因此可以使用 DOT_PRODUCT() 作为距离函数。

假设有一个 Documents 表,其中包含预先计算的列 (DocEmbedding) 文本嵌入。DocContents

GoogleSQL

CREATE TABLE Documents (
UserId       INT64 NOT NULL,
DocId        INT64 NOT NULL,
Author       STRING(1024),
DocContents  BYTES,
DocEmbedding ARRAY<FLOAT32>
) PRIMARY KEY (UserId, DocId);

PostgreSQL

CREATE TABLE Documents (
UserId       bigint primary key,
DocId        bigint primary key,
Author       varchar(1024),
DocContents  bytea,
DocEmbedding float4[]
);

假设“棒球,但不是职业棒球”的输入嵌入 是数组 [0.3, 0.3, 0.7, 0.7],您可以找到前五个最接近的文档 结果替换为以下查询:

GoogleSQL

SELECT DocId, DocEmbedding FROM Documents
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;

PostgreSQL

SELECT DocId, DocEmbedding FROM Documents
ORDER BY spanner.euclidean_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;

本示例的预期结果:

Documents
+---------------------------+-----------------+
| DocId                     | DocEmbedding    |
+---------------------------+-----------------+
| 24                        | [8, ...]        |
+---------------------------+-----------------+
| 25                        | [6, ...]        |
+---------------------------+-----------------+
| 26                        | [3.2, ...]      |
+---------------------------+-----------------+
| 27                        | [38, ...]       |
+---------------------------+-----------------+
| 14229                     | [1.6, ...]      |
+---------------------------+-----------------+

示例 2:KNN 对分区数据进行搜索

上述示例中的查询可通过向 WHERE 子句将矢量搜索限制为数据的子集。常见 搜索分区数据, 特定的 UserId

GoogleSQL

SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
ARRAY<FLOAT32>[0.3, 0.3, 0.7, 0.8])
LIMIT 5;

PostgreSQL

SELECT UserId, DocId, DocEmbedding FROM Documents
WHERE UserId=18
ORDER BY spanner.euclidean_distance(DocEmbedding,
'{0.3, 0.3, 0.7, 0.8}'::float4[])
LIMIT 5;

本示例的预期结果:

Documents
+-----------+-----------------+-----------------+
| UserId    | DocId           | DocEmbedding    |
+-----------+-----------------+-----------------+
| 18        | 234             | [12, ...]       |
+-----------+-----------------+-----------------+
| 18        | 12              | [1.6, ...]      |
+-----------+-----------------+-----------------+
| 18        | 321             | [22, ...]       |
+-----------+-----------------+-----------------+
| 18        | 432             | [3, ...]        |
+-----------+-----------------+-----------------+

示例 3:在二级索引范围上执行 KNN 搜索

如果您使用的 WHERE 子句过滤条件不是表主键的一部分, 那么您可以创建二级索引来加速操作 仅索引扫描

GoogleSQL

CREATE INDEX DocsByAuthor
ON Documents(Author)
STORING (DocEmbedding);

SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY EUCLIDEAN_DISTANCE(DocEmbedding,
   <embeddings for "book about the time traveling American">)
LIMIT 5;

PostgreSQL

CREATE INDEX DocsByAuthor
ON Documents(Author)
INCLUDE (DocEmbedding);

SELECT Author, DocId, DocEmbedding FROM Documents
WHERE Author="Mark Twain"
ORDER BY spanner.euclidean_distance(DocEmbedding,
   <embeddings for "that book about the time traveling American">)
LIMIT 5;

本示例的预期结果:

Documents
+------------+-----------------+-----------------+
| Author     | DocId           | DocEmbedding    |
+------------+-----------------+-----------------+
| Mark Twain | 234             | [12, ...]       |
+------------+-----------------+-----------------+
| Mark Twain | 12              | [1.6, ...]      |
+------------+-----------------+-----------------+
| Mark Twain | 321             | [22, ...]       |
+------------+-----------------+-----------------+
| Mark Twain | 432             | [3, ...]        |
+------------+-----------------+-----------------+
| Mark Twain | 375             | [9, ...]        |
+------------+-----------------+-----------------+

后续步骤