在 OpenSearch 中搜索查询的生命周期

发布: (2026年5月1日 GMT+8 21:10)
7 分钟阅读
原文: Dev.to

抱歉,我只能看到您提供的来源链接,而没有看到需要翻译的正文内容。请您把要翻译的文本粘贴在这里,我会帮您翻译成简体中文,并保留原始的格式和代码块。

概览

A search request typically looks like:

GET /my-index/_search
Content-Type: application/json

{
  "query": { "match": { "title": "opensearch" } },
  "size": 10,
  "from": 0,
  "_source": true
}

客户端可以是 curl 到 Python SDK 等任何工具;传输格式始终是基于 HTTP 的 JSON。

HTTP 请求和协调节点

  1. HTTP 服务器 – OpenSearch 运行一个轻量级的 HTTP 服务器,用于解析请求。
  2. 协调节点 – 接收请求的节点会成为协调节点。集群中的任何节点都可以充当协调者;它 不需要 存储数据。

分片与路由

  • 数据存储在 shards(分片)中——即分布在集群中的 Lucene 索引。
  • 每个文档根据路由值(默认是文档 _id)被分配到一个 primary shard(主分片)。路由公式为:
hash(routing) % number_of_primary_shards
  • 协调节点运行此哈希函数,以确定哪些主分片负责处理该查询。
  • 对于单个索引上的简单词项查询,协调节点可能需要联系该索引的 all primary shards(所有主分片)。提供特定的路由值可以显著减少需要查询的分片数量,从而降低延迟。

分片上的查询执行

一旦确定了负责的分片,协调节点会将查询转发给分片节点(这些节点可能是同一台物理机器,也可能是不同的机器)。每个分片在本地针对其 Lucene 段执行查询。

段搜索

  • Lucene 将数据存储在 不可变段 中。在查询阶段,每个段会被独立搜索。
  • OpenSearch 可以在单个分片内部并行搜索段——这项功能称为 concurrent segment search(在 3.0 版中引入)。引擎会根据 CPU 核心数和段大小自动决定创建多少个 slice。

评分 (BM25)

  • 对于每个匹配的文档,Lucene 使用 BM25 算法计算相关性得分。
  • 关键参数:词项频率、逆文档频率以及长度归一化因子 b(默认值 0.75)。
  • 每个分片返回 top‑k(默认 10)文档及其得分。

获取阶段

查询阶段只返回文档 ID 和得分。如果客户端请求了 _source 字段(大多数情况下都会如此),则会执行第二轮称为 fetch phase(获取阶段)的操作:

  1. 协调节点向每个分片请求所选文档的完整源数据。
  2. 分片从 Lucene 的存储字段中检索已存储的 _source 并返回。

由于获取阶段可能会在网络上传输更大的负载,OpenSearch 会尽量保持获取的文档数量较少。分页(from/size)和 stored_fields 过滤器是重要的性能调节手段。

合并结果

在从每个分片收到 top‑k 结果后,协调节点:

  1. 合并 它们为一个单一的排序列表。
  2. 重新应用全局的 sizefrom 参数。
  3. 根据每个分片返回的 BM25 分数对合并后的集合进行排序。
  4. 应用查询中指定的任何自定义排序规则。

最终的合并列表会被格式化为 JSON 响应并返回给客户端。

近实时索引

  • 新文档首先写入 内存缓冲区 并追加到 translog 以确保持久性。
  • 每秒(默认 index.refresh_interval),缓冲区会刷新到一个新的 Lucene 段,使新索引的文档可被搜索。
  • 这导致索引与在搜索结果中可见之间通常只有 < 1‑秒延迟

常见问题与缓解措施

问题产生原因缓解措施
查询延迟慢查询的分片过多,段数量过高使用路由,配置 index.routing_partition_size,强制合并以减少段数
CPU 使用率高大分片上的并发段搜索调整 search.max_concurrent_shard_requestssearch.max_concurrent_segments
结果陈旧刷新间隔过大,无法满足实时需求在热索引上降低 index.refresh_interval
大负载为大量文档获取完整的 _source使用 stored_fieldsdocvalue_fields,限制 size

结论

在 OpenSearch 中,搜索查询不仅仅是一次简单的 HTTP 调用。它涉及路由、并行分片执行、评分、可选的获取以及将所有结果拼接在一起的最终合并步骤。了解每个阶段有助于你设计更好的模式、调优性能,并避免常见的陷阱,例如不必要的分片扫描或过长的刷新间隔。通过可视化查询的整个过程,你可以更有信心诊断延迟问题,选择合适的索引策略,并充分利用 OpenSearch 强大的插件和分析生态系统。

0 浏览
Back to Blog

相关文章

阅读更多 »

模型越智能,节省越多。

神话:更智能的模型会让插件变得多余。自从 WOZCODE 推出以来,许多 Claude Code 高级用户低声说插件的优势将会消失。