
先说一下什么是深度分页
假设一个索引test_index(5分片,0副本,有5000w条数据)
在我们查询过程中,from+size默认是不允许超过10000的
所谓from+size超过10000的查询就叫深度分页。
具体怎么讲
假设我们的es集群只有5个节点(node1~node5),那test_index正好每个分片在一个节点上,此时我们要查from(10000)+size(100)的数据(深度分页),ES会怎么做呢
node1:取100100
node2:取100100
node3:取100100
node4:取100100
node5:取100100
再聚合后取其中10000到10100的数据
貌似还好,但是该索引有5000w条数据,那么如果我取from(4000w)+size(100w)呢
如果此时有多个用户这样搞呢,如果此时有多个用户这样搞多个索引呢。。。。。。。,ES一定会崩溃的
所以es默认限制了深度分页查询,from+size最大10000。
有人说,那ES真垃圾,每次最多10000是满足不了业务需求的!!!
也有人会说,不可能,大厂的产品都可以各种翻页~~~
真的吗?,针对两个疑问我们去一探究竟
1、百度、Google(全球最大的搜索引擎),当我们搜索任意内容后会发现
a:每页只有10条数据
b:最下方只有1~10页和下一页,没有跳页选项
c:想看10页以后的内容,最快也是直接跳到第10页,然后可选14页,到14页可选18页,到18页可选22页依此类推,也就是说某个不太聪明的用户想看第5000条数据大概要点123下
这还远没有到ES的深度分页(10000条)标准
2、淘宝、京东、拼多多等
a:每页大约60条数据
b:允许跳页,但是最多到第100页,也就是6000个商品,简言之:您搜了“衣服”看了6000款都没合适的,要不您就去别家看看,要不您就多加点条件再筛选一下,“科比篮球衣”或许您在第一页就能选到了。
c:app端更直接,没有翻页选项,就慢慢往下滑吧
可以看到,大家不约而同的都是为正常人服务,并不会因为某些神仙想看10001条数据就牺牲ES的性能去满足一个非人类需求。
但是但是,本着存在即合理的原则,我们还是要说一下如果一定要深度分页怎么办
1、“max_result_window”:10000,该参数直接控制ES中from+size的最大值,默认就是10000,假设你的数据只有2w条,那经常要查全部数据也没什么问题,该参数改到2w就是了。但是如果你有1000w数据你总要查100100的数据,然后把max_result_window参数设置为100100,那就不太聪明了
2、此时有另一种方法scroll_search(滚动查询),简单的说他可以实现第一次查10000条,第二次查10000到20000,第三次查20000到30000,,,然后一直往后查。
但是该方法官方已经不推荐使用了。
原因有几个
a内存问题:scroll\_search使用了内存中的位置指针,在大数据集上使用时,可能会耗尽内存。
b稳定性问题:scroll\_search可能会遇到网络中断等问题,导致请求失败,而这种失败又无法恢复。
3、从而取代的是search_after,他的原理就是根据a字段排序查询后(a字段的排序必须唯一),得到了第10000条a字段的值,再次查询时在查询条件中带入第10000条a字段的值,就会查出10000到20000条数据,依次类推。
search_after相较于scroll_search的优势:
a内存消耗更小:`scroll_search` 会在内存中缓存所有扫描到的文档,从而可能导致内存消耗过大,而 `search_after` 通过记录游标数据,只需缓存最后一个文档的 `_sort` 值,消耗的内存要比 `scroll_search` 低
b更高的可靠性:`scroll_search` 会在网络断开连接等情况下失败,而 `search_after` 在请求失败时仍然可以通过记录的游标信息继续扫描文档,从而提高了可靠性
最后:实际生产中会结合业务、基建等来具体设定from、size,这里都用10000是举例子,不要较真。





