es为什么要限制记录数为10000以及深度分页-from-cnblog- _Emotion丶小寳

  1. 性能要求,在硬件和查询效率中作出权衡
  2. 对大部分请求来说,都不会超过10000条,即不需要深度分页,当需要请求超过10000条时,你就需要考虑你的查询语句是否恰当

前言
近期在做新的项目时,使用了ElasticSearch作为数据的存储和查询。接到了一个比较恶心的需求,需要对es进行分页查询,单次查询一万条,最多需要查询十次。当时也没想太多,需求评审时并没有及时反驳,既然掉坑里了,那就想办法爬出来吧!

es的分页

1)from+size浅分页
我们当时有点想当然了,以为from+size就可以搞定(业务代码写多的后果)。实际测试的时候,发现内存消耗特别大,而且速度也很一般。ES的查询机制如下:
在这里插入图片描述
假设我们的ES有三个节点,当分页查询请求过来时,如果落到node1节点,那么node1节点将会向node2和node3发送同样的查询请求,每个节点将topN的文档返回(这里只返回文档的id以及打分排序的字段,减少数据传输),node1会对三个节点的所有文档(3N个)进行排序,取topN后再根据文档的id到对应的节点上查询整个文档数据,最后返回客户端。
而对于分页查询,比如from=10000,szie=10000,其实每个节点需要查询from+size=20000条数据,排序之后截取后10000条数据。当我们进行深度分页,比如查询第十页数据时,每个节点需要查询10
size=10W条数据,这个太恐怖了。而且默认情况下,当from+size大于10000时,查询会抛出一个异常,ES2.0后有一个max_result_window属性的设置,默认值是10000,也就是from+size的最大限度。当然你可以修改这个值作为临时的应对策略,不过治标不治本,产品也只会变本加厉!

2)scroll查询
ES支持scroll滚屏查询,有兴趣的同学可以了解一下,网上相关的文档不少。不过根据ES官网的描述,scroll查询是很耗性能的方式,不建议在实时查询中运用。摘抄自官网:The Scroll api is recommended for efficient deep scrolling but scroll contexts are costly and it is not recommended to use it for real time user requests.

3)search_after查询
search_after是ES5.0及之后版本提供的新特性,search_after有点类似scroll,但是和scroll又不一样,它提供一个活动的游标,通过上一次查询最后一条数据来进行下一次查询。
比如第一次查询如下:

GET zm/recall/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "lastModifyTime": {
        "order": "desc"
      }
    }
  ], 
  "size": 10
}

这里根据更新时间进行排序,拿到的结果如下:

{
        "_index": "zmrecall",
        "_type": "recall",
        "_id": "60310505115909",
        "_score": null,
        "_source": {
          "userId": 60310505115909,
          "score": 1,
          "city": [
            276
          ],
          "sex": 1,
          "age": 29,
          "lastModifyTime": 1545037514
        },
        "sort": [
          1545037514
        ]
      }

注意到返回结果中有一个sort字段,所以下一次查询的时候,只需要将本次查询最后一条数据中的排序字段加入查询即可:

GET zm/recall/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "lastModifyTime": {
        "order": "desc"
      }
    }
  ], 
  "search_after": [1545037514],//这个值与上次查询最后一条数据的sort值一致,支持多个
  "size": 10
}

这里需要说明一下,使用search_after查询需要将from设置为0或-1,当然你也可以不写
另外在ES6.5的文档中有这样一句话需要注意一下:
在这里插入图片描述
大致的意思就是,如果search_after中的关键字为654,那么654323的文档也会被搜索到,所以在选择search_after的排序字段时需要谨慎,可以使用比如文档的id或者时间戳等
另外,search_after并不是随机的查询某一页数据,而是并行的滚屏查询;search_after的查询顺序会在更新和删除时发生变化,也就是说支持实时的数据查询
在这里插入图片描述
总结
在使用一个工具之前,一定要对其内部的基本流程有一个简单的了解,否则出现问题时不知从何入手。search_after相比较上面的浅分页以及scroll滚屏查询会有很大的性能提升,推荐大家使用!

最后附上ES的官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.5/search-request-search-after.html

另外在csdn上也看到一个博客,讲的很不错:https://blog.csdn.net/ctwy291314/article/details/82754652

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值