一、前言

1.1、scrollfrom+size区别

之前讲过from+size的分页,为何又有scroll+size的深分页呢?这里先对比一下两者的区别;

ES对于from+size的个数是有限制的,二者之和不能超过1w。当所请求的数据总量大于1w时,可用scroll来代替from+size。

from+size在ES查询数据的方式步骤如下:

  • 1、先将用户指定的关键字进行分词;
  • 2、将词汇去分词库中进行检索,得到多个文档的id;
  • 3、去各个分片中拉取指定的数据,相对耗时较长;
  • 4、将数据根据score进行排序,耗时相对较长;
  • 5、根据from,size的值,截取满足条件的查询到的数据;
  • 6、返回结果;

优点:每次都能获取到最新的记录;
缺点:同一个查询,展示另一页的from+size时,以上步骤需要再来一遍;

scoll+size在ES查询数据的方式:

  • 1、先将用户指定的关键字进行分词;
  • 2、将词汇去分词库中进行检索,得到多个文档的id;
  • 3、将文档的id存放在内存的一个ES的上下文中;
  • 4、根据你指定的size的个数去ES上下文中检索指定个数的数据,拿完了数据的文档id,会从上下文中移除;
  • 5、如果需要下一页数据,直接去ES的上下文中,找后续内容;
  • 6、循环第4步,第五步,直到数据都取完了;

优点:数据缓存进了内存,速度快,同一个查询,展示另一页的scoll+size时,只需要循环4,5步;
缺点:冷加载,不适合做实时,当数据更新时,内存中的上下文id数据不会更新;

1.2、Scroll原理

1.2.1、 ES搜索两阶段简介

ES的搜索是分2个阶段进行的,即Query阶段和Fetch阶段。

Query阶段比较轻量级,通过查询倒排索引,获取满足查询结果的文档ID列表。

Fetch阶段比较重,需要将每个shard的结果取回,在协调结点进行全局排序。 通过From+size这种方式分批获取数据的时候,随着from加大,需要全局排序并丢弃的结果数量随之上升,性能越来越差。

1.2.2、 scroll分析

Scroll查询,先做轻量级的Query阶段以后,免去了繁重的全局排序过程。 它只是将查询结果集,也就是doc id列表保留在一个上下文里, 之后每次分批取回的时候,只需根据设置的size,在每个shard内部按照一定顺序(默认doc_id续), 取回这个size数量的文档即可。

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

具体原理分析可参考如下三篇文章:

https://elasticsearch.cn/question/2935 (ES中文社区讨论内容)
https://www.elastic.co/guide/cn/elasticsearch/guide/cn/_fetch_phase.html (query_then_fetch官方文档)
https://www.jianshu.com/p/91d03b16af77 (scroll源码分析)

二、Scroll实践

2.1、依据fee字段和moblie字段倒序按照每一页2条scroll查询公司信息

2.1.1、RESTful 代码

2.1.1.1、步骤1 scoll 查询,返回第一页数据,将ES的id存放在上下文中

参数scroll=2m表示scroll查询的上下文在内存中存放2分钟,不指定默认生存时间为0,当超时,会自动删除上下文,则下面的步骤2和3会查询报错
指定size为2
scroll可以指定字段排序,默认按照文档id排序

POST /sms-logs-index/_search?scroll=2m
{"query": {"match_all": {}}, "size": 2, "sort": [{"fee": {"order": "desc"},"moblie": {"order": "desc"}}]
}

2.1.1.2、步骤2 根据scroll查询下一页数量,再下一页的话再执行下此语句,再下一页再再执行,直到结束或超时;

scroll_id: 指的是上面的查询结果
scroll: 还是要继续指定上下文在内存中缓存2分钟

POST /_search/scroll
{"scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthMWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthQWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthYWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthcWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthUWUl94NU1lek1TZUMzSFMtSzVHWS03UQ==","scroll": "2m"
}

2.1.1.3、 删除scroll在es上下文中的数量

可能我查到第一页就知道了结果,对后面的分页不感兴趣了,我想提前删除scroll中的上下文

DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoBRZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthMWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthQWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthYWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthcWUl94NU1lek1TZUMzSFMtSzVHWS03URZlY3FTZWZGZVNUR0VFQmVMUlVBUmVnAAAAAAAAthUWUl94NU1lek1TZUMzSFMtSzVHWS03UQ==

2.1.2、java 代码

package com.chb.test;import com.chb.utils.ESClient;
import org.elasticsearch.action.search.*;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;import java.io.IOException;public class ScrollDemo {static RestHighLevelClient myClient = ESClient.getClient();  //获取操作ES的String index = "sms-logs-index";@Testpublic void scrollQuery() throws IOException {//1. 创建SearchRequestSearchRequest request = new SearchRequest(index);//2.指定scroll鑫鑫request.scroll(TimeValue.timeValueMinutes(2L));//3.指定查询条件SearchSourceBuilder builder = new SearchSourceBuilder();builder.size(4);builder.sort("fee", SortOrder.DESC);builder.query(QueryBuilders.matchAllQuery());request.source(builder);//4. 获取返回结果scrollId,source的首页信息SearchResponse response = myClient.search(request, RequestOptions.DEFAULT);String scrollId = response.getScrollId();System.out.println("-----------------------首页----------------------------");for (SearchHit hit : response.getHits().getHits()) {System.out.println(hit.getSourceAsMap());}while (true) {//5.循环-创建SearchSrollRequestSearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);//6.指定scrollId的生存时间scrollRequest.scroll(TimeValue.timeValueMinutes(2L));//7.执行查询获取返回结果SearchResponse scrollResp = myClient.scroll(scrollRequest, RequestOptions.DEFAULT);//8.判断这一页是否还有数据,有则输出,没有则跳出循环SearchHit[] hits = scrollResp.getHits().getHits();if (hits != null && hits.length > 0) {System.out.println("-----------------------下一页----------------------------");for (SearchHit hit : hits) {System.out.println(hit.getSourceAsMap());}} else {//9。判断没有查询到数据-退出循环System.out.println("-----------------------结束----------------------------");break;}}//10.创建ClearScrollRequestClearScrollRequest clearScrollRequest = new ClearScrollRequest();//11.指定ScrollIdclearScrollRequest.addScrollId(scrollId);//12.删除ScrollIdClearScrollResponse clearScrollResponse = myClient.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);//13.输出结果System.out.println("删除scroll:" + clearScrollResponse.isSucceeded());}}

关注我的微信公众号【宝哥大数据】,更多干货

ES--深分页Scroll相关推荐

  1. 如何在Elasticsearch中进行深分页

    如何在Elasticsearch中进行深分页 业务背景 在传统业务系统中,一个常见的信息展现方式就是"分页列表",随着数据量的增大,就会遇到"深分页"问题.比如 ...

  2. 实战!聊聊如何解决MySQL深分页问题

    前言 我们日常做分页需求时,一般会用limit实现,但是当偏移量特别大的时候,查询效率就变得低下.本文将分四个方案,讨论如何优化MySQL百万数据的深分页问题,并附上最近优化生产慢SQL的实战案例. ...

  3. MySql深分页问题详解

    MySql深分页问题详解 1. 问题描述 2. 问题分析 3. 验证测试 3.1 创建两个表 3.2 创建两个函数 3.3 编写存储过程 3.4 编写存储过程 3.5 创建索引 3.6 验证测试 4. ...

  4. ES深度分页查询详解

    一.ES支持的三种分页查询方式 From + Size 查询 Scroll 遍历查询 Search After 查询 说明: 官方已经不再推荐采用Scroll API进行深度分页.如果遇到超过1000 ...

  5. ES - 滚动查询(scroll)

    Elasticsearch - 滚动查询scroll 简介 实践中我使用到滚动的场景 from-size分页的缺点 json处理步骤 案例如下 java 处理步骤 代码逻辑 简化版java代码如下: ...

  6. es聚合分页java_ES 实现聚合分页

    注意: es版本至少6.1以上 先看一下es存储的数据情况,我们需要通过pid去重并且实现分页 先贴出Es的代码 { // 这里是对hits的数据进行限制只返回一条数据,因为我不要这里的数据,所以避免 ...

  7. es 聚合分页(group by后分页)

    es 实现sql的 group by后如何分页? 先放json解释,再放纯净版方便copy {"query": {...... //搜索条件},"aggs": ...

  8. MySQL千万数据量深分页优化

    前言 提到MySQL的事务,我相信对MySQL有了解的同学都能聊上几句,无论是面试求职,还是日常开发,MySQL的事务都跟我们息息相关. 而事务的ACID(即原子性Atomicity.一致性Consi ...

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

最新文章

  1. 10个必备的机器学习开源工具
  2. 平衡二叉树及其应用场景
  3. 【网络知识】4. linux抓包工具tcpdump的使用
  4. Ubuntu中重启ssh服务时提示:Job for ssh.service failed because the control process exited with error code. See
  5. STL-容器库101--array【C11】
  6. 计算机usb端口没反应,技术编辑教您电脑usb接口没反应怎么办
  7. iOS统计项目的代码总行数
  8. linux下java程序实现重启功能
  9. 关于thread不能被try catch
  10. MyBatis缓存机制学习
  11. @value注解取不到值_教学笔记:Java注解及自定义注解示例
  12. CakePHP查询数据
  13. CGPathAddArc
  14. 推荐5款好用的Java软件,初学者必看
  15. Arduino-atmega328p最小系统
  16. Git Bash/GUI Here “找不到应用程序问题” 的解决方案
  17. 恶意程序利用Linksys路由器漏洞在路由器中传播
  18. 60 个神级 VS Code 插件,助你打造最强编辑器
  19. 前端模板template-web简单使用
  20. vuepress build error: window is not defined

热门文章

  1. C# 如何更改程序集名称
  2. 计算机基础教学计划百度云,计算机基础教学计划(最新版).doc
  3. python除法编程_Java和Python中的整数除法,取余,舍入
  4. UAAC 访问 Predix UAA 入门
  5. mysql求回购率_回购利率计算方法
  6. 华为mate20参数表_华为的mate20系列参数对比,该选择什么一目了然
  7. Structured-Streaming编程练习知识点
  8. 疯狂的长租公寓:自如、蛋壳们2020的生死决战
  9. iOS 天气应用代码中文介绍
  10. LINUX 查看和修改文件系统的block的大小