TLDR: Elasticsearch 的速度高达 OpenSearch 的 12 倍 - 我们在 Elastic 收到了大量关于 Elasticsearch 和 OpenSearch 性能差异的询问,特别是在语义搜索/向量搜索方面。为了解决这个问题,我们进行了性能测试,以提供一个清晰的数据驱动比较。结果显示,Elasticsearch 的向量搜索速度高达 OpenSearch 的 12 倍,因此需要的计算资源更少。这反映了 Elastic 在巩固 Lucene 作为最佳向量数据库方面的专注,适用于搜索和检索用例。
向量搜索正在改变我们进行相似性搜索的方式,尤其是在 AI 和机器学习领域。随着向量嵌入模型的广泛应用,能够高效地搜索数百万高维向量变得至关重要。
在推动向量数据库的发展方面,Elastic 和 OpenSearch 采取了明显不同的方法。Elastic 大力优化了 Apache Lucene 和 Elasticsearch,使其成为向量搜索应用的首选。而 OpenSearch 则拓宽了其关注点,整合了其他向量搜索实现,探索了 Lucene 之外的领域。我们对 Lucene 的专注是战略性的,使我们能够在 Elasticsearch 中提供高度集成的支持,从而增强每个组件的功能。
这篇博客详细比较了 Elasticsearch 8.14 和 OpenSearch 2.14 在不同配置和向量引擎下的性能。在这次性能分析中,Elasticsearch 被证明是向量搜索操作的优越平台,未来的功能将进一步扩大这种差距。在所有基准测试中,Elasticsearch 的性能平均提高了 2 倍至 12 倍。测试涉及不同数量和维度的向量,包括 so_vector
(2百万向量,768维), openai_vector
(2.5百万向量,1536维) 和 dense_vector
(1千万向量,96维),所有数据集和 Terraform 脚本都在此存储库中。
博客中的结果补充了之前发布并由第三方验证的研究结果,这些研究显示 Elasticsearch 在文本查询、排序、范围、日期直方图和术语过滤等常见搜索分析操作中比 OpenSearch 快 40%–140%。现在我们可以添加另一个区分点:向量搜索。
我们在四个向量数据集上的基准测试涉及近似 KNN 和精确 KNN 搜索,考虑了不同的大小、维度和配置,共计 40.189.820
次未缓存的搜索请求。结果显示,Elasticsearch 的向量搜索速度高达 OpenSearch 的 12 倍,因此需要的计算资源更少。
图 1:Elasticsearch 和 OpenSearch 中不同组合的 ANN 和精确 KNN 任务组。
像 knn-10-100
这样的组意味着 KNN 搜索,其中 𝑘 表示要检索的最近邻向量数,𝑛 表示在每个段中要检索的候选向量数。更多候选向量可以提高准确性,但需要更多计算资源。
我们还测试了不同的量化技术并利用了引擎特定的优化,下面提供了每个任务和向量引擎的详细结果。
在处理不同数据集和用例时,向量搜索的正确方法会有所不同。本文中的所有 knn-*
任务使用近似 KNN,而 script-score-*
则指的是精确 KNN。但它们之间有什么区别,为什么重要?
简单来说,如果你处理的是较大的数据集,优选的方法是近似 K-最近邻(ANN),因为它具有更好的扩展性。而对于需要过滤过程的较小数据集,精确 KNN 方法则更理想。
精确 KNN 使用蛮力方法,计算一个向量与数据集中每个向量之间的距离,然后根据这些距离找到最近的 𝑘 个向量。虽然这种方法保证了精确匹配,但对于大型高维数据集来说扩展性较差。然而,在许多情况下,精确 KNN 是必需的:
因此,精确 KNN 确保基于向量相似性的最终排序和推荐是精确的,并且符合用户偏好。
近似 KNN(ANN)则采用某些方法使数据搜索比精确 KNN 更快更高效,特别是在大型高维数据集中。它不使用蛮力方法,而是利用某些技术来高效地重构数据集中的可搜索向量索引和维度。虽然这可能导致轻微的不准确性,但显著提高了搜索过程的速度,使其成为处理大数据集的有效替代方案。
本文中的所有 knn-*
任务使用近似 KNN,而 script-score-*
则指的是精确 KNN。
虽然 Elasticsearch 和 OpenSearch 在 BM25 搜索操作的 API 方面相似,因为后者是前者的一个分支,但在向量搜索方面则不尽相同。OpenSearch 采用了不同于 Elasticsearch 的算法,通过引入 nmslib
和 faiss
这两个引擎,除了 lucene
外,每个都有其特定的配置和限制(例如,OpenSearch 中的 nmslib
不允许过滤,这是许多用例的必要功能)。
这三个引擎都使用了层次导航小世界(HNSW)算法,它对近似最近邻搜索非常高效,尤其适用于高维数据。需要注意的是,faiss
还支持另一种算法 ivf
,但由于它需要对数据集进行预训练,因此我们将重点放在 HNSW 上。HNSW 的核心思想是将数据组织成多个连接图层,每层表示数据集的不同粒度。搜索从最高层(最粗略的视图)开始,逐层向下进行,直到到达基础层。
为了确保公平的测试环境,两个搜索引擎在相同条件下进行了测试。方法与之前发布的性能比较类似,为 Elasticsearch、OpenSearch 和 Rally 设置了专用节点池。提供的Terraform 脚本可以在 Kubernetes 集群中配置以下内容:
e2-standard-32
机器(128GB RAM 和 32 个 CPU)e2-standard-32
机器(128GB RAM 和 32 个 CPU)t2a-standard-16
机器(64GB RAM 和 16 个 CPU)每个“轨道”(或测试)在每种配置下运行 10 次,包括不同的引擎、配置和向量类型。每个轨道的任务重复 1000 到 10000 次,具体取决于轨道。如果轨道中的一个任务由于网络超时而失败,那么所有任务都会被丢弃,因此所有结果都代表顺利完成的轨道。所有测试结果都经过统计验证,确保改进不是偶然的。
为什么使用 99 百分位数而不是平均延迟进行比较?考虑一个假设的例子,一个特定社区的房屋平均价格。平均价格可能表明该地区昂贵,但仔细检查后可能发现大多数房屋的价值低得多,只有少数豪宅抬高了平均价格。这说明平均价格可能无法准确代表该地区的房价全貌。这类似于检查响应时间,平均值可能掩盖关键问题。
lucene
,版本 9.10faiss
nmslib
hnsw
int8_hnsw
(带有自动 8 位量化的 HNSW:链接)sq_fp16 hnsw
(带有自动 16 位量化的 HNSW:链接)如你所知,Lucene 是一个用 Java 编写的高性能文本搜索引擎库,作为 Elasticsearch、OpenSearch 和 Solr 等许多搜索平台的基础。Lucene 的核心是将数据组织成段,这些段本质上是自包含的索引,使 Lucene 能够更高效地执行搜索。因此,当你向任何基于 Lucene 的搜索引擎发出搜索请求时,你的搜索将最终在这些段中执行,无论是顺序执行还是并行执行。
OpenSearch 引入了并发段搜索作为可选标志,默认情况下不使用,必须使用特殊的索引设置 index.search.concurrent_segment_search.enabled
启用,详见此处,并有一些限制。
另一方面,Elasticsearch 开箱即用地并发搜索段,因此本文中的比较将考虑不同的向量引擎和向量类型,以及不同的配置:
现在,让我们深入了解每个测试向量数据集的详细结果:
从最简单的轨道开始,但也是维度最大的,openai_vector——使用 NQ 数据集,通过 OpenAI 的 text-embedding-ada-002 模型生成的嵌入丰富。它是最简单的,因为它只测试近似 KNN 并且只有 5 个任务。它测试独立(无索引)和与索引同时进行,并使用单个客户端和 8 个并发客户端。
平均 p99 性能如下所示:
在此我们观察到,Elasticsearch 在 k:10 和 n:100 的情况下,在进行向量搜索和索引(即读+写)时比 OpenSearch 快 3 倍到 8 倍,在无索引的情况下则快 2 倍到 3 倍。在 k:100 和 n:1000 的情况下(standalone-search-knn-100-1000-single-client 和 standalone-search-knn-100-1000-multiple-clients),Elasticsearch 比 OpenSearch 平均快 2 倍到 7 倍。
详细结果显示了具体情况和比较的向量引擎:
knn-recall-10-100 | knn-recall-100-1000 | |
---|---|---|
Elasticsearch-8.14.0@lucene-hnsw | 0.969485 | 0.995138 |
Elasticsearch-8.14.0@lucene-int8_hnsw | 0.781445 | 0.784817 |
OpenSearch-2.14.0@lucene-hnsw | 0.96519 | 0.995422 |
OpenSearch-2.14.0@faiss | 0.984154 | 0.98049 |
OpenSearch-2.14.0@faiss-sq_fp16 | 0.980012 | 0.97721 |
OpenSearch-2.14.0@nmslib | 0.982532 | 0.99832 |
在 dense_vector 中,1000 万个向量和 96 个维度。它基于 Yandex DEEP1B 图像数据集。数据集是从名为 learn.350M.fbin
的“示例数据”文件中创建的第一个 1000 万个向量。搜索操作使用“查询数据”文件 query.public.10K.fbin
中的向量。
在这个数据集上,Elasticsearch 和 OpenSearch 的表现都非常好,特别是在强制合并之后,这通常在只读索引上进行,类似于对索引进行碎片整理,以便在单个“表”上进行搜索。
每个任务预热 100 次请求,然后测量 1000 次请求
在近似 KNN 中,Elasticsearch 和 OpenSearch 的表现都很好。当索引合并(即只有一个段)时,在 knn-search-100-1000-force-merge 和 knn-search-10-100-force-merge 中,OpenSearch 使用 nmslib
和 faiss
时表现更好,尽管它们都在 15 毫秒左右,且都非常接近。
然而,当索引有多个段(即索引接收更新的典型情况)时,在 knn-search-10-100 和 knn-search-100-1000 中,Elasticsearch 保持延迟约为 ~7 毫秒和 ~16 毫秒,而所有其他 OpenSearch 引擎都较慢。
此外,在索引同时进行搜索和写入时(knn-search-100-1000-concurrent-with-indexing),Elasticsearch 将延迟保持在 15 毫秒以下(为 13.8 毫秒),比开箱即用的 OpenSearch 快了近 4 倍(49.3 毫秒),即使启用了并发段搜索(17.9 毫秒)时仍然更快,但差距不显著。
对于精确 KNN,差异更大:Elasticsearch 比 OpenSearch 快 6 倍(~260 毫秒 vs ~1600 毫秒)。
knn-recall-10-100 | knn-recall-100-1000 | |
---|---|---|
Elasticsearch-8.14.0@lucene-hnsw | 0.969843 | 0.996577 |
Elasticsearch-8.14.0@lucene-int8_hnsw | 0.775458 | 0.840254 |
OpenSearch-2.14.0@lucene-hnsw | 0.971333 | 0.996747 |
OpenSearch-2.14.0@faiss | 0.9704 | 0.914755 |
OpenSearch-2.14.0@faiss-sq_fp16 | 0.968025 | 0.913862 |
OpenSearch-2.14.0@nmslib | 0.9674 | 0.910303 |
这个 轨道,so_vector
,来源于 2022 年 4 月 21 日下载的 StackOverflow 帖子的 dump。它只包含问题文档——所有表示答案的文档都被删除了。每个问题标题都使用句子转换器模型 multi-qa-mpnet-base-cos-v1编码成一个向量。该数据集包含前 200 万个问题。
与之前的轨道不同,这里的每个文档除了向量外还包含其他字段,以支持近似 KNN 过滤和混合搜索等功能。由于nmslib 不支持过滤,在此测试中 OpenSearch 中的 nmslib
明显缺席。
每个任务预热 100 次请求,然后测量 100 次请求。请注意,为了简化,任务已分组,因为测试包含 16 种搜索类型 * 2 个不同的 k 值 * 3 个不同的 n 值。
在这个测试中,Elasticsearch 一直比开箱即用的 OpenSearch 快,只有在两个情况下 OpenSearch 更快,而且差距不大(knn-10-100 和 knn-100-1000)。涉及 knn-10-50、knn-10-100 和 knn-100-1000 结合过滤的任务显示了高达 7 倍 的差距(112 毫秒对 803 毫秒)。
在“强制合并”之后,两者的性能似乎趋于一致,这可以理解,通过 knn-10-50-after-force-merge、knn-10-100-after-force-merge 和 knn-100-1000-after-force-merge 的任务 faiss
表现更快。
精确 KNN 的性能差异再次非常大,这次 Elasticsearch 比 OpenSearch 快 13 倍(~385 毫秒对 ~5262 毫秒)。
knn-recall-10-100 | knn-recall-100-1000 | knn-recall-10-50 | |
---|---|---|---|
Elasticsearch-8.14.0@lucene-hnsw | 1 | 1 | 1 |
Elasticsearch-8.14.0@lucene-int8_hnsw | 1 | 0.986667 | 1 |
OpenSearch-2.14.0@lucene-hnsw | 1 | 1 | 1 |
OpenSearch-2.14.0@faiss | 1 | 1 | 1 |
OpenSearch-2.14.0@faiss-sq_fp16 | 1 | 1 | 1 |
OpenSearch-2.14.0@nmslib | 0.9674 | 0.910303 | 0.976394 |
在 Elastic,我们不断创新 Apache Lucene 和 Elasticsearch,以确保我们能够提供搜索和检索用例的顶级向量数据库,包括 RAG(检索增强生成)。我们的最新进展显著提高了性能,使向量搜索比以前更快且更节省空间,这建立在 Lucene 9.10 的基础上。本文介绍了一项研究,显示在比较最新版本时,Elasticsearch 的速度比 OpenSearch 高出 12 倍。
值得注意的是,两款产品使用相同版本的 Lucene(Elasticsearch 8.14 发行说明和OpenSearch 2.14 发行说明)。
Elastic 的创新步伐将为我们的本地和 Elastic Cloud 客户以及使用我们无状态平台的客户带来更多好处。支持量化到 int4等功能将经过严格测试,以确保客户可以使用这些技术而不会显著降低召回率,类似于我们对8 位量化的测试。
由于 AI 和机器学习应用的普及,向量搜索效率正成为现代搜索引擎中不可或缺的功能。对于寻找强大搜索引擎以应对高容量、高复杂度向量数据需求的组织来说,Elasticsearch 是明确的答案。
无论是扩展现有平台还是启动新项目,集成 Elasticsearch 以满足向量搜索需求都是一项战略性举措,将带来切实的长期利益。凭借其经过验证的性能优势,Elasticsearch 准备好支持搜索领域的下一波创新。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。