• Elasticsearch from/size-浅分页查询-深分页 scroll-深分页search_after深度查询区别使用及应用场景


    Elasticsearch调研深度查询

    1.from/size 浅分页查询

    copy
    一般的分页需求我们可以使用from和size的方式实现,但是这种的分页方式在深分页的场景下应该是避免使用的。深分页的页次增加,所消耗的内存和时间的增长也是成比例的增加,为了避免深度分页产生的问题,Elasticsearch从2.0版本楷书,增加了一个限制: index.max_result_window = 10000 # elasticsearch的一种保护机制,限制1w条数据,但是可以修改最大限根据实际需求,不过最好不要修改会影响性能。

    2.深分页 scroll

    copy
    # 引入scroll from/size查询查询在10000-50000条数据(1000到5000页)以内的时候还是可以的,但是如何数据量过多的话,就会出现深分页的问题 # 为了解决以上问题,elasticsearch提出了一个scroll滚动的方式。

    scroll使用

    copy
    1.scroll的原理是讲索引数据备份,每次记住最后一次查询的位置,下一次从最后一次位置开始查询。 2.使用scroll,通过size的查询最大限制,scroll返回一个代表最后一个size查询的位置scroll_id可以不断的获取下一页的内容。

    1.第一次查询带scroll参数

    copy
    GET tag-*/_search?scroll=10m { "query": { "match_all": {} }, "sort": [{"stime": {"order": "desc"}}], "from": 0, "size": 10000 }
    copy
    1.scroll=5m表示设置scroll_id保留5分钟可用。 2.使用scroll必须要将from设置为0。 3.size决定后面每次调用_search搜索返回的数量

    2.查询结果会返回scroll_id,第二次查询会带上scroll_id,就能从上一次查询的末尾开始查询了。

    copy
    1.然后我们可以通过数据返回的_scroll_id读取下一页内容,每次请求将会读取下10000条数据,直到数据读取完毕或者scroll_id保留时间截止 2.请求的接口不再使用索引名了,而是 _search/scroll,其中GET和POST方法都可以使用。
    copy
    GET /_search/scroll { "scroll_id": "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAC7EWa1U5THR6U0xSSXVOZjJTaUhpeHY2dw==", "scroll": "10m" }

    3.scroll删除scroll在es的上下文中的数据

    copy
    1.根据官方文档的说法,scroll的搜索上下文会在scroll的保留时间截止后自动清除,但是我们知道scroll是非常消耗资源的,所以一个建议就是当不需要了scroll数据的时候,尽可能快的把scroll_id显式删除掉,而且会生成历史快照,对于数据的变更不会反映到快照上。
    copy
    DELETE /_search/scroll/DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAC7EWa1U5THR6U0xSSXVOZjJTaUhpeHY2dw==

    4.scroll的使用场景(使用场景:数据导出)

    copy
    1.可以看出scroll不适合支持那种实时的和用户交互的前端分页工作,其主要用途用于从ES集群分批拉取大量结果集的情况,一般都是offline的应用场景。 比如需要将非常大的结果集拉取出来,存放到其他系统处理,或者需要做大索引的reindex等等。

    3.深分页search_after

    copy
    建议使用Scroll api进行高效深度滚动,但滚动上下文代价很高,建议不要将其用于实时用户请求。该search_after参数通过提供实时游标来解决此问题。

    search_after使用

    copy
    1.search_after是ES5.0及之后版本提供的新特性,search_after有点类似scroll,但是和scroll又不一样,它提供一个活动的游标,通过上次查询的最后一条数据来进行下一次查询。 2.search_after分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。 3.但是需要注意,因为每一页的数据都是依赖于上一页最后一条数据,所以无法跳页请求。

    1.search after 不能指定页数,只能一页挨一页问下查。第一次查询时带上sort,返回最后一个文档的id字段

    copy
    1.每个文档具有一个唯一值的字段应该用作排序规范的仲裁器。否则,具有相同排序值的文档的排序顺序将是未定义的。建议的方法是使用字段_id,它肯定包含每个文档的一个唯一值。 2.为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。
    copy
    GET tag-*/_search { "query": { "match_all": {} }, "sort": [ {"stime": {"order": "desc"}}, {"_id": {"order": "desc"}} ], "from": 0, "size": 10000 }
    copy
    # 为了根据最后一条数据的唯一标识来查询1w后面的数据 1.可以使用id的唯一标识,或者id加stime时间,来查询1w的后面数据。 2.当前我们search_after使用的唯一标识有id和stime,那么sort排序就必须加入stime和id排序不然会报错。

    2.下一次查询带上search after参数

    copy
    1.上面的请求会为每一个文档返回一个包含sort排序值的数组。这些sort排序值可以被用于 search_after 参数里以便抓取下一页的数据。比如,我们可以使用最后的一个文档的sort排序值,将它传递给 search_after 参数:
    copy
    GET tag-*/_search { "query": { "match_all": {} }, "sort": [ {"stime": {"order": "desc"}}, {"_id": {"order": "desc"}} ], "search_after": ["2022-09-25T12:38:42.142Z", "pxOodIMBf53JeIypLfhE"], "from": 0, "size": 10000 }
    copy
    使用search_after必须要设置from=0。 这里我使用timestamp和_id作为唯一值排序。 我们在返回的最后一条数据里拿到sort属性的值传入到search_after。

    3.删除和特性

    copy
    1.search_after不是自由跳转到随机页面而是并行滚动多个查询的解决方案。它与滚动API非常相似,但与它不同,search_after参数是无状态的,它始终针对最新版本的搜索器进行解析。因此,排序顺序可能会在步行期间发生变化,具体取决于索引的更新和删除。

    4.search_after应用场景

    copy
    1.不支持跳页查询 # 另外在ES6.5的文档中有这样一句话需要注意一下: 2.另外,search_after并不是随机的查询某一页数据,而是并行的滚屏查询;search_after的查询顺序会在更新和删除时发生变化,也就是说支持实时的数据查询 3.大致的意思就是,如果search_after中的关键字为654,那么654323的文档也会被搜索到,所以在选择search_after的排序字段时需要谨慎,可以使用比如文档的id或者时间戳等
  • 相关阅读:
    使用EFCore连接SQLite
    Java11改进的垃圾回收器
    【Call for papers】CSFW-2023(CCF-B/网络与信息安全/2023年2月3日截稿)
    Unigui可以使用WebSocket进行客户端之间的实时互相发消息
    halcon 区域Region(HObject)的传输
    YOLOV8目标检测——最全最完整模型训练过程记录
    微信小程序进阶——Flex弹性布局&轮播图&会议OA项目(首页)
    Spring Security之ExceptionTranslationFilter
    Redis开启远程连接
    实战讲解Kibana开发工具(Dev tools)操作ES:CURD(图+文)
  • 原文地址:https://www.cnblogs.com/goOJBK/p/16729321.html