• @Elasticsearch之深度应用及原理剖析--深度分页问题



    title: ElasticSearch之深度应用及原理剖析
    author: Xoni
    tags:

    • 搜索引擎
    • Elasticsearch
      categories:
    • 搜索引擎
    • Elasticsearch
      abbrlink: 5a1f6e0b

    第14节 deep paging性能问题 和 解决方案

    在这里插入图片描述

    深度分页问题

    ES 默认采用的分页方式是 from+ size 的形式,类似于mysql的分页limit。当请求数据量比较大时, Elasticsearch会对分页做出限制,因为此时性能消耗会很大。举个例子,一个索引 分10个 shards,然后,一个搜索请求,from=990,size=10,这时候,会带来严重的性能问题:

    • CPU
    • 内存
    • IO
    • 网络带宽

    CPU、内存和IO消耗容易理解,网络带宽问题稍难理解一点。在 query 阶段,每个shard需要返回 1000条数据给 coordinating node,而 coordinating node 需要接收 10*1000 条数据,即使每条数据只有 _doc _id 和 _score,这数据量也很大了,而且,这才一个查询请求,那如果再乘以100呢?
    es中有个设置 index.max_result_window,默认是10000条数据,如果分页的数据超过第1万条,就拒绝返回结果了。如果你觉得自己的集群还算可以,可以适当的放大这个参数,比如100万。
    我们意识到,有时这种深度分页的请求并不合理,因为我们是很少人为的看很后面的请求的,在很多的业务场景中,都直接限制分页,比如只能看前100页。
    不过,这种深度分页确实存在,比如有1千万粉丝的微信大V,要给所有粉丝群发消息,或者给某省粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,但这是不现实的,我们需要使用下面的解决方案。

    深度分页解决方案

    利用 scroll 遍历方式

    **

    • 初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照
    • 在遍历时,从这个快照里取数据,也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果。

    因此,scroll 并不适合用来做实时搜索,而更适用于后台批处理任务,比如群发。

    1)初始化

    POST /book/_search?scroll=1m&size=2 
    {
    	"query": {
    	  "match_all": {}
    	}
    }
    

    初始化时需要像普通 search 一样,指明 index 和 type (当然,search 是可以不指明 index 和 type 的),然后,加上参数 scroll,表示暂存搜索结果的时间,其它就像一个普通的search请求一样。
    初始化返回一个 scroll_id,scroll_id 用来下次取数据用

    1. 遍历
    GET /_search/scroll
    { 
      "scroll": "1m",
      "scroll_id" : "步骤1中查询出来的值"
    }
    

    这里的 scroll_id 即 上一次遍历取回的 _scroll_id 或者是初始化返回的 _scroll_id,同样的,需要带scroll 参数。 重复这一步骤,直到返回的数据为空,即遍历完成。注意,每次都要传参数 scroll,刷新搜索结果的缓存时间。另外,不需要指定 index 和 type。设置scroll的时候,需要使搜索结果缓存到下一次遍历完成,同时,也不能太长,毕竟空间有限。

    search after方式

    满足实时获取下一页的文档信息,search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改,这些变更也会实时的反映到游标上,这种方式是在es-5.X之后才提供的。为了找到每一页最后一条数据,每个文档的排序字段必须有一个全局唯一值 使用 _id 就可以了。

    GET /book/_search
    {
      "query": {
        "match_all": {}
      },
      "size": 2,
      "sort": [
        {
          "_id": "desc"
        }
      ]
    }
    
    GET /book/_search
    {
      "query": {
        "match_all": {}
      },
      "size": 2,
      "search_after": [
        3
      ],
      "sort": [
        {
          "_id": "desc"
        }
      ]
    }
    

    下一页的数据依赖上一页的最后一条的信息所以不能跳页。

    三种分页方式比较

  • 相关阅读:
    对于MVVM的理解、使用、MVC与MVVM的区别、MVVM应用场景
    猿创征文|在第一轮复习中,考研路上的成长历程
    Oracle自治事务示例演示
    TrOCR——基于transformer模型的OCR手写文字识别
    分享一下短视频创作前需要了解的内容和注意事项
    从Redis的架构看Redis使用优化方面的几个要点
    即时通讯开发Netty实现心跳机制、断线重连机制
    python-web应用程序-Django的请求与访问
    拆解美图SaaS:开着飞机换引擎
    Kernel: config: PARAVIRT; 部分虚拟化;类虚拟化
  • 原文地址:https://blog.csdn.net/weixin_45992021/article/details/127041228