Spanner Omni 向量搜索概览

Spanner Omni 中的向量搜索是一项高性能的内置功能,可对高维向量数据进行语义搜索和相似度匹配。通过直接在事务型数据库中存储和索引向量嵌入,Spanner Omni 消除了对单独的向量数据库和复杂的提取、转换、加载 (ETL) 流水线的需求。

本文档中的主题适用于 Spanner Omni,就像它们适用于 Spanner 一样。

借助矢量搜索,您可以将数据表示为数值向量(嵌入),从而找到语义相似的项。Spanner Omni 支持两种主要搜索方法:

  • K 最近邻 (KNN):通过计算查询与数据集中每个向量之间的距离来执行精确搜索。它可提供最高的召回率,但对于大型数据集而言,计算成本可能很高。

  • 近似最近邻 (ANN):使用向量索引在大型数据集中快速查找匹配项。它会牺牲少量准确率(召回率),以换取速度和可伸缩性提升。

与其他功能结合使用时,向量搜索功能尤为强大:

组合 有利
使用 SQL 过滤进行向量搜索 高效地将向量搜索与过滤条件相结合(例如,“查找类别为‘鞋子’且价格低于 100 的类似图片”)。
向量搜索 + 全文搜索 使用倒数排序融合 (RRF) 将语义相似度与关键字精确度相结合,以提高搜索相关性。
向量 + 图表 使用向量搜索在属性图中查找相关入口点(节点),然后遍历复杂的关系。

如需了解详情,请参阅 Spanner 文档中的 Spanner 向量搜索概览。

Spanner Omni 支持使用内置距离函数进行 K 最近邻 (KNN) 搜索。您可以提供向量嵌入作为输入参数,以查找 N 维空间中最接近的向量。

以下距离函数可供使用:

  • COSINE_DISTANCE():衡量两个向量之间夹角的余弦值

  • EUCLIDEAN_DISTANCE():衡量两个向量之间的最短直线距离

  • DOT_PRODUCT():计算夹角的余弦值与向量大小的乘积(非常适合归一化数据)

如需了解详情,请参阅 Spanner 文档中的通过查找 K 最近邻来执行向量相似度搜索。

选择最佳向量距离函数

选择合适的距离函数取决于您的数据和用于生成嵌入的模型。

函数 说明 与相似度增加的关系
点积 计算角度的余弦值与相应向量大小的乘积。 增加
余弦距离 衡量两个向量之间夹角的余弦值(1 - 余弦相似度)。 减少
欧几里得距离 衡量两个向量之间的直线距离。 减少

如果您的嵌入向量已归一化(大小 = 1.0),则 DOT_PRODUCT() 通常是一个高效的选择。对于非归一化数据,请尝试使用 COSINE_DISTANCE() 或 EUCLIDEAN_DISTANCE(),以确定哪种方法能为您的使用情形带来更好的结果。

如需了解详情,请参阅 Spanner 文档中的选择向量距离函数。

近似最近邻 (ANN)

ANN 搜索专为超大型数据集而设计,在这些数据集中,精确的 KNN 搜索会变得过慢或成本过高。它使用向量索引来提供快速结果,但召回率会略有降低。

在没有专用计算工作器的情况下,Spanner Omni 中的 ANN 搜索支持最多包含 100 万个向量的数据集,向量长度最多为 128 维。如果向量的维度更多,则支持的向量数量会相应减少。当您部署工作器来构建向量索引时,Spanner Omni 支持更大的表。如需了解详情,请参阅创建和管理向量索引。

如需执行 ANN 搜索,请使用近似距离函数,例如 APPROX_COSINE_DISTANCE()、APPROX_EUCLIDEAN_DISTANCE() 或 APPROX_DOT_PRODUCT()。这些函数需要:

  • 嵌入列上的现有向量索引。

  • 使用近似距离函数的 ORDER BY 子句。

  • 用于指定结果数量的 LIMIT 子句。

如需了解详情,请参阅 Spanner 文档中的查找近似最近邻 (ANN) 和查询向量嵌入。

创建和管理向量索引

创建向量索引时,请指定嵌入列的 vector_length,并使用 STORING 子句添加其他列以加快过滤速度。

以下示例展示了如何创建向量索引:

CREATE VECTOR INDEX INDEX_NAME
  ON TABLE_NAME(EMBEDDING_COLUMN)
  OPTIONS (distance_type = 'DISTANCE_TYPE', tree_depth = 2, num_leaves = 1000);

如需了解详情,请参阅 Spanner 文档中的创建和管理向量索引。

在超出近似最近邻 (ANN) 中限制的大型表上构建向量索引需要专用计算工作器,以将处理任务从 Spanner Omni 服务器分流。如需了解详情,请参阅部署和管理工作器。

创建向量索引时使用抽样

对于大型数据集(例如包含数千万行或更多行的表),您可以通过指定抽样百分比来缩短向量索引创建时间。在构建初始索引树时,使用 CREATE VECTOR INDEX 语句中的 clustering_sampling_percentage 选项对数据集的子集进行抽样。

一般来说,每个叶节点应至少有 50 个抽样行。例如,对于一个包含 1,000 万行且具有 1 万个叶的数据集,5% 的抽样率 (clustering_sampling_percentage = 5) 会抽取 50 万行,即每个叶抽取 50 行,如下例所示:

CREATE VECTOR INDEX VectorIndex
  ON BaseTable(Embedding)
  WHERE Embedding IS NOT NULL
  OPTIONS (
    tree_depth = 3,
    num_leaves = 10000,
    num_branches = 100,
    leaf_scatter_factor = 32,
    distance_type = 'COSINE',
    min_branch_splits = 10,
    min_leaf_splits = 10,
    clustering_sampling_percentage = 5
  );

与在不进行抽样的完整数据集上构建索引相比,在相同目标召回率下,抽样会增加查询延迟时间和每次查询的 CPU 使用量。提高抽样百分比会增加索引创建时间,但会缩短查询延迟时间并降低每次查询的 CPU 费用。根据可用于创建索引的计算资源,选择一个可在索引创建时间和查询性能之间取得平衡的抽样百分比。

向量索引编制最佳实践

为了保持较高的搜索性能和召回率:

  • 调整索引选项:根据数据大小和性能要求调整 num_leaves 和 num_leaves_to_search。

  • 定期重建:如果向量的分布随时间推移发生显著变化,请重建索引。

  • 有效使用过滤功能:将经常过滤的列存储在索引中,以提高搜索效率。

如需了解详情,请参阅 Spanner 文档中的向量索引编制最佳实践。