向量搜索索引与向量数据库#
本指南提供了关于向量搜索索引与完整向量数据库之间差异的信息。有关选择和配置向量搜索索引的更多信息,请参阅我们的选择和配置索引指南
向量数据库索引与传统数据库索引之间的主要区别之一是,向量搜索通常使用近似方法来以结果的准确性换取速度。因此,虽然许多成熟的数据库提供了调整其索引以实现更好性能的机制,但如果向量数据库索引没有在性能调整之外为合理的搜索质量进行调整,它们可能会返回完全无用的结果。这是因为向量数据库索引与机器学习模型的关系比与传统数据库索引的关系更为密切。
向量数据库和向量搜索索引之间有什么区别?#
向量搜索本身指的是在索引中围绕一组给定的查询向量找到最接近的向量的目标。在最底层,向量搜索索引只是机器学习模型,它们具有构建、搜索和召回性能,可以根据算法和各种超参数进行权衡。
单独的向量搜索索引被认为是构建块,它们本身并不被视为一个成熟的向量数据库。向量数据库提供了更多的生产级功能,这些功能通常结合向量搜索算法和其他流行的数据库设计技术,以增加重要的能力,如持久性、容错性、垂直可扩展性、分区容错性和水平可扩展性。
在向量数据库的世界中,有一些专门构建的数据库,它们主要专注于向量搜索,但也可能提供一些更通用数据库的小功能,比如能够跨向量和元数据执行混合搜索。许多通用数据库,包括关系型数据库和nosql/文档数据库,也开始添加一流的向量类型。
那么,这一切对你意味着什么?有时,一个简单的独立向量搜索索引就足够了。通常它们可以被训练并序列化到文件中以供以后使用,并且经常提供在搜索期间过滤特定向量的能力。有时它们甚至提供一种机制来扩展到利用多个GPU,例如,但它们通常就到此为止——并建议要么使用你自己的分布式系统(如Spark或Dask),要么使用一个成熟的向量数据库来扩展。
FAISS 和 cuVS 是独立的向量搜索库的示例,它们与机器学习库的关系更为密切,而不是与完整的数据库。Milvus 是一个专用向量数据库的示例,而 Elastic、MongoDB 和 OpenSearch 是增加了向量搜索功能的通用数据库的示例。
向量数据库如何使用向量搜索?#
在向量数据库的上下文中,向量搜索索引主要有两种使用方式,了解你正在使用的是哪一种非常重要,因为它可能会影响参数相对于数据的行为。
许多向量搜索算法通过将向量空间分割成更小的部分来提高可扩展性,同时减少距离计算的数量,这通常通过使用聚类、哈希、树和其他技术来实现。另一种流行的技术是减少空间的宽度或维度,以降低计算每个距离的成本。相比之下,数据库通常会对数据进行分区,但可能只是为了改善诸如IO性能、分区容错性或扩展性等方面,而不考虑最终将用于向量搜索的底层数据分布。
这引导我们遇到了向量数据库中的两个核心架构设计:
本地分区向量搜索索引#
大多数数据库遵循这种设计,向量通常首先写入预写日志以确保持久性。在写入一定数量的向量后,预写日志变为不可变,并可能与其他预写日志合并,最终转换为新的向量搜索索引。
搜索通常在每个本地分区的索引上进行,并将结果合并。在设置超参数时,只需要考虑本地向量搜索索引,尽管相同的超参数将在所有本地分区中使用。因此,例如,如果您已经摄入了1亿个向量,但每个分区只包含大约1000万个向量,则索引的大小只需要考虑其本地的1000万个向量。索引中的向量数量等细节很重要,例如,在设置基于IVF(倒排文件索引)方法的聚类数量时,如下所述。
全局分区向量搜索索引#
一些特殊用途的向量数据库遵循这种设计,例如雅虎的Vespa和谷歌的Spanner。一旦有足够的向量,就会训练一个全局索引来预先分区整个数据库的向量(通常这些数据库的规模足够大,最初会引导大量向量,因此避免了冷启动问题)。摄入的向量首先通过全局索引(例如聚类,但也使用了基于树和图的方法)来确定它们属于哪个分区,然后向量被直接写入该分区。各个分区可以包含图、树或简单的IVF列表。这些类型的索引已经能够扩展到数千亿到数万亿个向量,并且由于分区本身通常基于邻域而不是像本地分区架构那样基于均匀随机分布的向量,因此可以根据系统的需求将分区分组或有意分离,以支持局部搜索或负载平衡。
为全局分区索引设置超参数的挑战在于,它们需要考虑整个向量集,因此全局索引的超参数通常考虑数据库中的所有向量,而不是任何本地分区。
当然,上述两种方法也可以结合使用(例如,训练一个全局的“粗略”索引,然后在每个全局索引中创建局部向量搜索索引),但据我所知,目前还没有这样的架构实现这种模式。
当今在向量数据库中使用GPU的一个挑战是,生成的向量索引需要适应可用GPU的内存以实现快速搜索。也就是说,目前还没有一种有效的机制来卸载或交换GPU索引,以便它们可以从磁盘或主机内存中缓存。我们正在研究实现这一点的机制,并利用GPUDirect Storage和GPUDirect RDMA等技术来进一步提高IO性能。
调优和超参数优化#
不幸的是,对于大型数据集,在整个数据集上进行超参数优化并不总是可行的,而这正是本地分区向量搜索索引的优势所在,因为你可以将较大索引的每个较小部分视为数据集中总向量的均匀随机样本。这意味着可以在较小的子集上执行超参数优化,并找到应该能够很好地推广到整个数据集的合理可接受的参数。通常,这种超参数优化将需要使用精确方法(如暴力搜索)在子集上计算真实值,然后使用它来评估对随机采样向量的多次搜索。
全面的超参数优化可能并不总是必要的——例如,一旦你在一个子集上构建了一个真实数据集,很多时候你可以从使用默认构建参数构建索引开始,然后尝试不同的搜索参数,直到获得所需的质量和搜索性能。对于可能达到数TB的大规模索引,你也可以采取子采样的方法,比如1000万个向量,训练一个索引,然后从那里调整搜索参数。虽然可能会有一些小的误差,但所选的构建/搜索参数应该能够很好地推广到构建本地分区索引的数据库。
请参考我们的调优指南,了解更多信息及示例,了解如何根据您的需求高效且自动地调整您的向量搜索索引。