向量搜索索引入门#

向量搜索索引通常使用近似方法来权衡结果的准确性和速度,这可以通过降低延迟(端到端单次查询速度)或增加吞吐量(在短时间内可以满足的查询向量数量)来实现。向量搜索索引,特别是那些使用近似方法的索引,与机器学习模型非常密切相关,但它们被优化以实现快速搜索和结果的准确性。

当向量数量非常少时,例如少于10万个向量,使用暴力搜索(也称为平面索引)可能足够快,它会返回精确的结果,但代价是穷举搜索所有可能的邻居。

目标#

本入门指南旨在解决配置向量搜索索引的挑战,但其主要目标是让用户快速上手并获得可接受的结果,以便选择合适的索引类型和一个小而易于管理的调优旋钮,而不是提供全面调优每个超参数的指南。

因此,我们重点关注4种主要的数据大小:

  1. 小型数据集,可能不需要GPU(少于10万向量)

  2. 小型数据集,可能不需要GPU(少于100万向量)

  3. 大型数据集(> 100万向量),目标是以牺牲搜索质量为代价快速创建索引

  4. 大型数据集,优先考虑高质量,即使以快速索引创建为代价

与其他机器学习算法类似,向量搜索索引通常有一个训练步骤——即构建索引——和一个推理——或搜索步骤。超参数也往往被分为构建参数和搜索参数。

虽然并非总是如此,但通常观察到一个普遍趋势,即搜索速度随着质量的提高而降低。索引构建性能也往往如此,尽管不同的算法在构建时间、质量和搜索时间之间有不同的关系。重要的是要理解没有免费的午餐,因此每种索引类型总是会有权衡。

质量的定义#

当我们说索引的质量时,我们指的是什么?在机器学习术语中,我们使用召回率来衡量这一点,召回率有时与准确性互换使用,尽管这两者是略有不同的度量。在向量搜索中使用召回率时,基本上意味着“在我的所有结果中,哪些结果会被包含在精确结果中?”在向量搜索中,目标是找到一些与给定查询向量最接近的向量,因此召回率往往比准确性更宽松,仅基于集合包含进行区分,而不是基于精确的有序列表匹配,后者更接近准确性度量。

选择向量搜索索引#

许多向量搜索算法通过将向量空间分割成更小的部分来提高可扩展性,同时减少距离计算的数量,这通常通过使用聚类、哈希、树和其他技术来实现。另一种流行的技术是减少空间的宽度或维度,以降低计算每个距离的成本。

小型数据集(少于10万向量)#

这些数据集非常小,GPU是否能够提供任何价值是值得怀疑的。如果维度也相对较小(< 1024),你可以直接在CPU上使用暴力搜索或HNSW并获得出色的性能。如果维度相对较大(1536, 2048, 4096),你应该考虑使用HNSW。如果构建时间性能至关重要,你应该考虑使用CAGRA来构建图并将其转换为HNSW图进行搜索(此功能目前存在于独立的cuVS/RAFT库中,并将很快添加到Milvus中)。IVF平面索引在这里也是一个很好的候选方案,因为它可以通过分区向量空间来减少搜索空间,从而提高搜索性能。

可能不需要GPU的小数据集(少于100万向量)#

对于较小的维度,例如1024或以下,您可以考虑在GPU上使用暴力(即平面)索引,并获得非常好的搜索性能和精确结果。您也可以在CPU上使用基于图的索引,如HNSW,或在GPU上使用CAGRA。如果构建时间至关重要,您甚至可以在GPU上构建CAGRA图,并将其转换为CPU上的HNSW图。

对于更大的维度(1536、2048、4096),在更高质量的搜索设置下,使用HNSW时您将开始看到构建时间性能下降,因此更明显地看出构建CAGRA图可能更有用。

大型数据集(大于100万向量),目标是以牺牲搜索质量为代价快速创建索引#

对于快速摄入且搜索质量稍低(召回率85%及以上)可接受的情况,IVF(倒排文件索引)方法非常有用,因为它们可以非常快速地构建,并且仍然具有可接受的搜索性能。IVF-flat索引将向量划分为一定数量的簇(由用户指定为n_lists),在搜索时,将对每个查询向量使用暴力搜索方法搜索一定数量的最近簇(由n_probes定义)。

IVF-PQ 与 IVF-flat 类似,主要区别在于向量使用有损产品量化压缩进行压缩,因此索引在 GPU 上的占用空间可以小得多。通常建议将 n_lists 设置为 sqrt(n_vectors),并将 n_probes 设置为 n_lists 的某个百分比(例如 1%、2%、4%、8%、16%)。由于 IVF-PQ 是一种有损压缩,可以通过最初增加邻居数量(通过某个倍数因子)并使用原始向量计算精确距离来执行细化步骤,最终将邻域缩小到大小 k。即使是 2 倍的细化(最初查询 k*2)也可以非常有效地弥补 PQ 压缩导致的召回率损失,但这确实需要保留原始向量(考虑到许多数据库无论如何都会存储原始向量)。

大型数据集(大于100万向量),目标是以牺牲快速索引创建为代价实现高质量搜索#

通过权衡索引创建性能,可以构建一个极其高质量的搜索模型。通常,所有向量搜索索引类型都有与搜索精度直接相关的超参数,因此可以调整这些参数以提高召回率。不幸的是,这也会显著增加索引构建时间并降低搜索吞吐量。这里的技巧是找到能够以最低延迟或最高吞吐量实现最佳召回率的最快构建时间。

至于推荐的索引类型,基于图的算法如HNSW和CAGRA往往能够很好地扩展到更大的数据集,同时在质量方面具有优越的搜索性能。挑战在于,基于图的索引需要学习图,因此,正如本节副标题所暗示的,它们往往比其他选项构建得更慢。在GPU上使用CAGRA算法可以显著减少构建时间,同时与在CPU上搜索相比,具有更高的吞吐量(和更低的延迟)。目前,在GPU上使用CAGRA的缺点是它需要图和原始向量都适合GPU内存。可以通过在GPU上构建CAGRA图并将其转换为HNSW,以在CPU上进行高质量(且速度适中)的搜索,来达到一个折衷方案。

调优和超参数优化#

不幸的是,对于大型数据集,在整个数据集上进行超参数优化并不总是可行的。然而,可以在较小的子集上执行超参数优化,并找到应该能够很好地推广到整个数据集的合理可接受的参数。通常,这种超参数优化将需要使用精确方法(如暴力破解)在子集上计算真实值,然后使用它来评估对随机采样向量的多次搜索。

全面的超参数优化可能并不总是必要的——例如,一旦你在一个子集上构建了一个真实数据集,很多时候你可以从使用默认构建参数构建索引开始,然后尝试不同的搜索参数,直到获得所需的质量和搜索性能。对于可能达到数TB的大规模索引,你也可以采取子采样的方法,比如1000万个向量,训练一个索引,然后从那里调整搜索参数。虽然可能会有一些小的误差,但所选的构建/搜索参数应该能够很好地推广到构建本地分区索引的数据库。

向量搜索索引类型概述#

名称

权衡

最适合用于…

暴力搜索(也称为平面搜索)

精确搜索但需要穷举距离计算

小型数据集(< 100k 向量)

IVF-Flat

将向量空间分区以减少暴力搜索的距离计算,但会牺牲召回率

小型数据集(<1M向量)或大型数据集(>1M向量),其中快速索引构建时间优先于质量。

IVF-PQ

将产品量化添加到IVF-Flat中,以牺牲召回率为代价实现扩展

大型数据集(>>1M向量),其中快速索引构建优先于质量

HNSW

显著减少距离计算,但以更长的构建时间为代价

小型数据集(<1M向量)或大型数据集(>1M向量),其中搜索质量和速度优先于索引构建时间

CAGRA

显著减少了距离计算,但以更长的构建时间为代价(尽管构建时间比HNSW有所改善)

适用于大型数据集(>>1M向量),其中搜索质量和速度优先于索引构建时间,但索引构建时间仍然重要。

CAGRA 构建 + HNSW 搜索

(即将在 Milvus 中推出)

显著减少距离计算并提高构建时间,但以更高的搜索延迟/更低的吞吐量为代价。 适用于大型数据集(>>1M 向量),其中索引构建时间和搜索质量很重要,但 GPU 资源有限且搜索延迟不重要。