java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Elasticsearch搜索原理

Elasticsearch搜索原理及详细过程讲解

作者:代码的余温

Elasticsearch的搜索原理主要是通过倒排索引实现的,而倒排索引是相对于像MySQL数据库搜索数据的正向索引而言的,这篇文章主要介绍了Elasticsearch搜索原理及详细过程的相关资料,需要的朋友可以参考下

Elasticsearch 的搜索过程是一个高效、分布式的流程,设计用于在大量数据中快速定位相关信息。以下是其详细步骤:

核心流程:分散/聚集模型 (Scatter/Gather)

Elasticsearch 的搜索本质上是 分散 请求到相关分片,然后 聚集/合并 结果的过程。

1. 客户端发起请求 (Client Request Initiation)

2. 查询解析与路由 (Query Parsing & Routing)

3. 查询阶段 - 分散到分片 (Query Phase - Scatter)

4. 查询阶段 - 聚集结果 (Query Phase - Gather)

5. 取回阶段 (Fetch Phase)

6. 最终响应组装与返回 (Response Assembly & Return)

关键概念与注意事项

  1. 分布式本质:

    • 查询在每个分片本地并行执行,极大提高速度。
    • 协调节点负责路由、分发、合并和最终组装。
  2. 深度分页 (Deep Pagination) 问题:

    • from + size 的值非常大时(如 from: 10000, size: 10),每个分片都需要构建一个大小为 10010 的本地优先级队列,协调节点需要合并 number_of_shards * 10010 个结果来找到全局的 Top 10010,然后只返回最后 10 个。这对 CPU、内存和网络带宽消耗巨大,性能极差。
    • 解决方案: 使用 search_after 参数(基于上一页最后一个结果的排序值)或滚动 API (scroll)(用于深度遍历或导出,非实时)替代传统的 from/size
  3. 相关性评分 (_score):

    • 评分在每个分片本地计算,基于该分片的本地统计信息(如 IDF)。这在大集群中通常是足够准确的近似值。
    • 如果索引非常小或要求极端精确的全局评分(代价很高),可设置 search_type: dfs_query_then_fetch。它会在查询阶段增加一个额外的步骤,先收集所有分片的全局词频统计信息,再分发下去重新评分。通常不推荐使用,除非绝对必要。
  4. 聚合 (Aggregations):

    • 聚合计算也是在查询阶段在每个分片上并行执行的(构建桶、计算指标)。
    • 每个分片返回其本地聚合结果(部分桶和指标)。
    • 协调节点负责将来自所有分片的聚合结果合并成全局聚合结果(例如,合并桶、累加总和、计算全局平均值等)。这通常非常高效。
    • 某些聚合(如 terms)默认返回的是每个分片的 Top 桶合并后的结果,可能遗漏低频项(可通过增大 shard_size 缓解)。cardinalitypercentiles 等聚合使用近似算法。
  5. 过滤上下文 (Filter Context) vs. 查询上下文 (Query Context):

    • 查询上下文: 影响评分 (_score),用于全文搜索和相关性排序。must/should 通常在此上下文。
    • 过滤上下文: 只关心文档是否匹配(是/否),不评分。结果会被缓存,性能更高。filter/must_not/constant_score 通常在此上下文。将不关心评分的条件放入 filter 可以显著提升性能。
  6. 缓存:

    • 分片级请求缓存: 缓存整个查询请求的结果(通常是 size=0 的聚合请求或频繁重复的查询)。默认开启,但仅缓存特定查询(如 boolfilter 部分)。
    • 分片级查询缓存 (Query Cache): Lucene 级别,缓存查询结果的文档 ID 位集 (bitset)。对过滤 (filter 上下文) 性能提升明显,但对文本评分查询效果有限。默认开启但大小有限。
    • 文件系统缓存: OS 会将频繁访问的 Lucene 段文件缓存在内存中,极大加速索引读取。确保有足够内存给文件系统缓存是 ES 性能的关键。
  7. 副本的作用:

    • 副本不仅提供高可用性,也能分担读负载(搜索请求)。协调节点会将请求发送到分片副本(主或副),实现负载均衡。

总结流程图示:

[客户端]
   |
   | (1. 发送搜索请求)
   V
[协调节点]
   |
   | (2. 解析查询, 确定目标分片)
   |--------------------------------------------------
   |                                                  |
   V (3a. 发送查询请求)                              V (3a. 发送查询请求)
[分片副本 A]                                     [分片副本 B]
   | (执行本地查询, 构建优先级队列)                  | (执行本地查询, 构建优先级队列)
   | (4a. 返回文档ID/分片/分数队列)                 | (4a. 返回文档ID/分片/分数队列)
   |                                                  |
   |<-------------------------------------------------|
   |
   V
[协调节点]
   | (4b. 合并所有分片的队列, 确定全局Top-K)
   |
   | (5a. 发送mget请求获取具体文档)
   |--------------------------------------------------
   |                                                  |
   V (5b. 返回文档_source/高亮)                     V (5b. 返回文档_source/高亮)
[分片副本 A] (持有Doc X)                         [分片副本 N] (持有Doc Y)
   |                                                  |
   |<-------------------------------------------------|
   |
   V (6. 组装最终响应)
[协调节点]
   |
   | (返回搜索结果给客户端)
   V
[客户端]

理解这个分散/聚集流程对于诊断 Elasticsearch 搜索性能问题、优化查询 DSL 和配置集群至关重要。

总结

到此这篇关于Elasticsearch搜索原理及详细过程的文章就介绍到这了,更多相关Elasticsearch搜索原理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文