ES 查询过程
ES查询
Coordinating 节点
每个节点都是协调节点。当客户端向一个节点发送查询请求时,这个节点就充当协调节点,协调节点需要处理本次请求:
- 解析请求参数,计算当前索引的分片;
- 广播查询请求到索引的各个分片,并行查询各分片数据;
- 合并所有分片的查询结果,返回到客户端。
两步查询
查询分两个阶段:
查询阶段
协调节点将查询请求发送到当前索引的所有分片后:
- 各个分片根据 term 查询倒排索引取到 docId;
- 每个分片生成一个优先队列(根据 from size 确定),只包含 doc_id 和排序值;
- 所有分片将队列返回到协调节点。
取回阶段
协调节点根据查询阶段查到的队列,汇总所有队列,截取 size 内容,向队列中 doc 所在的分片发起 Fetch 请求,取到 doc 的正排信息组装结果,最终返回给客户端。
深翻页请求
深翻页请求为什么那么慢?
在深翻页请求时:每一个分片都需要生成一个 from size 大小的队列,深翻页的 from 值一般都非常大,每个分片都需要计算资源来处理前 from 条数据,但是最终只取 size 大小的数据。CPU 和 memory 消耗都是随着 from 的大小线性增长的。
search_after
search_after 基于当前查询知道上一页请求的 sort 值之后,后续请求可以只请求 sort 值大于前一页 sort 值的这个游标的后续 doc,无需维护大的优先队列。
比如:
第一次请求按 age 从小到大排序,此时我已经知道了第一页 age 的值是到了 10,第二次请求我就可以用 search_after 参数为 age: 10,那么每个分片都会用这个值作为开始的游标,忽略比这个小的 age,每个分片都不用再维护无用的队列了。
但是这个方式有一个缺点就是,只能连续翻页查询,不能支持跳页,跳页是不知道 sort 值是多少的。
聚合
聚合操作在查询阶段之后进行,每个分片都要各自计算聚合结果,然后将各自结果返回到协调节点,协调节点汇总再聚合。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment
