Elasticsearch过滤向量搜索速度比OpenSearch快8倍
在2000万文档语料库上的基准测试显示,Elasticsearch过滤向量搜索吞吐量比OpenSearch高8倍,且召回率更高。上下文工程中多次检索循环使延迟成倍放大,检索性能直接影响端到端响应速度和成本。
搜索速度这事儿,在AI袋里和上下文工程里到底有多重要?直接看数据吧。我们在一个包含2000万篇文档的语料库上跑了基准测试,结果很说明问题——Elasticsearch在过滤向量搜索方面,吞吐量比OpenSearch高出8倍,而且在我们测试的所有配置里,Recall@100都更高。
上下文工程可不仅仅是依赖快速的向量检索。随着工作流不断迭代,团队还需要强大的相关性控制手段,比如混合搜索和过滤,操作上要简便,性能上要可预测。但关键在于,袋里在每个请求里通常要多次运行“检索→推理→再检索”这样的循环,检索延迟就成了一个倍增器。所以,这方面的任何改进,都会直接转化为更好的端到端响应速度和更低的成本。
OpenSearch 与 Elasticsearch:过滤向量搜索基准测试的吞吐量比较
图 1:吞吐量。
对于上下文工程而言,检索从来不是一次性的。袋里和应用程序会反复运行循环,比如检索→推理→检索,目的是优化查询、验证事实、构建更贴切的上下文,最终完成任务。这种模式在袋里工作流和迭代检索增强生成(RAG)中相当常见。每个用户请求都可能多次调用检索,这自然就拉长了响应延迟,或者推高了基础设施成本。
上下文工程将庞大的上下文池转换为有限的 LLM 上下文窗口。
图 1:上下文工程通过重复检索和整理,将大型上下文池(文档、内存、工具、聊天记录)转换为有限的大型语言模型 (LLM) 上下文窗口。
上下文工程的优化实施是一项新兴技术。迭代次数因工作流程而异。这些基准测试结果中最根本的关键概念是:上下文工程是有方向性的,迭代检索会让延迟成倍增加。
为什么向量搜索的性能至关重要?
场景是这样的:一位购物助理要回答一个需求——“我需要一个价格低于60美元的随身背包,能装下15英寸笔记本电脑,防水,而且周五之前必须送到。”
在生产环境中,这个助手很少只发一次向量查询就完事。它会跑一个检索循环来构建正确的上下文,每一步都常常受到库存、地区、配送承诺、品牌规则、政策资格等筛选条件的限制。
第一步:理解意图,并将其转化为约束条件。
袋里会把请求转换成结构化的过滤器和语义查询,比如:
筛选条件:有现货、可配送至用户邮编、周五前送达、价格低于60美元、有效商品信息
矢量查询:“可携带15英寸笔记本电脑的防水背包”
第二步:检索候选对象,然后进行筛选。
它会用不同的方法反复检索,避免错过好的匹配项:
“旅行背包,可携带笔记本电脑”
“15英寸防水通勤背包”
“轻便登机背包”
每次查询都带着相同的资格筛选器,因为检索到不相关或不可用的项目,只会浪费宝贵的上下文窗口。
第三步:展开确认细节,降低风险。
然后,袋里会再次检索,验证那些影响最终答案的关键属性:
材质和防水性能描述
尺寸和笔记本电脑隔层适配性
退货政策或保修限制
库存不足时的替代方案
这就是多步骤的上下文工程:检索、推理、检索、组装。
为什么延迟和召回对上下文工程至关重要
在每一个用户会话中,这些交互可能涉及数十次带筛选的检索调用。这意味着,每次调用的延迟会直接放大端到端的响应时间。而低召回率则迫使袋里进行额外的重试,或者导致它错过符合条件的项目,最终影响答案质量。
核心要点在于:在上下文相关的系统中,过滤近似最近邻(ANN)搜索不是单次查找,而是一项在约束条件下反复进行的操作。因此,即使大型语言模型(LLM)是最显眼的组件,向量搜索性能也会立竿见影地体现在延迟、吞吐量和成本上。
基准测试
结果
在图2里,每个点代表一个测试配置。效果最好的结果出现在左上角附近,意味着更高的召回率和更低的延迟。Elasticsearch的结果始终比OpenSearch更靠近左上角,说明在相同的工作负载下,Elasticsearch的速度和准确性都更胜一筹。
图 2:回忆率与平均延迟(重新评分 1)。
图 2:回忆率与平均延迟的关系,重新评分为 1。
一些关键见解
s_n_r_value:简写形式size_numCandidates_rescoreOversample(在这些测试中,k 和 numCandidates 均等于 numCandidates),例如,100_500_1表示 size=100,numCandidates=500 和 k=500,rescore oversample=1
召回率:该配置下测得的召回率(Recall@100)
平均延迟(毫秒):每次查询的平均端到端延迟
吞吐量:每秒查询次数
召回率:Elasticsearch 相对于 OpenSearch 的相对召回率提升(Elasticsearch 值减去 OpenSearch 值)/ OpenSearch
延迟 Xs:OpenSearch 平均延迟除以 Elasticsearch 平均延迟
吞吐量 Xs:Elasticsearch 吞吐量除以 OpenSearch 吞吐量
引擎 |
| 记起 | 平均延迟(毫秒) | 吞吐量 | 记起 % | 延迟 Xs | 吞吐量 Xs |
|---|---|---|---|---|---|---|---|
Elasticsearch | 100_250_1 | 0.7704 | 25 | 534.75 | 9.70% | 2.28 | 1.91 |
OpenSearch | 100_250_1 | 0.7023 | 57.08 | 279.58 | |||
Elasticsearch | 100_500_1 | 0.8577 | 25.42 | 524.14 | 7.20% | 2.4 | 2 |
OpenSearch | 100_500_1 | 0.8001 | 60.9 | 262.12 | |||
Elasticsearch | 100_750_1 | 0.8947 | 29.67 | 528.09 | 5.72% | 2.25 | 2.21 |
OpenSearch | 100_750_1 | 0.8463 | 66.76 | 239.11 | |||
Elasticsearch | 100_1000_1 | 0.9156 | 29.65 | 534.5 | 4.66% | 2.46 | 2.44 |
OpenSearch | 100_1000_1 | 0.8748 | 72.88 | 219.01 | |||
Elasticsearch | 100_1500_1 | 0.9386 | 31.84 | 497.3 | 3.38% | 2.71 | 2.68 |
OpenSearch | 100_1500_1 | 0.9079 | 86.16 | 185.4 | |||
Elasticsearch | 100_2000_1 | 0.9507 | 34.69 | 457.2 | 2.57% | 2.98 | 2.96 |
OpenSearch | 100_2000_1 | 0.9269 | 103.36 | 154.55 | |||
Elasticsearch | 100_2500_1 | 0.9582 | 37.9 | 418.43 | 1.99% | 3.28 | 3.26 |
OpenSearch | 100_2500_1 | 0.9395 | 124.29 | 128.53 | |||
Elasticsearch | 100_3000_1 | 0.9636 | 41.86 | 379.4 | 1.62% | 3.46 | 3.44 |
OpenSearch | 100_3000_1 | 0.9482 | 144.67 | 110.34 | |||
Elasticsearch | 100_4000_1 | 0.9705 | 50.28 | 316.21 | 1.06% | 3.87 | 3.85 |
OpenSearch | 100_4000_1 | 0.9603 | 194.36 | 82.22 | |||
Elasticsearch | 100_5000_1 | 0.9749 | 58.77 | 270.91 | 0.73% | 4.43 | 4.41 |
OpenSearch | 100_5000_1 | 0.9678 | 260.33 | 61.38 | |||
Elasticsearch | 100_6000_1 | 0.9781 | 66.75 | 238.59 | 0.52% | 4.91 | 4.89 |
OpenSearch | 100_6000_1 | 0.973 | 327.44 | 48.81 | |||
Elasticsearch | 100_7000_1 | 0.9804 | 74.64 | 213.49 | 0.38% | 5.28 | 5.27 |
OpenSearch | 100_7000_1 | 0.9767 | 394.24 | 40.53 | |||
Elasticsearch | 100_8000_1 | 0.9823 | 82.28 | 193.59 | 0.27% | 6.86 | 6.83 |
OpenSearch | 100_8000_1 | 0.9797 | 564.14 | 28.33 | |||
Elasticsearch | 100_9000_1 | 0.9837 | 90.08 | 176.96 | 0.16% | 7.63 | 7.61 |
OpenSearch | 100_9000_1 | 0.9821 | 687.25 | 23.25 | |||
Elasticsearch | 100_10000_1 | 0.9848 | 97.64 | 163.31 | 0.08% | 8.38 | 8.36 |
OpenSearch | 100_10000_1 | 0.984 | 818.64 | 19.53 |
举个例子,在100_9000_1配置下,OpenSearch上每次检索平均耗时687毫秒,而Elasticsearch只要90毫秒。如果在一个10步的检索循环里,那就要多等大约10 × (687 - 90) = 6秒钟。这差距,可不是一点半点。
查看完整结果。
方法论
我们使用Python发送查询,并跟踪响应时间和其他统计数据。需要说明的是,任何向量搜索引擎的性能都取决于核心参数的调优方式:考虑多少候选答案、重新评分的频率、返回多少上下文信息。这些设置直接决定了召回率(找到正确答案的可能性)和延迟(获得结果的速度)。
在基准测试中,我们使用了与袋里检索循环中通常调优的相同的候选列表、重评分和结果大小设置,测量了Elasticsearch在此工作负载下的性能。然后,我们使用相同的设置运行OpenSearch作为参考。
OpenSearch
GET /_search
{
"query": {
"knn": {
"": {
"vector": [...],
"k": ,
"method_parameters": {
"ef_search":
},
"rescore": {
"oversample_factor":
},
"filter": {
}
}
}
},
"size": ,
"_source": {
"excludes": [""]
}
} "size": :返回给客户端的命中次数。在此基准测试中,结果集大小为 100,以计算 Recall@100。"k": :最近邻候选对象的数量。"ef_search": :要检查的向量数量。"oversample_factor": :在重新评分之前检索到多少个候选向量。
Elasticsearch
GET /_search
{
"query": {
"knn": {
"field": "",
"query_vector": [...],
"k": ,
"num_candidates": ,
"rescore_vector": {
"oversample":
},
"filter": {
}
}
},
"size": ,
"_source": {
"excludes": [""]
}
} "size": :返回给客户端的命中次数。在此基准测试中,结果集大小为 100,以计算 Recall@100。"k": :从每个分片返回的最近邻居的数量。"num_candidates": :在进行 knn 搜索时,每个分片要考虑的最近邻候选数。"oversample": :在重新评分之前检索到多少个候选向量。
例子
对于配置100_500_1,对应的查询语句如下:
OpenSearch
GET search_catalog_128/_search
{
"query": {
"knn": {
"search_catalog_embedding": {
"vector": [...],
"k": 500,
"method_parameters": {
"ef_search": 500
},
"rescore": {
"oversample_factor": 1
},
"filter": {
"term": {
"valid": true
}
}
}
}
},
"size": 100,
"_source": {
"excludes": ["search_catalog_embedding"]
}
}Elasticsearch
GET search_catalog_128/_search
{
"query": {
"knn": {
"field": "search_catalog_embedding",
"query_vector": [...],
"k": 500,
"num_candidates": 500,
"rescore_vector": {
"oversample": 1
},
"filter": {
"term": {
"valid": true
}
}
}
},
"size": 100,
"_source": {
"excludes": ["search_catalog_embedding"]
}
}完整的配置,包括Terraform脚本、Kubernetes清单和基准测试代码,都可以在这个存储库的es-9.3-vs-os-3.5-vector-search文件夹中找到。
集群设置
我们在六台e2-standard-16云服务器上进行了测试,每台服务器配备16个vCPU和64GB内存。在每台服务器上,我们为运行搜索引擎节点的每个Kubernetes pod分配了15个vCPU和56GB内存,并为JVM堆保留了28GB内存。
集群运行的是Elasticsearch 9.3.0和OpenSearch 3.5.0(底层都是Lucene 10.3.2)。由于两个系统用了相同的Lucene版本,我们观察到的吞吐量和延迟差异就不能简单归因于Lucene本身,而是反映了每个引擎在集成和执行过滤后的k近邻(kNN)检索和重评分方面的差异。我们使用了一个包含三个主分片和一个副本的索引(总共6个分片,每个节点1个)。
另外,我们在同一区域用了另一台服务器来运行基准测试客户端,并收集计时统计数据。
Elasticsearch 和 OpenSearch 基准测试的集群设置
图 2:集群设置示意图。
数据集
为了进行这项基准测试,我们使用了一个包含2000万份文档的大规模电子商务风格目录嵌入数据集,旨在反映现实世界中大规模过滤向量检索的挑战。
每个文档代表一个目录项,包含:
- 用于近似kNN检索的128维稠密向量嵌入。
- 用于筛选的结构化元数据字段(例如,项目有效性和可用性,以及其他目录约束),这样可以模拟常见的生产模式:检索最近的邻居,但仅限于符合条件的子集内。
选择这个数据集,是因为它捕捉到了我们在生产环境中遇到的智能体和RAG类系统的核心性能挑战:仅靠向量相似度远远不够,检索经常受限于各种过滤器,系统必须在这些限制下保持高召回率和低延迟。与规模较小的问答类数据集相比,一个包含2000万篇文档的语料库,能更好地反映过滤式ANN系统在实践中面临的规模和候选词压力。
结论
在现代AI架构中,尤其是那些围绕上下文工程构建的架构,向量搜索速度不是一个可以忽略的实现细节,而是一个关键的倍增器。当袋里和工作流迭代地执行“检索→推理→检索”流程时,检索性能直接影响端到端延迟、吞吐量,以及最终喂给模型的上文质量。
在我们的基准测试中,当正确性取决于是否检索到正确的文档(而不仅仅是相似的向量)时,Elasticsearch始终比OpenSearch提供更高的召回率和更低的延迟。在受控数据集上,这种差异已经很明显;到了生产环境,这些优势会随着大量检索调用而不断累积,最终带来更快的响应速度、更多的容量余量,以及更低的基础设施成本。
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
同类文章
CAD零基础入门教程:坐标输入、图层管理与基础绘图命令
本文面向CAD零基础学习者,系统讲解坐标输入、图层管理与基础绘图命令的核心用法。通过分步实操与常见问题排查,帮助新手建立精确绘图习惯,掌握规范出图的基础能力。
CAD从入门到项目交付:绘图、标注、图块与实战工作流
掌握CAD的核心在于建立“画得准、标得清、复用快、交付稳”的工作流。本文提供从环境设置、高频命令组合、标注规范、图块标准化到项目分阶段交付的完整路径,帮助初学者避免常见返工陷阱,独立完成可检查、可复用、可打印的工程图纸。
Claude Code 登录指南:个人、Teams 与企业账号区分与授权步骤
本文详细解析 Claude Code 登录前的账号类型区分方法,涵盖个人订阅、Teams 席位与企业 Enterprise 席位的授权路径差异。提供终端登录命令、环境变量排查及常见异常处理步骤,帮助用户快速完成正确授权并避免登录路径混淆。
Claude Code 文件修改前的权限模式配置与命令审批指南
本文详细介绍Claude Code在修改文件前的权限模式配置方法,包括defaultMode可选值、permissions allow与deny规则设置、多层级配置文件管理以及 status验证技巧,帮助开发者安全高效地使用AI编程助手。
Claude Code接入VS Code后先测扩展和终端命令
在VS Code中接入Claude Code后,建议优先验证扩展面板与集成终端两条入口。本文提供标准检查顺序、关键命令与常见故障排查路径,帮助你快速确认环境就绪,避免后续开发受阻。
- 热门数据榜
1
2
3
4
5
6
7
8
9
10
相关攻略
2026-09-01 16:53
2026-09-01 16:52
2026-09-01 14:27
2026-09-01 14:12
2026-09-01 14:10
2026-09-01 14:07
2026-09-01 13:55
2026-09-01 13:47
热门教程
- 游戏攻略
- 安卓教程
- 苹果教程
- 电脑教程

