我们先了解一下在ES中数据的检索流程

  1. 请求发送到集群中的某一个协调节点(Coordinate node)
  2. 协调节点根据集群的meta信息找到此次查询的索引的所有分片信息
  3. 对于每一组主分片和备分片,协调节点会从该组中选出一个合适的分片,并对该分片的宿主节点发起查询请求
  4. 包含了指定分片的数据节点收到查询请求之后,会根据查询条件对数据进行检索
    • 首先根据search或filter查询要求查询数据,获取到查询结果
    • 如果查询请求中包含了排序的要求,此时根据排序条件对查询结果进行排序
    • 根据from和size对结果进行切割,保留前from+size条数据
    • 将数据返回给协调节点
  5. 协调节点取回各个数据节点所返回的数据,对这些数据再进行排序汇总,之后取出from至size的数据集,该数据集就是最终的数据结果
  6. 协调节点将数据返回给所查询的客户端

第4步的操作叫做scatter,类比于MapReduce中的map阶段
第5步的操作叫做gather,类比于MapReduce中的reduce阶段

数据节点需要对当前查询所对应的分片上的所有的数据进行检索和排序,如果此分片中数据量很大,此时数据节点的查询将会消耗大量的资源。因此如果一个索引的数据越多,该索引的分片也应该越多,这样可以减少索引的每个分片中的数据量。

协调节点会对所有从数据节点中取回的数据进行汇总和排序,协调节点中需要排序的数据等于

(from + size) × shards_num

因为协调节点中的数据量会被分片的数量所放大,因而一旦使用了深分页,协调节点会需要对大量的数据进行排序,影响查询性能。