ES 22 - Elasticsearch的分页查询及其深分页问题 (deep paging)

目录

1 分页查询方法

2 分页查询的deep paging问题

 

1 分页查询方法

  • 在GET请求中拼接from和size参数
// 查询10条数据, 默认从第0条数据开始
GET book_shop/_search?size=10
// 从第0条数据开始(包括第0条), 查询10条数据
GET book_shop/_search?from=0&size=10
// 从第5条数据开始(包括第5条), 查询10条数据
GET book_shop/_search?from=5&size=10

2 分页查询的deep paging问题

deep paging, 就是深层分页搜索:

分页搜索的深度越深, 协调节点(负责分发查询、汇总结果的ES节点)上要存储的数据就越多, 协调节点对这些数据整体排序后, 再取对应页的数据.

这个过程既耗费网络资源, 也耗费内存和CPU资源.

deep paging简单来说,就是搜索的特别深,比如总共有60000条数据,现在有3个primary shard,每个shard上分20000条,每页是10条数据,这个时候你要搜索到第1000页,实际上要拿到的是10001-10010,该怎么拿呢?
请求首先可能是打到一个不包含这个index的shard的node上,这个node就是一个coordinate node,这个coordinate node就会将搜索请求转发到index的三个shard所在的node上去。

要搜索60000条数据中的第1000页,实际上每个shard都要将内部的20000条数据中的第1-10010条数据拿出来,不是10条,是10010条数据,3个shard每个shard都返回10010条数据给coordinate node,coordinate node会收到总共30030条数据,然后排序取到所需的那10条数据,其实就是我们要的最后的第1000页的10条数据。

举个例子,现在有60个带编号的球(从1到60),我现在随机给他们放到三个篮子里面(他们在篮子里面已经排好序了),现在我要取出第10-12个球,那我是不是应该先把各个篮子里面前12个球取出来放到一起(篮子里面的球是随机放的,无规律),共计36个球,然后汇总进行排序后,在这个结果中取出第10-12个球!!!

应该尽可能避免deep paging操作. —— 方法类似于Solr的游标

 

解决方案

为了解决上面的问题,elasticsearch提出了一个scroll滚动的方式,这个滚动的方式原理就是通过每次查询后,返回一个scroll_id。根据这个scroll_id 进行下一页的查询。可以把这个scroll_id理解为通常关系型数据库中的游标。但是,这种scroll方式的缺点是不能够进行反复查询,也就是说,只能进行下一页,不能进行上一页。

经过分析,如果数据达到了50000条以上,那么用户基本上是不会考虑每条都去看的,用户需要的是最后对数据分析处理后的结果。而如果小于50000条的时候我们可以使用from size的方式进行分页的查询。那么这种方式存在是为了什么情景呢。应该是为了分批次的检索所有数据。

 

实现步骤

1.首先取出前2条,并且得到scroll_id(这里的3s代表的是持续滚动时间,如果过了3秒钟,还没有查询下一页,那么这个scroll_id就会失效)。

get /bank/_search?scroll=3s&size=2

返回结果

{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHlRRVlUM1VCbVdLV0tyRU1mS3dsAAAAAAACAC4WRmpKb1RzR0ZTeC1nSHVfMWZBcDNOZw==",
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1000,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "bank",
        "_type" : "account",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "account_number" : 1,
          "balance" : 39225,
          "firstname" : "Amber",
          "lastname" : "Duke",
          "age" : 32,
          "gender" : "M",
          "address" : "880 Holmes Lane",
          "employer" : "Pyrami",
          "email" : "amberduke@pyrami.com",
          "city" : "Brogan",
          "state" : "IL"
        }
      },

 

2.再次查询下一页,注意,这里查询时不需要指定index,只需要指定scroll_id和本次的持续滚动时间。

说白了,想要第几页,循环请求几次就行了,在设置的时间内scroll_id是不会变的

POST /_search/scroll
{
  "scroll" : "3s",
  "scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHlRRVlUM1VCbVdLV0tyRU1mS3dsAAAAAAACAC4WRmpKb1RzR0ZTeC1nSHVfMWZBcDNOZw=="
}

返回结果

{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHlRRVlUM1VCbVdLV0tyRU1mS3dsAAAAAAACAC4WRmpKb1RzR0ZTeC1nSHVfMWZBcDNOZw==",
  "took" : 1,
  "timed_out" : false,
  "terminated_early" : true,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1000,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "bank",
        "_type" : "account",
        "_id" : "44",
        "_score" : 1.0,
        "_source" : {
          "account_number" : 44,
          "balance" : 34487,
          "firstname" : "Aurelia",
          "lastname" : "Harding",
          "age" : 37,
          "gender" : "M",
          "address" : "502 Baycliff Terrace",
          "employer" : "Orbalix",
          "email" : "aureliaharding@orbalix.com",
          "city" : "Yardville",
          "state" : "DE"
        }
      },

删除对应scroll_id

当我们搜索完毕或者说已经滚动到最后的时候,我们可以选择删除scroll_id

DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFHlRRVlUM1VCbVdLV0tyRU1mS3dsAAAAAAACAC4WRmpKb1RzR0ZTeC1nSHVfMWZBcDNOZw==

删除所有scroll_id

DELETE /_search/scroll/_all

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值