一:ES的存储和查询原理

Elasticsearch中数据都存储在分片中,当执行搜索时每个分片独立搜索后,数据再经过整合返回

二:如何分页查询呢?

(1)抛出需求问题
按照一般的查询流程来说,如果我想查询前10条数据:
1 客户端请求发给某个节点
2 节点再转发给某个分片,查询每个分片上的前10条
3 各个分片的查询结果返回给节点,然后再整合数据,提取前10条
4 节点再返回给请求客户端
那么当我想要查询第11条到第20条的数据该怎么办呢?这个时候就用到分页查询了。
(2)两种解决方式
1.第一种from-size"浅"分页
概念:"浅分页”是查的页数比较小;"深分页”是查的比较深。
举个例子:百度最多查询前76页,为什么只有76页,而没有第1万页,假如查询第1万页就是深度分页了。

带着为啥百度只能查询76页的疑问,我们分析下浅分页和深分页的原理是什么?
假设每页大小是10条,查第77页761-770条数据。
浅分页的原理就是要查询每个分片上的前77页的前770条数据,然后不要前760条,只返回761-770的数据。这样其实白白浪费了前760条的查询。

查询的方法如:

{"from" : 760, "size" : 10,"query" : {"term" : { "user" : "yao" }}
}

其中,from定义了目标数据的偏移值,size定义当前返回的事件数目。
默认from为0,size为10,即所有的查询默认仅仅返回前10条数据。
性能问题:做过测试,越往后的分页,执行的效率越低。
通过下图可以看出,刨去一些异常的数据,总体上还是会随着from的增加,消耗时间也会增加。而且数据量越大,效果越明显!

也就是说,分页的偏移值越大,执行分页查询时间就会越长
2.第二种scroll“深”分页
相对于from和size的分页来说,使用scroll可以模拟一个传统数据的游标,记录当前读取的数据条数位置。这个分页的用法,缺点是不实时查询数据,优点是一次性查询大量的数据(甚至是全部的数据)。

因为这个scroll相当于维护了一份当前索引段的快照信息,这个快照信息是你执行这个scroll查询时的快照。**为什么不实时?**因为快照没有更新最新的索引,在这个查询后的任何新索引进来的数据,都不会在这个快照中查询到。但是它相对于from和size,不是查询所有数据然后剔除不要的部分,而是记录一个读取的位置,保证下一次快速继续读取。
看到这里,总结下两者的区别
(1)从查询数据的大小来看。form和size是全量查询数据,然后舍弃掉无用数据;scroll是只查询所需数据,因为它有游标记录了位置。
(2)从查询数据的实时性来看。form和size是实时查询;scroll因为快照没有及时更新最新插入数据的索引,es为查询而生,插入不是强项,所有插入都要构建索引。而快照属于拷贝,拷贝之后有新的数据插入并构建了索引,快照并没有及时重新拷贝新的。
如何选择哪种方式进行分页?
(1)使用上的选择,form和size已经满足大部分的需求。form和size每次只能查询1万条。百度的76页,每页6条只有456条数据。对于平时的业务系统每页10条,能够满足查询1000页了,如果超出了1000页,谁会看超出1000页的数据呢?已经没有业务使用意义了,那么肯定是产品定义错了需求,需要页面加过滤条件,比如时间字段,分多次查询几千页,每次看1000页。

API使用方法如:

curl -XGET 'localhost:9200/twitter/tweet/_search?scroll=1m' -d '
{"query": {"match" : {"title" : "elasticsearch"}}
}

会自动返回一个_scroll_id,通过这个id可以继续查询(实际上这个ID会很长哦!):

curl -XGET ‘localhost:9200/_search/scroll?scroll=1m&scroll_id=c2Nhbjs2OzM0NDg1ODpzRlBLc0FXNlNyNm5JWUc1’
注意,我在使用1.4版本的ES时,只支持把参数放在URL路径里面,不支持在JSON body中使用。

测试from&size VS scroll的性能
首先呢,需要在java中引入elasticsearch-jar,比如使用maven:
这里重点不是讲ES的使用,ES8.x已经舍弃了TransportClient 客户端的用法,建议使用Java REST Client客户端,本文中还是用的旧的TransportClient ,这不是重点,重点是知道两种分页方式

<dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>1.4.4</version>
</dependency>

然后初始化一个client对象:

private static TransportClient client;private static String INDEX = "index_name";private static String TYPE = "type_name";public static TransportClient init(){Settings settings = ImmutableSettings.settingsBuilder().put("client.transport.sniff", true).put("cluster.name", "cluster_name").build();client = new TransportClient(settings).addTransportAddress(new InetSocketTransportAddress("localhost",9300));return client;}public static void main(String[] args) {TransportClient client = init();//这样就可以使用client执行查询了}

然后就是创建两个查询过程了 ,下面是from-size分页的执行代码:

System.out.println("from size 模式启动!");
Date begin = new Date();
long count = client.prepareCount(INDEX).setTypes(TYPE).execute().actionGet().getCount();
SearchRequestBuilder requestBuilder = client.prepareSearch(INDEX).setTypes(TYPE).setQuery(QueryBuilders.matchAllQuery());
for(int i=0,sum=0; sum<count; i++){SearchResponse response = requestBuilder.setFrom(i).setSize(50000).execute().actionGet();sum += response.getHits().hits().length;System.out.println("总量"+count+" 已经查到"+sum);
}
Date end = new Date();
System.out.println("耗时: "+(end.getTime()-begin.getTime()));

下面是scroll分页的执行代码,注意啊!scroll里面的size是相对于每个分片来说的,所以实际返回的数量是:分片的数量*size

System.out.println("scroll 模式启动!");
begin = new Date();
SearchResponse scrollResponse = client.prepareSearch(INDEX).setSearchType(SearchType.SCAN).setSize(10000).setScroll(TimeValue.timeValueMinutes(1)) .execute().actionGet();
count = scrollResponse.getHits().getTotalHits();//第一次不返回数据
for(int i=0,sum=0; sum<count; i++){scrollResponse = client.prepareSearchScroll(scrollResponse.getScrollId())  .setScroll(TimeValue.timeValueMinutes(8))  .execute().actionGet();sum += scrollResponse.getHits().hits().length;System.out.println("总量"+count+" 已经查到"+sum);
}
end = new Date();
System.out.println("耗时: "+(end.getTime()-begin.getTime()));

我这里总的数据有33万多,分别以每页5000,10000,50000的数据量请求,得到如下的执行时间:

可以看到仅仅30万,就相差接近一倍的性能,更何况是如今的大数据环境…因此,如果想要对全量数据进行操作,快换掉fromsize,使用scroll吧!

最后总结:ES更新版本很快,1.x,2.x,3.x,4.x,5.x,6.x,我用的6.x

Elasticsearch——分页查询FromSize VS scroll相关推荐

  1. Elasticsearch分页查询FromSize vs scroll vs search_after

    背景 Elasticsearch 是一个实时的分布式搜索与分析引擎,被广泛用来做全文搜索.结构化搜索.分析.在使用过程中,有一些典型的使用场景,比如分页.遍历等.在使用关系型数据库中,我们被告知要注意 ...

  2. elasticsearch 分页查询实现方案——Top K+归并排序

    elasticsearch 分页查询实现方案 1. from+size 实现分页 from表示从第几行开始,size表示查询多少条文档.from默认为0,size默认为10, 注意:size的大小不能 ...

  3. ElasticSearch分页查询几种方式分析

    ElasticSearch分页查询几种方式分析 1 from+size 语句示例 # from+size浅分页 GET test/_search {"from": 10," ...

  4. Elasticsearch 分页查询聚合分析

    分页查询 关于 Elasticsearch 分页查询,这几个问题经常被问到 问题1:想请问下,一次性获取索引上的某个字段的所有值(100 万左右),除了把 max_result_window 调大 , ...

  5. Elasticsearch分页查询Fromamp;Size VS scroll

    对于ES来说,按照一般的查询流程来说,如果我想查询数据: 1 客户端请求发给某个节点 2 节点转发给个个分片,查询每个分片上的前10条 3 结果返回给节点,整合数据,提取前10条 4 返回给请求客户端 ...

  6. ElasticSearch分页查询的3个坑

    点击上方"Java基基",选择"设为星标" 做积极的人,而不是积极废人! 每天 14:00 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java ...

  7. 解决 Elasticsearch 分页查询记录超过10000时异常

    问题一: 查询结果中 hits.total.value 值最大为10000的限制 解决方法: 请求时设置 "track_total_hits": true Rest 请求设置方法: ...

  8. ElasticSearch分页查询四种解决方案与原理

    当你拼命想完成一件事的时候,你就不再是别人的对手,或者说得更确切一些,别人就不再是你的对手了,不管是谁,只要下了这个决心,他就会立刻觉得增添了无穷的力量,而他的视野也随之开阔了.--<基督山伯爵 ...

  9. ElasticSearch 分页查询及深度分页原理与实现

    查询流程 查询阶段 在初始化查询阶段(query phase),查询被向索引中的每个分片副本(原本或副本)广播.每个分片在本地执行搜索并且建 立了匹配 document 的优先队列(priority ...

最新文章

  1. oracle外部表ora29913,从外部表中选择sqlplus错误:ORA-29913:执行ODCIEXTTABLEOPEN标注时出错...
  2. ios和android交互差异,Android 和 iOS 主要交互区别整理
  3. 依存句法分析的任务以及形式化定义
  4. java socket调用接口_java调用websocket接口
  5. Android深入探究笔记--手势识别
  6. 免费资源:Polaris UI套件 + Linecons图标集(AI, PDF, PNG, PSD, SVG)
  7. Centos7安装Docker(二进制)
  8. Swift与OC混编
  9. Stata统计学软件
  10. 干细胞相关研究最新进展(2021年9月)
  11. Excel常用电子表格公式大全
  12. b类 蚂蚁金服_蚂蚁金服开放平台 - 文档中心
  13. Google员工的工作环境
  14. Google Chrome谷歌浏览器去掉右上角更新提示图标
  15. 正规的IT外包公司的报价组成
  16. Floating IP
  17. [矩阵论]欧氏空间的线性变换是正交变换的充要条件是,它对于标准正交基的矩阵是正交矩阵
  18. LeetCode久不久来一题系列之Add Two Numbers
  19. My thoughts through a robot's eyes: An augmented reality-brain–machine interface
  20. 若依微服务框架ruoyi-cloud使用手册(持续更新中)

热门文章

  1. C#中关于“集合已被修改,可能无法操作枚举类型”报错的解决方法
  2. 拼多多根据关键词获取商品列表接口调用展示
  3. 2016.1.6~2017.7.7,袋鼠云一岁半啦
  4. 2022年3月PMP考试时间定了 ---「3月27日」
  5. Stc8硬件乘除法器_16位除16位_汇编
  6. mac下搭建java开发环境:eclipse+tomcat+maven
  7. 软件工程新生需要注意什么?
  8. 请尽快报名参加Imagine Cup 微软“创新杯”全球学生大赛
  9. Windows下virtualbox相关软件安装设置全过程
  10. L2-040 哲哲打游戏 (25 分)