es查询-统计总数以及深度分页
一、查询总数
1. ES 查询 hits 统计总数不准?
当我们使用 ES 的时候,有时会比较关心匹配到的文档总数是多少,所以在查询得到结果后会使用 hits.total.value 这个值作为匹配的总数,如下
图一
说明:这是因为,es官方默认限制索引查询最多只能查询10000条数据。
2. track_total_hits
平常数据量不大的情况下,这个数值没问题。但是当超出 10000 个数据量的时候,这个 value 将不会增长了,固定为 10000。这个时候很显然数量统计就不准了。
ES 为我们准备了这样一个参数来开启精确匹配 track_total_hits
这个时候返回值将是精确的:
图二
3. track_total_hits的使用场景
如果你的业务需求在超过 10000 这个阈值之后就不需要精准的计算的话,就不需要设置该值,毕竟匹配大量的文档是一个成本较高的操作,同样的如果你并不需要统计数量,那么将该值设置为 false "track_total_hits": false 也是一种优化检索效率的操作。
4. hits.total.relation
通过图一和图二,可以发现设置 track_total_hits 为 true 的时候返回 relation 的值是不一样的,gte 表示 hits.total.value 是查询匹配总命中数的上限。 eq 则表示hits.total.value 是准确计数。
因此,我们可以通过设置 track_total_hits 为整数,来自定义上限如:
二、查询数据
1. 查询超过10000条数据,开始报错
上面解决了需要统计超过10000条数据总数的问题,但是在查询具体数据的时候依然存在类似的问题。es官方默认限制索引查询最多只能查询10000条数据,查询第10001条数据开始就会报错:
result window is too large, from + size must be less than or equal to
解决方案:
1)第一种办法:在kibana中执行,解除索引最大查询数的限制
put _all/_settings {"index.max_result_window":200000 }
_all表示所有索引,针对单个索引的话修改成索引名称即可。
2)第二种办法:在创建索引的时候加上
1 "settings":{ 2 "index":{ 4 "max_result_window": 500000 5 } 7 }
三、深度分页
做分页查询的时候,我们需要考虑两个问题
- 性能要求,在硬件和查询效率中作出权衡
- 对大部分请求来说,都不会超过10000条,即不需要深度分页,当需要请求超过10000条时,就需要考虑我们的查询语句是否恰当
下面有几种分页方式:
1、方式一: from+size浅分页
"浅"分页可以理解为简单意义上的分页。它的原理很简单,就是查询前20条数据,然后截断前10条,只返回10-20的数据。这样其实白白浪费了前10条的查询。
1 GET test_alias/_search2 {3 "query": {4 "match_all": {5 }6 },7 "sort": [8 {9 "add_time": { 10 "order": "desc" 11 } 12 } 13 ], 14 "from":0, 15 "size": 2 16 }
其中,from定义了目标数据的偏移值,size定义当前返回的数目。默认from为0,size为10,即所有的查询默认仅仅返回前10条数据。
from/size的原理:
因为es是基于分片的,假设有5个分片,from=100,size=10。则会根据排序规则从5个分片中各取回100条数据数据,然后汇总成500条数据后,选择最后面的10条数据。
做过测试,越往后的分页,执行的效率越低。总体上会随着from的增加,消耗时间也会增加。而且数据量越大,就越明显。
说明:from+size查询在10000-50000条数据(1000到5000页)以内的时候还是可以的,但是如果数据过多的话,就会出现深分页问题。
2、方式二: scroll深分页
为了解决上面的问题,elasticsearch提出了一个scroll滚动的方式。
scroll 类似于sql中的cursor,使用scroll,每次只能获取一页的内容,然后会返回一个scroll_id。根据返回的这个scroll_id可以不断地获取下一页的内容,所以scroll并不适用于有跳页的情景。
2.1 参数说明:
- scroll=5m表示设置scroll_id保留5分钟可用。
- size决定后面每次调用_search搜索返回的数量
2.2 scroll删除
根据官方文档的说法,scroll的搜索上下文会在scroll的保留时间截止后自动清除,但是我们知道scroll是非常消耗资源的,所以一个建议就是当不需要了scroll数据的时候,尽可能快的把scroll_id显式删除掉。
1)清除指定的scroll_id:
DELETE _search/scroll/DnF1ZX...
2)清除所有的scroll:
DELETE _search/scroll/_all
然后我们可以通过数据返回的_scroll_id读取下一页内容,每次请求将会读取下10条数据,直到数据读取完毕或者scroll_id保留时间截止。
说明:scroll 的方式,官方的建议不用于实时的请求(一般用于数据导出),因为每一个 scroll_id 不仅会占用大量的资源,而且会生成历史快照,对于数据的变更不会反映到快照上。
3、方式三:search_after 深分页
search_after是ES5.0 及之后版本提供的新特性,search_after有点类似scroll,但是和scroll又不一样,它提供一个活动的游标,通过上一次查询最后一条数据来进行下一次查询。
比如第一次查询如下:
注意到返回结果中有一个sort字段,所以下一次查询的时候,只需要将本次查询最后一条数据中的排序字段加入查询即可:
实现原理:
search_after 分页的方式是根据上一页的最后一条数据来确定下一页的位置,同时在分页请求的过程中,如果有索引数据的增删改查,这些变更也会实时的反映到游标上。
说明:
- 为了找到每一页最后一条数据,每个文档必须有一个全局唯一值,官方推荐使用 _uid 作为全局唯一值,其实使用业务层的 id 也可以。
- 说明:使用search_after查询需要将from设置为0或-1,当然也可以不写。
需要注意的是:
1)sort字段的选择
如果search_after中的关键字为***,那么***123的文档也会被搜索到,所以在选择search_after的排序字段时需要谨慎,可以使用比如文档的id或者时间戳等。另外,search_after并不是随机的查询某一页数据,而是并行的滚屏查询;search_after的查询顺序会在更新和删除时发生变化,也就是说支持实时的数据查询。
2)无法跳页请求
因为每一页的数据依赖于上一页最后一条数据,所以无法跳页请求。
4、方式四: 由前端传入上次查询的最小ID
由于业务需要,我这边实现的分页列表由前端配合一起完成,这样也解决了跳页的问题,供参考:
1 <?php2 3 class Test4 {5 6 public function queryBaiduJobList(array $fileds, int $minId, int $limit)7 {8 // 为了解决es查询默认1w条的上限,由前端传入上一次查询返回列表中最小id:minId9 $query = JobParams::build() 10 ->term('is_check', 1) 11 ->select($fileds) 12 ->trackHits(true) 13 ->sort('id') 14 ->limit($limit); 15 16 if ($minId) { 17 $query = $query->range('id', ['<', $minId]); 18 } 19 20 return $this->all($query); 21 } 22 }
es查询-统计总数以及深度分页相关推荐
- ES 查询示例 搜索 分组 去重 分页 排序
es 查询示例 搜索 分组 去重 分页 排序 java 语句 @Autowiredprivate static RestHighLevelClient client;@PostConstructpub ...
- PageHelper关联查询 统计总数问题
项目场景: 业务:查询功能,需要关联多张表,为一对多或多对多. 需求:要求分页,分页统计总数. 使用技术:Mybatis,PageHelper 问题描述 正常查询一张表的情况下,官方推荐: //获取第 ...
- 【ES】ES 运用search_after来进行深度分页
1.概述 ES本身是支持分页查询的,使用方式跟MySQL非常类似: from: Indicates the number of initial results that should be skipp ...
- ElasticSearch之处理深度分页
ElasticSearch之处理深度分页 一.常规分页 二.scroll分页 三.search_after 在ES中实现分页的方法有三种,我们逐个分析一下他们的优缺点. 一.常规分页 在ES中,我们可 ...
- ElasticSearch 深度分页详解
来源 | OSCHINA 社区 作者 | 京东云开发者-何守优 原文链接:https://my.oschina.net/u/4090830/blog/5593128 1 前言 ElasticSearc ...
- ES深度分页查询详解
一.ES支持的三种分页查询方式 From + Size 查询 Scroll 遍历查询 Search After 查询 说明: 官方已经不再推荐采用Scroll API进行深度分页.如果遇到超过1000 ...
- Mybatisplus 分页查询时,禁止自动统计总数
1.分页插件 使用 Mybatisplus 时 ,我们使用 PaginationInnerInterceptor 作为分页插件,它会帮助我们进行分页,查询总数. @Configuration @Map ...
- ElasticSearch 分页查询及深度分页原理与实现
查询流程 查询阶段 在初始化查询阶段(query phase),查询被向索引中的每个分片副本(原本或副本)广播.每个分片在本地执行搜索并且建 立了匹配 document 的优先队列(priority ...
- 上亿数据怎么玩深度分页?兼容MySQL + ES + MongoDB
面试题 & 真实经历 面试题:在数据量很大的情况下,怎么实现深度分页? 大家在面试时,或者准备面试中可能会遇到上述的问题,大多的回答基本上是分库分表建索引,这是一种很标准的正确回答,但现实总是 ...
最新文章
- 悠然乱弹:聊聊模块化
- python 散点图_Python绘制散点图
- KPCR:CPU控制区(Processor Control Region)
- 【图像处理】——傅里叶变换、DFT以及在图像上的应用
- java与java ee_RxJava + Java8 + Java EE 7 + Arquillian =幸福
- java 递归从子节点删除父节点_LeetCode450. 删除二叉搜索树中的节点
- Hash (散列,哈希)
- [视频]Silverlight for Windows Phone 7基本开发过程以及Push Button控件的使用
- c# 网口相机可以通过_双网口硬盘录像机怎么设置?录像机连接GB28181公安专网步骤指导...
- iOS9 开发新特性 Spotlight使用
- Android手机使用Windows应用,微软宣布在你的手机应用上运行安卓APP功能向Windows 10稳定版提供...
- springboot 配置过滤器不起作用的原因
- 正则表达式匹配第一个单个字符
- 孪生网络图像相似度_图像相似度比对
- 多多客id是什么意思_拼多多skuid是什么意思(关于sku编码的详细介绍)
- Win10+Android+夜神安卓模拟器 搭建ReactNative开发环境
- 好未来 Dolphin-儿童口语表达能力AI自动评测:顶尖AI算法技术与教育理念的有机结合 | 百万人学AI评选
- 如何建立简易Rss源
- RabbitMq中的mandatory
- 智能称体脂称实现(基本原理解释篇)
热门文章
- VSCode快捷键冲突?关掉微软拼音的简繁体切换热键即可
- 使用HMMER搜索PFam
- python kfold交叉验证_KFold交叉验证
- 求n的阶乘的算法框图_当代程序员必备技能(算法)之:递归详解 - Java斗帝之路...
- 弱网测试NEWT-----Network Emulator for Windows Toolkit
- Fast-MoCo: Boost Momentum-based Contrastive Learning with Combinatorial Patches
- python 路边停车
- Python爬虫爬取手机APP的数据
- 用python处理水仙花数
- js indexOf使用及注意事项以及数组使用indexOf