生活资讯
ElasticSearch深度分页解决方案
2025-01-01 21:50  浏览:93


「文章较长,可以点赞再看」

Elasticsearch 是一个实时的分布式搜索与分析引擎,在使用过程中,有一些典型的使用场景,比如分页、遍历等。

在使用关系型数据库中,我们被告知要注意甚至被明确禁止使用深度分页,同理,在 Elasticsearch 中,也应该尽量避免使用深度分页。

这篇文章主要介绍 Elasticsearch 中分页相关内容!

在ES中,分页查询默认返回最顶端的10条匹配hits。

如果需要分页,需要使用from和size参数。

一个基本的ES查询语句是这样的:

上面的查询表示从搜索结果中取第100条开始的10条数据。

「那么,这个查询语句在ES集群内部是怎么执行的呢?」

在ES中,搜索一般包括两个阶段,query 和 fetch 阶段,可以简单的理解,query 阶段确定要取哪些doc,fetch 阶段取出具体的 doc。

Query阶段

如上图所示,描述了一次搜索请求的 query 阶段:·

在上面的例子中,coordinating node 拿到条数据,然后合并并排序后选择前面的条数据存到优先级队列,以便 fetch 阶段使用。

另外,各个分片返回给 coordinating node 的数据用于选出前条数据,所以,只需要返回唯一标记 doc 的以及用于排序的即可,这样也可以保证返回的数据量足够小。

coordinating node 计算好自己的优先级队列后,query 阶段结束,进入 fetch 阶段。

Fetch阶段

query 阶段知道了要取哪些数据,但是并没有取具体的数据,这就是 fetch 阶段要做的。

上图展示了 fetch 过程:

coordinating node 的优先级队列里有 个,但是,在 fetch 阶段,并不需要取回所有数据,在上面的例子中,前100条数据是不需要取的,只需要取优先级队列里的第101到110条数据即可。

需要取的数据可能在不同分片,也可能在同一分片,coordinating node 使用 「multi-get」 来避免多次去同一分片取数据,从而提高性能。

「这种方式请求深度分页是有问题的:」

我们可以假设在一个有 5 个主分片的索引中搜索。当我们请求结果的第一页(结果从 1 到 10 ),每一个分片产生前 10 的结果,并且返回给 协调节点 ,协调节点对 50 个结果排序得到全部结果的前 10 个。

现在假设我们请求第 1000 页—结果从 10001 到 10010 。所有都以相同的方式工作除了每个分片不得不产生前10010个结果以外。然后协调节点对全部 50050 个结果排序最后丢弃掉这些结果中的 50040 个结果。

「对结果排序的成本随分页的深度成指数上升。」

「注意1:」

size的大小不能超过这个参数的设置,默认为10000。

如果搜索size大于10000,需要设置参数

「注意2:」

举个例子,一个索引,有10亿数据,分10个 shards,然后,一个搜索请求,from=1000000,size=100,这时候,会带来严重的性能问题:CPU,内存,IO,网络带宽。

在 query 阶段,每个shards需要返回 1000100 条数据给 coordinating node,而 coordinating node 需要接收,100 条数据,即使每条数据只有 和 ,这数据量也很大了?

「在另一方面,我们意识到,这种深度分页的请求并不合理,因为我们是很少人为的看很后面的请求的,在很多的业务场景中,都直接限制分页,比如只能看前100页。」

比如,有1千万粉丝的微信大V,要给所有粉丝群发消息,或者给某省粉丝群发,这时候就需要取得所有符合条件的粉丝,而最容易想到的就是利用 from + size 来实现,不过,这个是不现实的,这时,可以采用 Elasticsearch 提供的其他方式来实现遍历。

深度分页问题大致可以分为两类:

「下面介绍几个官方提供的深度分页方法」

Scroll遍历数据

我们可以把scroll理解为关系型数据库里的cursor,因此,scroll并不适合用来做实时搜索,而更适合用于后台批处理任务,比如群发。

这个分页的用法,「不是为了实时查询数据」,而是为了「一次性查询大量的数据(甚至是全部的数据」)。

因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。在这个查询后的任何新索引进来的数据,都不会在这个快照中查询到。

但是它相对于from和size,不是查询所有数据然后剔除不要的部分,而是记录一个读取的位置,保证下一次快速继续读取。

不考虑排序的时候,可以结合使用。

scroll可以分为初始化和遍历两部,初始化时将「所有符合搜索条件的搜索结果缓存起来(注意,这里只是缓存的doc_id,而并不是真的缓存了所有的文档数据,取数据是在fetch阶段完成的)」,可以想象成快照。

在遍历时,从这个快照里取数据,也就是说,在初始化后,对索引插入、删除、更新数据都不会影响遍历结果。

「基本使用」

初始化指明 index 和 type,然后,加上参数 scroll,表示暂存搜索结果的时间,其它就像一个普通的search请求一样。

会返回一个,用来下次取数据用。

「遍历」

这里的即 上一次遍历取回的或者是初始化返回的,同样的,需要带 scroll 参数。

重复这一步骤,直到返回的数据为空,即遍历完成。

「注意,每次都要传参数 scroll,刷新搜索结果的缓存时间」。另外,「不需要指定 index 和 type」

设置scroll的时候,需要使搜索结果缓存到下一次遍历完成,「同时,也不能太长,毕竟空间有限。」

「优缺点」

缺点:

「优点:」

适用于非实时处理大量数据的情况,比如要进行数据迁移或者索引变更之类的。

ES提供了scroll scan方式进一步提高遍历性能,但是scroll scan不支持排序,因此scroll scan适合不需要排序的场景

「基本使用」

Scroll Scan 的遍历与普通 Scroll 一样,初始化存在一点差别。

需要指明参数:

「Scroll Scan与Scroll的区别」

如果你数据量很大,用Scroll遍历数据那确实是接受不了,现在Scroll接口可以并发来进行数据遍历了。

每个Scroll请求,可以分成多个Slice请求,可以理解为切片,各Slice独立并行,比用Scroll遍历要快很多倍。

上边的示例可以单独请求两块数据,最终五块数据合并的结果与直接scroll scan相同。

其中max是分块数,id是第几块。

官方文档中建议max的值不要超过shard的数量,否则可能会导致内存爆炸。

是 ES 5 新引入的一种分页查询机制,其原理几乎就是和scroll一样,因此代码也几乎是一样的。

「基本使用:」

第一步:

返回出的结果信息 :

上面的请求会为每一个文档返回一个包含sort排序值的数组。

这些sort排序值可以被用于参数里以便抓取下一页的数据。

比如,我们可以使用最后的一个文档的sort排序值,将它传递给参数:

若我们想接着上次读取的结果进行读取下一页数据,第二次查询在第一次查询时的语句基础上添加,并指明从哪个数据后开始读取。

「基本原理」

es维护一个实时游标,它以上一次查询的最后一条记录为游标,方便对下一页的查询,它是一个无状态的查询,因此每次查询的都是最新的数据。

由于它采用记录作为游标,因此「SearchAfter要求doc中至少有一条全局唯一变量(每个文档具有一个唯一值的字段应该用作排序规范)」

「优缺点」

「优点:」

「缺点:」

不是自由跳转到任意页面的解决方案,而是并行滚动多个查询的解决方案。

分页方式性能优点缺点场景from + size低灵活性好,实现简单深度分页问题数据量比较小,能容忍深度分页问题scroll中解决了深度分页问题无法反应数据的实时性(快照版本)维护成本高,需要维护一个 scroll_id海量数据的导出需要查询海量结果集的数据search_after高性能最好不存在深度分页问题能够反映数据的实时变更实现复杂,需要有一个全局唯一的字段连续分页的实现会比较复杂,因为每一次查询都需要上次查询的结果,它不适用于大幅度跳页查询海量数据的分页

参照:http://www.elastic.co/guide/en/elasticsearch/reference/master/paginate-search-results.html#scroll-search-results

在版本中,ES官方不再推荐使用Scroll方法来进行深分页,而是推荐使用带PIT的来进行查询;

从版本开始,您可以使用参数通过上一页中的一组排序值检索下一页命中。

使用需要多个具有相同查询和排序值的搜索请求。

如果这些请求之间发生刷新,则结果的顺序可能会更改,从而导致页面之间的结果不一致。

为防止出现这种情况,您可以创建一个时间点(PIT)来在搜索过程中保留当前索引状态。

在搜索请求中指定PIT:

这种方式虽然能够一定程度上解决深分页问题。但是,它们并不是深分页问题的终极解决方案,深分页问题「必须避免!!」

对于Scroll,无可避免的要维护和历史快照,并且,还必须保证的存活时间,这对服务器是一个巨大的负荷。

对于,如果允许用户大幅度跳转页面,会导致短时间内频繁的搜索动作,这样的效率非常低下,这也会增加服务器的负荷,同时,在查询过程中,索引的增删改会导致查询数据不一致或者排序变化,造成结果不准确。

本身就是一种业务折中方案,它不允许指定跳转到页面,而只提供下一页的功能。

Scroll默认你会在后续将所有符合条件的数据都取出来,所以,它只是搜索到了所有的符合条件的(这也是为什么官方推荐用进行排序,因为本身缓存的就是,如果用其他字段排序会增加查询量),并将它们排序后保存在协调节点(coordinate node),但是并没有将所有数据进行fetch,而是每次scroll,读取size个文档,并返回此次读取的最后一个文档以及上下文状态,用以告知下一次需要从哪个shard的哪个文档之后开始读取。

这也是为什么官方不推荐scroll用来给用户进行实时的分页查询,而是适合于大批量的拉取数据,因为它从设计上就不是为了实时读取数据而设计的。

    以上就是本篇文章【ElasticSearch深度分页解决方案】的全部内容了,欢迎阅览 ! 文章地址:http://ww.kub2b.com/tnews/4303.html
     栏目首页      相关文章      动态      同类文章      热门文章      网站地图      返回首页 企库往资讯移动站 http://ww.kub2b.com/mobile/ , 查看更多   
最新文章
耐水弹力海棉
产品属性用途区域产品包装、耐水 防潮密度0.02-0.18g/cm3原产地中国,江苏,常州品牌D-Foam形状可根据客户提供图纸生产颜色可根
耐水高强度海棉
产品属性用途区域产品包装、耐水 防潮密度0.02-0.18g/cm3原产地中国,江苏,常州品牌D-Foam形状可根据客户提供图纸生产颜色可根
防潮耐水EVA材料
产品属性用途区域产品包装、耐水 防潮密度0.02-0.18g/cm3原产地中国,江苏,常州品牌D-Foam形状可根据客户提供图纸生产颜色可根
耐油耐水海绵
产品属性用途区域产品包装、耐水 防潮密度0.02-0.18g/cm3原产地中国,江苏,常州品牌D-Foam形状可根据客户提供图纸生产颜色可根
供应耐水海绵
产品属性用途区域产品包装、耐水 防潮密度0.02-0.18g/cm3原产地中国,江苏,常州品牌D-Foam形状可根据客户提供图纸生产颜色可根
看了OPPO、vivo的新旗舰手机样张后,决定还是继续用微单吧
最近,OPPO、vivo都给出了自家旗舰手机的样张,大战一触即发。记得手机圈上一次这么火爆,还是小米15 Ultra的时候。具体来说,当
微信借钱不求人,6个步骤轻松搞定...手机微信怎么借钱「微信借钱不求人,6个步骤轻松搞定...」
微信,作为中国人日常生活中不可或缺的社交软件,不仅满足了人们的沟通需求,还悄然融入了金融服务,其中就包括微信借钱功能。无
小米8系列手机,有它才叫防摔保护手机爆屏「小米8系列手机,有它才叫防摔保护」
手机已成为日常生活必备品,而且小米8陶瓷后盖摔不得,维修的费用都赶上半个手机的钱了,选什么手机壳呢,贼难拆的磨砂硬壳?一
米其林指南开启江苏篇章,“江苏味”如何与世界“双向奔赴”
米其林指南作为餐饮界的“奥斯卡”,关注度高。2024年7月,米其林指南重调评价体系,转为省份榜单评选,并官宣江苏省、福建省成
重磅发布!5.4%!
4月16日,国家统计局发布的数据显示,一季度,在以习近平同志为核心的党中央坚强领导下,各地区各部门认真贯彻落实党中央、国务