ES之分布式分页查询

我们知道ES的查询是非常快的,且每个索引的数据是存储在多个分片中的,查询压力负载到多个分片机器上,最后汇合查询结果,减轻了机器压力同时加快了速度。

但是当用户分页获取查询结果时,ES又是怎么获得全局的排序并取得分页结果呢?

这不光是ES会遇到的问题,所有的分布式存储数据排序都会有这个问题。

逐步分析

假设我们的索引有5个分片,每个分片上10万个文档数据

获取1~10条

我们知道单个节点数据都在本地,排序是很方便的。我们很容易将各个节点数据进行排序,分别取排序为1~10的文档数据,然后汇总从5(分片数) * 10(单片文档数)=50 条数据中获得1~10的文档。

获取11~20条

一个误区:有人会想当然的认为从上一个步骤中获取的50条数据中,直接取出11~20即为结果。他们觉得这些数据都是各个分区的前10组成,那么组成的结果理所当然的就是所有数据中排名的前50。

这是不对的。因为你只是取了各分片的前10条数据,它们只在各自分片下排序有用,无法证明这10条就一定比其它分片的11~n条数据大。

了解了误区,类别第一步,我们很容易知道应该获取5(分片数) * 20(单片文档数)=100条数据,然后整体排序,取得第11~20条数据。

获取第pageNumber页数据

由前两步可知: 当我们想获取分页数据时: es需要总共获得: (pageNumber * pageSize * 分片数)条数据,然后汇总排序,再取得所需结果。

如果pageNumber 和 pageSize 非常大, es每个分片所需获取的数据就会非常多,网络带宽以及后续的汇总会占用很多资源,严重影响性能。

因此使用es非常不建议进行深分页

数据汇总

我们知道es从各个节点总共获取到(pageNumber * pageSize * 分片数)条数据,需要排序取得总排名为1~pageNumber * pageSize的数据,然后再取其最后10条数据。

如何处理排序呢?

构建一个长度为(pageNumber * pageSize * 分片数)的数组,然后调用排序算法将整体排序,然后再获取结果即可。

可以但不可行。但pageNumber或pageSize或分片数,任意一个参数变大时,总数组长度增加的太快,太耗费内存。

使用优先队列:

许多时候我们需要处理有序的元素,但不一定要求他们全部有序,或是不一定要一次就将他们排序,这种时候就需要优先队列这种数据结构。

优先队列需要支持两种操作:删除最大元素插入元素

效果:可从不间断的输入数据中,始终筛选出当前输入数据中指定长度的最大的(或最小的)元素。

主分片创建优先队列,将本节点的符合条件的数据存入优先队列中,汇总其它节点数据时,只需将数据一个一个输入到优先队列中,队列会自动完成过滤,非常方便,也无需构建那么长的数组。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值