深度解析 Elasticsearch 搜索过程:Query Then Fetch 两阶段详解

news2026/4/27 21:30:16
深度解析 Elasticsearch 搜索过程Query Then Fetch 两阶段详解前言一、搜索流程全景图1.1 两阶段概览1.2 为什么需要两个阶段二、示例集群环境三、第一阶段Query 阶段3.1 步骤一协调节点广播请求3.2 步骤二每个分片本地查询3.3 步骤三协调节点合并排序四、第二阶段Fetch 阶段4.1 步骤一协调节点发起 MultiGet 请求4.2 步骤二分片返回完整文档4.3 步骤三协调节点组装并返回五、深度剖析关键设计细节5.1 为什么 Query 阶段返回 fromsize 条而非只返回 size 条5.2 深度分页问题5.3 分片选择策略主 vs 副本5.4 搜索类型已废弃六、完整时序图七、性能优化建议八、常见面试题Q1Query 阶段和 Fetch 阶段各自做了什么Q2为什么需要两个阶段不能合二为一Q3什么是深度分页问题如何解决Q4协调节点如何决定查询主分片还是副本分片九、总结十、面试加分回答)The Begin点点关注收藏不迷路前言搜索是 Elasticsearch 最核心的功能之一但很多开发者对 ES 内部如何执行搜索请求一知半解。为什么搜索分为两个阶段协调节点做了什么分片如何返回结果本文将围绕官方定义的“Query Then Fetch”两阶段模型逐步拆解分布式搜索的完整流程。一、搜索流程全景图1.1 两阶段概览┌─────────────────────────────────────────────────────────────────────┐ │ 客户端发送搜索请求 │ │ GET /my_index/_search?qkeyword │ └─────────────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 【第一阶段Query 阶段】 │ │ 目的定位到哪些文档匹配但不返回文档内容 │ │ │ │ 1. 协调节点将请求广播到所有分片主或副本 │ │ 2. 每个分片本地查询返回文档ID 排序值到优先队列 │ │ 3. 协调节点合并各分片结果生成全局排序列表 │ └─────────────────────────────────┬───────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────────────┐ │ 【第二阶段Fetch 阶段】 │ │ 目的根据 Query 阶段得到的文档ID获取完整的文档内容 │ │ │ │ 1. 协调节点向相关分片发送 MultiGet 请求 │ │ 2. 分片返回完整文档内容 │ │ 3. 协调节点组装结果返回给客户端 │ └─────────────────────────────────────────────────────────────────────┘1.2 为什么需要两个阶段如果合并为一个阶段两阶段分离的好处每个分片返回完整文档 → 大量网络传输Query 阶段只传ID和排序值数据量极小协调节点需要丢弃超出size的文档Fetch 阶段只取最终需要的文档无法做全局排序先全局排序再按需获取一句话总结先定位后取数避免网络和内存浪费。二、示例集群环境为便于理解设定以下集群状态配置项值索引名my_index主分片数5副本数1总分片数105主 5副本文档总数10,000 条搜索请求GET/my_index/_search{from:0,size:10,query:{match:{title:elasticsearch}},sort:[{_score:desc}]}三、第一阶段Query 阶段3.1 步骤一协调节点广播请求┌─────────────────┐ │ 客户端 │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ 协调节点 │ │ (接收搜索请求) │ └────────┬────────┘ │ ┌──────────────┬───────────────┼───────────────┬──────────────┐ │ │ │ │ │ ▼ ▼ ▼ ▼ ▼ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ 分片0 │ │ 分片1 │ │ 分片2 │ │ 分片3 │ │ 分片4 │ │ (主/副本) │ │ (主/副本) │ │ (主/副本) │ │ (主/副本) │ │ (主/副本) │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘关键要点协调节点向所有分片发送请求每个分片只命中主或副本中的一个采用轮询策略选择主还是副本负载均衡请求参数完全相同query、from、size、sort3.2 步骤二每个分片本地查询每个分片收到请求后独立执行以下操作┌─────────────────────────────────────────────────────────────────┐ │ 单个分片内部处理流程 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 1. 解析查询语句 → 生成 Lucene Query │ │ ▼ │ │ 2. 遍历倒排索引 → 找到匹配的文档ID列表 │ │ ▼ │ │ 3. 计算每个文档的 _score相关性评分 │ │ ▼ │ │ 4. 按排序字段排序默认按 _score 降序 │ │ ▼ │ │ 5. 截取 [from, fromsize] 范围的文档本地优先队列 │ │ ▼ │ │ 6. 返回 (文档ID 排序值) 给协调节点不返回文档内容 │ │ │ └─────────────────────────────────────────────────────────────────┘示例假设每个分片有 2000 条匹配文档from0, size10每个分片只返回前 10 条按排序值。// 每个分片返回给协调节点的数据格式{shard:0,hits:[{_id:doc_123,_score:9.5,sort_values:[9.5]},{_id:doc_456,_score:9.2,sort_values:[9.2]},...{_id:doc_789,_score:8.1,sort_values:[8.1]}// 共10条]}3.3 步骤三协调节点合并排序协调节点收到所有分片的返回结果后┌─────────────────────────────────────────────────────────────────┐ │ 协调节点合并流程 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ 输入5个分片 × 10条结果 50条候选记录 │ │ ▼ │ │ 1. 将所有50条记录放入全局优先队列 │ │ ▼ │ │ 2. 按排序规则重新排序_score 降序 │ │ ▼ │ │ 3. 截取 [0, 10] 条即最终需要的10条文档 │ │ ▼ │ │ 4. 记录这10条文档分别来自哪个分片 │ │ 文档A → 分片0 │ │ 文档B → 分片2 │ │ 文档C → 分片1 │ │ ... │ │ │ └─────────────────────────────────────────────────────────────────┘此时 Query 阶段结束协调节点知道哪 10 条文档需要返回每条文档所在的分片位置四、第二阶段Fetch 阶段4.1 步骤一协调节点发起 MultiGet 请求协调节点根据 Query 阶段的结果向相关分片批量获取文档内容协调节点 │ ┌──────────────────┼──────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 分片0 │ │ 分片1 │ │ 分片2 │ │ 需要文档 │ │ 需要文档 │ │ 需要文档 │ │ [A, D] │ │ [C, E] │ │ [B, F] │ └─────────┘ └─────────┘ └─────────┘// 协调节点发送的 MultiGet 请求示例GET/_mget{docs:[{_index:my_index,_id:doc_A,_shard:0},{_index:my_index,_id:doc_D,_shard:0},{_index:my_index,_id:doc_C,_shard:1},...]}4.2 步骤二分片返回完整文档每个分片从Lucene 段或Translog中读取完整的文档源_source// 分片返回的文档内容{_id:doc_A,_index:my_index,_score:9.5,_source:{title:Elasticsearch 入门教程,content:本文介绍 Elasticsearch 的基本概念...,timestamp:2026-01-26T10:00:00Z}}4.3 步骤三协调节点组装并返回协调节点收集所有文档按 Query 阶段排好的顺序组装返回给客户端{took:15,timed_out:false,_shards:{total:10,successful:10,skipped:0,failed:0},hits:{total:{value:10000,relation:eq},max_score:9.5,hits:[{_index:my_index,_id:doc_A,_score:9.5,_source:{title:Elasticsearch 入门教程,...}},{_index:my_index,_id:doc_B,_score:9.3,_source:{title:Elasticsearch 高级查询,...}}// ... 共10条]}}五、深度剖析关键设计细节5.1 为什么 Query 阶段返回fromsize条而非只返回size条如果只返回 size 条实际做法返回 fromsize 条每个分片返回前 10 条每个分片返回前 50 条from0, size10 → 01010等等纠正实际上每个分片返回from size条而不是size条原因假设from90, size10全局第 91-100 条文档可能分散在各分片的前 100 条中。如果每个分片只返回 10 条会丢失数据。示例计算from 90, size 10 每个分片需要返回from size 100 条本地排序后的前100条 协调节点收到5个分片 × 100条 500条候选记录 ↓ 全局排序后取 [90, 100) 共10条5.2 深度分页问题上述机制导致深度分页性能极差页码from每个分片返回数协调节点处理数第1页0105×1050第10页901005×100500第100页99010005×10005000第1000页9990100005×1000050000解决方案Search After基于上一页最后一条文档的排序值继续查询Scroll API用于大量数据导出不再推荐Point in Time (PIT)ES 7.10 引入的游标机制5.3 分片选择策略主 vs 副本协调节点决定每个分片查询主还是副本遵循负载均衡原则默认策略自适应副本选择Adaptive Replica Selection - 优先选择响应最快的节点 - 考虑节点历史延迟和队列长度好处分摊主节点压力提升查询吞吐量5.4 搜索类型已废弃早期 ES 支持多种搜索类型现已统一为query_then_fetch搜索类型说明状态query_and_fetch查询取回合并废弃dfs_query_then_fetch全局词频计算废弃默认已优化query_then_fetch标准两阶段当前唯一六、完整时序图客户端 协调节点 分片0(主) 分片1(副本) 分片2(主) ... │ │ │ │ │ │──搜索请求────▶│ │ │ │ │ │ │ │ │ │ │──Query请求───▶│ │ │ │ │──Query请求──────────────────▶│ │ │ │──Query请求──────────────────────────────────▶│ │ │ │ │ │ │ │◀──返回ID列表──│ │ │ │ │◀──返回ID列表──────────────────│ │ │ │◀──返回ID列表──────────────────────────────────│ │ │ │ │ │ │ │ (合并排序) │ │ │ │ │ │ │ │ │ │──Fetch请求────▶│ │ │ │ │──Fetch请求──────────────────▶│ │ │ │ │ │ │ │ │◀──完整文档────│ │ │ │ │◀──完整文档──────────────────│ │ │ │ │ │ │ │◀──最终结果────│ │ │ │七、性能优化建议优化点建议效果控制返回字段使用_source只返回必要字段减少网络传输避免 depth 分页使用search_after替代from/size性能提升 10-100x合理设置分片数单分片 30-50GB避免过度分片使用索引排序index.sort减少排序开销查询提速 30%开启自适应副本默认已开启负载更均衡八、常见面试题Q1Query 阶段和 Fetch 阶段各自做了什么回答Query 阶段协调节点将搜索请求广播到所有分片每个分片本地查询后返回文档ID 排序值不返回文档内容。协调节点合并所有结果生成全局排序列表确定最终需要获取的文档ID及所在分片。Fetch 阶段协调节点向相关分片发送MultiGet 批量请求获取完整文档内容_source组装后返回给客户端。Q2为什么需要两个阶段不能合二为一回答如果合为一个阶段每个分片会返回大量完整文档造成巨大的网络开销。例如from990, size10每个分片需要返回 1000 条完整文档5 个分片就是 5000 条但最终只取 10 条。两阶段分离后Query 阶段只传轻量级的 ID 和排序值约 100 字节/条Fetch 阶段只取最终的 10 条效率大幅提升。Q3什么是深度分页问题如何解决回答深度分页指跳转到很深页码如第 1000 页的情况。由于 Query 阶段每个分片必须返回fromsize条记录翻页越深协调节点处理的数据量越大第 1000 页需要每个分片返回 10000 条5 分片处理 50000 条。解决方案Search After使用上一页最后一条文档的排序值像游标一样向前翻页Point in Time (PIT)固定时间点的快照视图结合 search_after 使用Scroll API适合大量数据导出已不推荐用于实时搜索Q4协调节点如何决定查询主分片还是副本分片回答ES 7.x 后默认使用自适应副本选择Adaptive Replica Selection协调节点会维护每个节点的响应延迟、历史失败率、搜索线程池队列长度等指标动态选择当前最优的节点主或副本发送请求。这样既实现了负载均衡又能自动避开慢节点。九、总结维度Query 阶段Fetch 阶段目的定位匹配文档获取完整内容传输数据文档ID 排序值完整_source数据量小每个分片fromsize条大仅size条涉及的节点所有分片只包含最终文档的分片关键操作倒排索引检索本地排序Lucene 读取_source时间复杂度O(分片数 × 查询开销)O(文档条数)核心要点搜索采用Query Then Fetch两阶段模型Query 阶段坐标 不取→ 轻量级定位Fetch 阶段取数 组装→ 按需获取深度分页用Search After替代from/size协调节点通过自适应副本选择实现负载均衡十、面试加分回答面试官请详细描述 Elasticsearch 的搜索过程。候选人“ES 的搜索采用Query Then Fetch两阶段模型。Query 阶段协调节点将请求广播到所有分片主或副本之一。每个分片独立执行查询从倒排索引中找到匹配文档计算_score并按排序字段截取fromsize条结果只返回文档ID和排序值给协调节点。协调节点合并所有分片结果进行全局排序最终确定需要返回的size条文档及其所在分片。这一阶段的核心价值是轻量级传输避免早期传输大量无用数据。Fetch 阶段协调节点向包含目标文档的分片发送 MultiGet 批量请求获取完整的_source内容按 Query 阶段排好的顺序组装返回给客户端。这里有一个关键设计每个分片必须返回fromsize条记录而非size条因为全局第 N 条可能来自任意分片的前 N 条。这也导致了深度分页问题解决方案是使用Search After Point in Time代替传统的 from/size 翻页。另外ES 通过自适应副本选择来决定查询主还是副本优先选择响应最快的节点兼顾负载均衡和性能。”The End点点关注收藏不迷路

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2557218.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…