向量搜索基准测试

向量搜索性能评估

在 Qdrant,性能是我们的首要任务。我们始终确保高效利用系统资源,以便为您提供以最低云成本获得最快速、最准确的结果。因此,我们从选择 RustIO 优化无服务器支持二进制量化,到我们的 fastembed 库的所有决策,都是基于这一原则。在本文中,我们将对比 Qdrant 与其他向量搜索引擎的性能表现。

以下是我们设计这些基准测试时遵循的原则

  • 我们进行对比基准测试,这意味着我们关注相对数值而非绝对数值。
  • 我们使用经济实惠的硬件,以便您可以轻松复现结果。
  • 我们在完全相同的机器上运行基准测试,以避免任何可能的硬件偏差。
  • 所有基准测试都是开源的,您可以为此做出贡献并改进它们。
我们测试的场景
  1. 单节点上传与搜索基准测试 - 基准测试
  2. 过滤搜索基准测试 - 基准测试
  3. 内存消耗基准测试 - 即将推出
  4. 集群模式基准测试 - 即将推出

我们的一些实验设计决策在 常见问题解答 (F.A.Q) 部分 中有描述。如果您想讨论任何关于 Qdrant 或这些基准测试的相关内容,请加入我们的 Discord 频道

单节点基准测试

我们使用不同配置的多种向量搜索引擎在各种数据集上进行了基准测试,以检查结果可能存在的差异。这些数据集不仅具有不同的向量维度,而且在使用距离函数方面也有所不同。我们还试图捕捉在针对引擎本身和搜索操作使用不同配置参数时可能产生的差异。

更新时间:2024年1月/6月

下载原始数据:点击此处

观察结果

我们上次测试以来,大多数引擎都有所改进。生活和软件都有权衡,但有些确实表现更好

  • 无论我们选择何种精度阈值和度量标准,Qdrant 在几乎所有场景下都实现了最高的 RPS(每秒请求数)和最低的延迟。 它在其中一个数据集上甚至展示了 4 倍的 RPS 提升。
  • Elasticsearch 在许多情况下速度显著加快,但在索引时间方面非常缓慢。当存储超过 1000 万个 96 维向量时,它可能慢 10 倍!(32 分钟 vs 5.5 小时)
  • Milvus 在索引时间方面是最快的,并保持了良好的精度。然而,当处理更高维度的嵌入或更多的向量数量时,它的 RPS 或延迟表现不如其他引擎。
  • Redis 能够实现良好的 RPS,但主要是在较低精度下。它在单线程下也实现了低延迟,但随着并发请求的增加,其延迟会迅速上升。这种速度提升的部分原因来自其自定义协议。
  • Weaviate 自我们上次测试以来的进步最小。

如何解读结果

  • 选择您想要检查的数据集和度量标准。
  • 选择一个满足您用例的精度阈值。这一点很重要,因为 ANN(近似最近邻)搜索的核心就是在精度和速度之间进行权衡。这意味着在任何向量搜索基准测试中,只有在精度相似时,两个结果才具有可比性。然而,大多数基准测试都忽略了这一关键方面。
  • 表格按所选指标(RPS / 延迟 / p95 延迟 / 索引时间)排序,第一项始终是该类别的胜出者 🏆

延迟与 RPS

在我们的基准测试中,我们测试了实践中出现的两个主要搜索使用场景。

  • 每秒请求数 (RPS):以牺牲单个请求处理时长(即更高延迟)为代价,提供更高的吞吐量。这是 Web 应用程序的典型场景,其中多个用户同时进行搜索。为了模拟这种情况,我们使用多线程并行运行客户端请求,并测量引擎每秒能处理多少个请求。
  • 延迟:对单个请求做出快速响应,而非并行处理大量请求。这是服务器响应时间至关重要的应用程序的典型场景。自动驾驶汽车、制造机器人和其他实时系统就是此类应用的典型示例。为了模拟这种情况,我们使用单线程运行客户端,并测量每个请求所需的时间。

测试数据集

我们的基准测试工具灵感来源于 github.com/erikbern/ann-benchmarks。我们使用以下数据集来测试引擎在 ANN 搜索任务中的性能

数据集# 向量数量维度距离度量
dbpedia-openai-1M-angular100 万1536余弦
deep-image-96-angular1000 万96余弦
gist-960-euclidean100 万960欧几里得距离
glove-100-angular120 万100余弦

设置

Benchmarks configuration

基准测试配置

  • 这是我们本次实验的设置
    • 客户端:8 核 vCPU,16 GiB 内存,64 GiB 存储空间(Azure 云上的 Standard D8ls v5
    • 服务器:8 核 vCPU,32 GiB 内存,64 GiB 存储空间(Azure 云上的 Standard D8s v3
  • Python 客户端将数据上传到服务器,等待所有必要的索引构建完成,然后以配置的线程数执行搜索。我们针对每个引擎的不同配置重复此过程,然后为给定的精度选择最佳配置。
  • 我们在 Docker 中运行所有引擎,并将它们的内存限制为 25GB。这是为了确保公平性,避免某些引擎配置在内存使用上过于贪婪。25GB 的限制是完全合理的,因为即使是为最大的 dbpedia-openai-1M-1536-angular 数据集提供服务,通常也只需要 1M * 1536 * 4字节 * 1.5 = 8.6GB 的 RAM(包括向量 + 索引)。因此,我们决定为所有引擎提供约为需求 3 倍的内存。

请注意,由于 25GB 的内存限制,某些引擎的某些配置在处理部分数据集时发生了崩溃。这就是为什么在选择更高精度阈值时,您可能会看到某些引擎的数据点较少的原因。

过滤搜索基准测试

将过滤器应用于搜索结果引入了全新的复杂性。仅仅将一种算法应用于纯数据已不再足够。通过过滤,问题变成了不同索引的交叉集成

为了衡量不同搜索引擎在此场景下的表现,我们准备了一套带过滤功能的 ANN 基准数据集 - https://github.com/qdrant/ann-filtering-benchmark-datasets

它与 ann-benchmarks 项目中使用的类似,但通过负载元数据和预生成的过滤请求进行了增强。它包括带有各种过滤器(从关键字到地理空间查询)的合成数据集和真实世界数据集。

为什么过滤不是一件简单的事?

并没有多少 ANN 算法兼容过滤。HNSW 是为数不多的几种算法之一,但搜索引擎集成它的方式各不相同

  • 一些引擎使用后过滤 (post-filtering),即在 ANN 搜索之后应用过滤器。这种方式扩展性不佳,因为它要么丢失结果,要么要求在第一阶段处理大量候选者。
  • 另一些引擎使用预过滤 (pre-filtering),这要求将整个数据集的二进制掩码传递给 ANN 算法。这也无法扩展,因为掩码大小会随数据集大小线性增长。

此外,还有一个搜索准确性的问题。如果过滤掉太多的向量,HNSW 图就会变得不连通。

Qdrant 使用了一种不同的方法,既不需要预过滤也不需要后过滤,同时解决了准确性问题。阅读我们关于 可过滤 HNSW 的文章以了解更多信息。

更新时间:2023年2月

下载原始数据:点击此处

过滤结果

从图表中可以看出,主要存在三种模式

  • 速度提升 - 对于某些引擎/查询,过滤搜索比未过滤搜索更快。如果过滤器足够严格,以至于完全避免使用向量索引,就可能发生这种情况。

  • 速度下降 - 一些引擎难以维持高 RPS,这可能与上述为数据集构建过滤掩码的需求有关。

  • 准确性崩溃 - 一些引擎在某些过滤器下准确性大幅下降。这是由于 HNSW 图变得不连通,导致搜索变得不可靠。

Qdrant 避免了所有这些问题,并且由于实现了先进的 查询规划策略,还能从速度提升中获益。

基准测试常见问题 (F.A.Q.)

我们有偏见吗?

可能有的。即使我们努力保持客观,我们也并非所有现有向量搜索引擎的专家。我们构建了 Qdrant,因此对它最了解。正因如此,我们可能遗漏了不同向量搜索引擎中的一些重要调优。

然而,我们尽了最大努力,反复查阅文档,尝试了各种配置组合,并让所有引擎都有平等的脱颖而出机会。如果您认为您能比我们做得更好,我们的基准测试是完全开源的,欢迎贡献代码!

我们测量什么?

在决定使用哪个数据库时,需要考虑多个因素。当然,某些数据库支持不同的功能子集,这些可能是做出决定的关键因素。但总的来说,我们都关心搜索的精度、速度以及实现该目标所需的资源。

有一件重要的事情 - 向量搜索引擎的速度只有在达到相同精度时才具有可比性。否则,它们可以通过提供不准确的结果来最大限度地提高速度因素,这是每个人都想避免的。因此,我们的基准测试结果仅在特定的搜索精度阈值下进行比较。

我们如何选择硬件?

在实验中,我们并不关注指标的绝对值,而是关注不同引擎之间的相对比较。重要的是我们在所有测试中都使用了相同的机器。在启动不同引擎之间,它被完全重置过。

我们选择了一台普通机器,您可以从几乎任何云提供商处轻松租用到。不需要额外的配额或自定义配置。

为什么不与 FAISS 或 Annoy 进行比较?

像 FAISS 这样的库提供了进行向量搜索实验的绝佳工具。但它们离生产环境中的实际使用还很远。如果您在生产中使用 FAISS,在最好的情况下,您不需要实时更新它。在最坏的情况下,您必须围绕它创建自定义包装器来支持 CRUD、高可用性、水平扩展、并发访问等。

有些搜索引擎甚至在底层使用 FAISS,但搜索引擎不仅仅是一个索引算法。

不过,我们确实使用了与著名的 ann-benchmarks 项目相同的基准测试数据集,因此您可以据此对任何实际需求调整预期。

为什么我们决定使用 Python 客户端进行测试

关于运行基准测试的最佳技术,目前尚无共识。您可以自由选择基于 Go、Java 或 Rust 的系统。但我们选择 Python 有两个主要原因

  1. 在生成嵌入时,您很可能使用 Python 和基于 Python 的机器学习框架。
  2. 根据 GitHub 上的关注度,Python 客户端是所有引擎中最受欢迎的客户端之一。

从用户的角度来看,关键在于使用特定库(大多数情况下是 Python 客户端)时感受到的延迟。没有人能够、也不应该仅仅因为使用特定的搜索工具就去重写整个技术栈。这就是为什么我们决定主要关注数据库作者提供的官方 Python 库。这些库在底层可能使用不同的协议,但归根结底,只要数据最终到达目标位置,我们并不关心数据是如何传输的。

闭源 SaaS 平台怎么样?

有些向量搜索引擎仅以 SaaS 形式提供,因此我们无法在与其余系统相同的机器上测试它们。这使得比较不公平。这就是为什么我们完全专注于测试开源向量搜索引擎,以便每个人都可以轻松复现这些基准测试。

这不是最终列表,我们将继续对尽可能多的不同引擎进行基准测试。

如何复现基准测试?

源代码可在 Github 上获取,其中包含一个 README.md 文件,描述了针对特定引擎运行基准测试的过程。

如何贡献?

我们将基准测试开源,是因为我们相信它必须是透明的。我们可能配置错了其中一个引擎,或者只是操作得不够高效。如果您觉得可以帮助我们,请查看我们的 基准测试仓库