当前位置: 首页 > news >正文

Elasticsearch搜索原理

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

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

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


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

  • 用户或应用程序向 任意一个 Elasticsearch 节点(通常通过 REST API)发送搜索请求 (GET /<index>/_search)。
  • 请求包含查询 DSL(如 match, term, bool 查询)、过滤条件、排序、分页(from/size)、高亮、聚合等参数。
  • 收到请求的节点自动成为本次搜索请求的 协调节点 (Coordinating Node)

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

  • 协调节点 解析查询 DSL,确定需要搜索哪些 索引 (Indices)
  • 对于每个目标索引,协调节点根据索引的 分片 (Shards) 配置(主分片数量)和 路由策略(通常基于文档 ID 的哈希):
    • 计算查询应该发送到哪些 分片副本 (Shard Replicas)
    • ES 默认会将搜索请求 轮询 (Round-Robin) 发送到索引的所有分片(包括主分片和副本分片)的一个副本。这样做是为了充分利用所有节点的资源,实现负载均衡。
    • 如果查询指定了路由参数 (routing),协调节点会根据路由值计算出目标分片 ID,并只将请求发送到该特定分片(及其副本)。

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

  • 协调节点 将解析和处理后的搜索请求 并行地 发送到在步骤 2 中确定的所有 相关分片副本(目标分片的主分片或副本分片)。
  • 每个目标分片副本 在其本地独立执行查询:
    • 加载倒排索引: 查找查询词项在倒排索引中对应的文档 ID (_id) 列表。
    • 执行查询逻辑: 根据查询类型(布尔组合、短语匹配、范围查询等)处理这些文档 ID 列表,过滤掉不匹配的文档。例如:
      • Term Query: 直接查找对应 term 的倒排列表。
      • Match Query: 分词后对每个词项查找倒排列表,再按逻辑(如 OR)合并。
      • Bool Query: 组合多个子查询的 MUST/MUST_NOT/SHOULD/FILTER 逻辑。
      • Range Query: 查找数值或日期范围字段的倒排索引或 Doc Values。
    • 评分 (Scoring - 如果适用):
      • 对于需要相关性排序 ("sort": [{"_score": "desc"}]) 或 track_scores: true 的查询,每个分片使用选定的相似度算法(如 TF/IDF, BM25)计算匹配文档的 本地相关性分数 (_score)。评分基于该分片本地的词频、逆文档频率等统计信息。
      • FILTER 上下文 中的查询条件(如 filter 子句、boolfiltermust_not不参与评分,只用于二元过滤,效率通常更高。
    • 构建优先级队列:
      • 每个分片根据请求的 sizefrom(或 search_after)参数以及排序规则(默认按 _score 降序),在本地维护一个优先级队列 (Priority Queue)
      • 队列的大小是 size + from (对于 Top-K 结果合并足够)。
      • 该队列保存了当前分片本地得分最高(或按指定排序规则最靠前)的 size + from 个文档的元数据:文档 ID (_id)、分片 ID、排序字段值(主要是 _score注意:此时并不获取文档的实际源数据 (_source) 或存储字段。

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

  • 所有目标分片副本将其本地执行的查询结果(即包含文档 ID、分片 ID、排序值的优先级队列)并行地 发送回 协调节点
  • 协调节点 接收来自所有分片的结果。
  • 协调节点合并与排序:
    • 协调节点将来自各个分片的优先级队列 合并 成一个全局的优先级队列。
    • 这个全局队列的大小是用户请求的 size + from
    • 合并时,根据请求指定的排序规则(默认 _score 降序)决定文档在全局结果中的最终顺序。
    • 关键点: 协调节点此时只持有全局 Top (size + from) 结果的 文档 ID (_id)、分片位置、_score 等排序元数据,仍然没有文档内容 (_source)

5. 取回阶段 (Fetch Phase)

  • 一旦协调节点确定了全局排序后的最终文档列表(fromfrom + size 之间的文档),它需要获取这些文档的完整内容 (_source) 和/或任何显式请求的存储字段(stored_fields)。
  • 协调节点持有这些文档实际数据的分片 发送 多文档获取请求 (Multi-Get Request / mget)
    • 请求包含需要获取的文档的 _id 和它们所在的具体分片 ID。
  • 相关分片 接收到 mget 请求后:
    • 根据 _id 在其本地存储中查找对应的文档。
    • 加载 _source 从存储(通常是文件系统缓存中的 Lucene 段文件)中读取文档的原始 JSON 源数据 (_source)。
    • 应用高亮 (Highlighting): 如果需要,对 _source 中指定字段的内容执行高亮处理(查找匹配词并添加高亮标签)。
    • 应用字段过滤: 如果请求指定了 _source 过滤(如 "_source": ["title", "date"]),则只返回请求的字段。
    • 将处理好的文档数据(_id, _source, 高亮结果,存储字段等)返回给协调节点。

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

  • 协调节点 收集来自各个分片的 mget 响应。
  • 它组装最终的搜索结果响应 (Search Response):
    • hits 数组:包含排好序的实际文档数据 (_source),高亮信息等。数组长度由 size 决定,跳过前 from 个结果。
    • hits.total:匹配文档的总数 (这是一个下限值,如需精确值需设置 track_total_hits: true,代价较高)。
    • took:整个搜索请求消耗的总时间(毫秒)。
    • _shards:报告参与搜索的分片总数、成功数、失败数。
    • aggregations (如果请求了聚合):包含聚合结果。
    • 其他信息:如是否超时 (timed_out)、滚动 ID (_scroll_id) 等。
  • 协调节点 将组装好的最终 JSON 响应返回给原始客户端。

关键概念与注意事项

  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 和配置集群至关重要。

http://www.xdnf.cn/news/1348777.html

相关文章:

  • HEVC(H.265)与HVC1的关系及区别
  • Unreal Engine UProjectileMovementComponent
  • 异步开发的三种实现方式
  • Unreal Engine USceneComponent
  • Unreal Engine Simulate Physics
  • 线段树01
  • 20250822 组题总结
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘uvicorn’问题
  • 北京-测试-入职甲方金融-上班第三天
  • 嵌入式第三十五天(网络编程(UDP))
  • GPS欺骗式干扰的产生
  • DSPy框架:从提示工程到声明式编程的革命性转变
  • 声网SDK更新,多场景抗弱网稳定性大幅增强
  • GaussDB GaussDB 数据库架构师修炼(十八)SQL引擎(1)-SQL执行流程
  • week3-[二维数组]小方块
  • ArrayList线程不安全问题及解决方案详解
  • 硬件驱动---linux内核驱动 启动
  • 云原生俱乐部-k8s知识点归纳(7)
  • RCE的CTF题目环境和做题复现第4集
  • Unreal Engine UActorComponent
  • base64认识实际使用
  • #Datawhale 组队学习#8月-工作流自动化n8n入门-2
  • LLM实践系列:利用LLM重构数据科学流程01
  • 简单聊聊多模态大语言模型MLLM
  • LeetCode100 -- Day4
  • RCE的CTF题目环境和做题复现第3集
  • RoboTwin--CVPR2025--港大--2025.4.17--开源
  • 大模型微调训练资源占用查询:Windows 10 查看 NVIDIA 显卡GPU状态教程(替代 Ubuntu 下 watch nvidia-smi)
  • Python精确小数计算完全指南:从基础到金融工程实践
  • 二、高可用架构(Nginx + Keepalived + MySQL 主从)