Spanner Omni 中的向量搜索是一项高性能的内置功能,可对高维向量数据进行语义搜索和相似度匹配。通过直接在事务型数据库中存储和索引向量嵌入,Spanner Omni 消除了对单独的向量数据库和复杂的提取、转换、加载 (ETL) 流水线的需求。
本文档中的主题适用于 Spanner Omni,就像它们适用于 Spanner 一样。
向量搜索的工作原理
借助矢量搜索,您可以将数据表示为数值向量(嵌入),从而找到语义相似的项。Spanner Omni 支持两种主要搜索方法:
K 最近邻 (KNN):通过计算查询与数据集中每个向量之间的距离来执行精确搜索。它可提供最高的召回率,但对于大型数据集而言,计算成本可能很高。
近似最近邻 (ANN):使用向量索引在大型数据集中快速查找匹配项。它会牺牲少量准确率(召回率),以换取速度和可伸缩性提升。
与其他功能结合使用时,向量搜索功能尤为强大:
| 组合 | 有利 |
|---|---|
| 使用 SQL 过滤进行向量搜索 | 高效地将向量搜索与过滤条件相结合(例如,“查找类别为‘鞋子’且价格低于 100 的类似图片”)。 |
| 向量搜索 + 全文搜索 | 使用倒数排序融合 (RRF) 将语义相似度与关键字精确度相结合,以提高搜索相关性。 |
| 向量 + 图表 | 使用向量搜索在属性图中查找相关入口点(节点),然后遍历复杂的关系。 |
如需了解详情,请参阅 Spanner 文档中的 Spanner 向量搜索概览。
执行 K 最近邻搜索
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 搜索
如需执行 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 文档中的向量索引编制最佳实践。