ES查询

Coordinating 节点

每个节点都是协调节点。当客户端向一个节点发送查询请求时,这个节点就充当协调节点,协调节点需要处理本次请求:

  1. 解析请求参数,计算当前索引的分片;
  2. 广播查询请求到索引的各个分片,并行查询各分片数据;
  3. 合并所有分片的查询结果,返回到客户端。

两步查询

查询分两个阶段:

查询阶段

协调节点将查询请求发送到当前索引的所有分片后:

  1. 各个分片根据 term 查询倒排索引取到 docId;
  2. 每个分片生成一个优先队列(根据 from size 确定),只包含 doc_id 和排序值;
  3. 所有分片将队列返回到协调节点。
取回阶段

协调节点根据查询阶段查到的队列,汇总所有队列,截取 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 值是多少的。

聚合

聚合操作在查询阶段之后进行,每个分片都要各自计算聚合结果,然后将各自结果返回到协调节点,协调节点汇总再聚合。