elasticsearch分页的实现方式

对于搜索命中的结果,分页浏览是一项基本的需求。在es内部,分页有两种实现方式。

1:通过设置查询参数from和size

size:返回结果的数量。

from:从哪一条结果返回。

比如,返回前三页,没一页10条记录,可以用下边的命令表示:

GET /_search?size=10

GET /_search?size=10&from=10

GET /_search?size=10&from=20

在这种方式下,结果集在返回之前要经过排序,查询请求往往要在所有shards上搜索,每一个shard产生自己的排序结果集,然后汇聚在一起,再统一排序,返回。前面几页返回往往没什么问题,但是随着页数的增加,问题凸显。比如我们要第1000页的数据,则每一个shard要产生top 10010的数据,然后汇聚在一起综合排序,然后返回第10001--10010条数据,其实在这一页数据的时候,大部分排序结果我们都浪费掉了。而且,随着页数的增多,代价也越来越大。

这并不是首选的分页实现方式。

2:scroll+scan的方式

scroll的方式类似于数据库中的游标,可以分页返回大量的结果集。接口也十分简单:

GET /index/type/_search?scroll=1m {"query" :{.....}}

GET /_search/scroll?scroll=1m&scroll_id=cXVlcnlUaGVuRmV0Y2g7

第一条命令用scroll参数表明了这是一个scroll类型的查询,有效时间是1分钟。

第二条命令取下一页的数据,注意scroll_id字段,这是第一条命令返回的id。依次类推,直到返回的结果集为0.

上边已经介绍过from和size的方式在深度翻页的时候效率不高,而scroll api则会跟踪那些记录已经在之前的翻页中返回过,因此能更高效的完成排序。但是,对结果集进行排序还是会有消耗。

我们来分析下日常的需求,在需要返回大量结果集的情况下,往往用户对结果集的顺序并不是特别在意,因此scroll可以结合设置type=scan来禁止排序,这样就能更高效的返回大量结果集合。

GET /index/type/_search?scroll=1m&search_type=scan {"query":{.....}}

scan scroll跟标准的scroll 有几点不同:

(1)结果没有排序,按照doc进入索引的顺序

(2)不支持聚合操作

(3)最初的查询结果的hits列表是不包含查询结果的

(4)如果设置了size参数,其计算规则并不是本次搜索返回的结果条数,而是size*shard_num。假设size=10,有10个shard,则本次搜索最多会返回100条记录。

scroll参数会告诉es在多长时间内保存这次搜索的上下文。这个时间间隔并不是所有结果返回然后失效的时间间隔,而是单页的时间间隔。在整个搜索结束或者设置的时间间隔到期后自动清除上下文。时间设置的太久意味着打开更多的资源,比如file handler等,因此可以及时清除这些上下文,调用clear接口即可。

还有一点需要注意的是:scroll并不是实时的,前面讲过是在查询发生时刻做的一次snapshot,之后的查询结果都会落在这个时间点之前,因此最近刚刚进入的数据不在检索范围之内。其实这个时间差在应用中可以忽略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值