查询结果取交集_Elasticsearch 查询过程中的 prefilter 原理

大家都知道在对索引执行查询的时候,需要在所有的分片上执行查询,因为无法知道被查询的关键词位于哪个分片,对于全文查询来说诚然如此,然而对于时序型的索引,当你从 my_index-* 中执行 now-3d 的范围查询时,可能很多分片上都不存在被查询的数据范围,因此 es 从 v5.6 开始引入了 pre-filter 机制:对于 Date 类型的 Range 查询,在对分片执行搜索之前,先检查一下分片是否包括被查询的数据范围,如果查询的范围与分片持有的数据没有交集,就跳过该分片。

分布式搜索过程原先由两个阶段执行:查询阶段和取回阶段,在引入了 pre-filter 之后,分布式搜索过程变成了三个阶段:预过滤阶段(pre-filter)、查询阶段和取回阶段。pre-filter 在查询阶段之前执行。

协调节点收到客户端的查询请求后,向本次搜索涉及到的全部分片发送RPC 请求:

indices:data/read/search[can_match]

这次 RPC 请求以 shard 为单位并行发送,没有并发限制。待查询的 shard 有多少个,就并发发送多少个 RPC。然后等待全部 RPC 返回响应。

tips
此时发送的 RPC 请求没有超时限制。事实上,_search 请求的 timeout参数仅在整个分布式搜索的 query 阶段进行检查,并且不包括 PRC 层面,他只在数据节点收到协调节点发来的 RPC 后开始计时,检查 query 过程是否超时。fetch 阶段的 RPC,以及数据节点对 fetch 请求的处理均没有超时检查。

节点收到请求后,判断请求的范围和待查询的分片是否存在交集,返回是或否,然后协调节点跳过不存在交集的分片,向其他分片发送下一阶段(查询阶段)的请求。

本次查询跳过了多少分片可以通过查询结果中的 skipped 字段看到,如:

"_shards":{
"total": 130,
"successful": 130,
"skipped": 129,
"failed": 0
}

同时也来看一下手册对 skipped 字段的解释:

skipped
(Integer) Number of shards that skipped the request because a lightweight check helped realize that no documents could possibly match on this shard. This typically happens when a search request includes a range filter and the shard only has values that fall outside of that range.

什么情况下会执行 pre-filter

pre-filter 并不会在所有查询过程中执行,在 v7.4中,需要同时满足以下条件,才会执行 pre-filter :

  • 待查询的分片数大于 128(pre_filter_shard_size指定)

  • 聚合请求不要求访问所有 doc。即非 Global Aggregation 或 "min_doc_count" 不为0

另外,非 Date 类型的数值查询虽然也会走 pre-filter流程,但内部不会去判断范围,虽然协调节点也会发送 can_match 的 RPC,但数据节点的响应会在 MappedFieldType#isFieldWithinQuery 中直接返回相交,所以没有分片会被 skip,未来这方面可能会有扩展。

pre-filter 实现原理

数据节点判断某个 Range 查询与分片是否存在交集,依赖于 Lucene 的一个重要特性:PointValues 。在早期的版本中,数值类型在 Lucene 中被转换成字符串存入倒排索引,但是由于范围查询效率比较低,从 Lucene 6.0开始,对于数值类型使用 BKD-Tree 来建立索引,内部实现为 PointValues。PointValues原本用于地理位置场景,但它在多维、一维数值查询上的表现也很出色,因此原先的数值字段(IntField,LongField,FloatField,DoubleField)被替换为(IntPoint,LongPoint,FloatPoint,DoublePoint)

关于 BKD-Tree 的性质请参阅其他资料,暂且只需要知道 Lucene为每个字段单独建立索引,对于数值字段生成 BKD-Tree,一个新的 segment 生成时会产生一个新的.dim和.dii文件。最重要的,可以获取到这个 segment 中数值字段的最大值和最小值,为 pre-filter 提供了基础。当 segment 被 reader 打开的时候,Lucene 内部的 BKDReader 会将最大值和最小值读取出来保存到类成员变量,因此每个 segment 中,每个数值字段的最大最小值都是常驻 JVM 内存的。

既然每个 segment 记录了数值字段的取值范围,获取shard 级别的范围就轻而易举:PointValues.getMaxPackedValue(),PointValues.getMinPackedValue(),函数遍历全部的 segment 分别计算最大值和最小值,然后根据查询条件判断是否存在交集,在 DateFieldMapper.DateFieldType#isFieldWithinQuery 函数中:

c2ccb1841897f0742811de86d983b880.png

既然数值类型都可以获取分片级别的范围,为什么 pre-filter 只在 Date 类型的Range 查询里实现了,而其他的数值类型的 Range 查询不会走 pre-filter 流程?原因也非常简单,只有 Date 类型的数值确定是递增的,其他数值类型未必。对于非递增的数值字段,其数据会散布到 my_index-* 的每个分片上,因此 pre-filter 也就没有必要了。如果你有另外一个递增的数值字段,目前也没有配置的方式来使用 pre-filter。

题外话:BKD-Tree 的每个节点都记录了节点自己的maxPackedValue、minPackedValue

Lucenene 内部查询的也会按照 segment file 级别跳过

现在我们忘掉 es,讨论数值类型查询在 Lucene 内部的实现。

HBase 的写入模型和 Lucene 类似,先写内存,然后刷盘生成 HFile,HFile 合并成大文件。由于 HBase 使用时间戳作为数据版本号,因此每个 HFile 都记录了时间范围。因此查询的时候如果指定时间范围,就可以过滤掉大量的 HFile 不用查询。这么优秀的操作在 Lucene 中也必不可少。

在一个 Lucene 索引中可能有很多 segment,Lucene遍历所有的 segment 进行处理,在对每个 segment 的 weight.bulkScorer过程中,BKDReader.intersect函数根据相交情况决定收集符合条件的 docid,如果查询条件和 segment 没有交集,就什么都不做。

c4a0f47f7d24d82182775e07fceb5868.png

因此当对数值类型查询的时候,不在范围的 segment 会直接跳过,Lucene 内部称为:CELL_OUTSIDE_QUERY

但是,段合并的时候目前还不会考虑按时间临近的方式进行合并,因此借鉴 HBase 的思想按照时间临近的段进行合并有助于降低数值类型的范围查询耗时。

思考

既然 Lucene 对数值类型有 segment 级别的skip,Elasticsearch 实现的分片层面的 pre-filter 还有必要存在吗?他可以让搜索延迟更低么?我们实际测试来说话。过程如下:

生产集群有 filebeat-* 索引,数据为 nginx 日志,大约8T,有180个shard,11227个 segment,分布在3个节点。

step1:我们对 date 字段执行一个不会命中的查询,让他走 pre-filter 流程:

POST filebeat-7.4.2-*/_search
{
"size":0,
"query": {
"range": {
"@timestamp": {
"gte": "2021-01-01",
"lte":"2022-01-01"
}
}
}
}

返回结果摘要如下,整个过程执行了31ms:

{
"took" : 31,
"timed_out" : false,
"_shards" : {
"total" : 180,
"successful" : 180,
"skipped" : 179,
"failed" : 0},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"}}

step2:现在加上 ?pre_filter_shard_size=1000 参数重新查询,其他条件不变,让查询过程不走 pre-filter,返回结果如下,整个过程执行了31ms,可见没什么区别:

{
"took" : 23,
"timed_out" : false,
"_shards" : {
"total" : 180,
"successful" : 180,
"skipped" : 0,
"failed" : 0},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"}}}

step3:最后我们对 long 字段执行 range 查询,这样也不走 pre-filter 流程:

POST filebeat-7.4.2-*/_search?size=0
{
"query": {
"range": {
"nginx.bytes.body_sent": {
"gte": -2,
"lte":-1
}
}
}
}

这次查询执行了50ms,还是在一个数据级。

{
"took" : 50,
"timed_out" : false,
"_shards" : {
"total" : 180,
"successful" : 180,
"skipped" : 0,
"failed" : 0},
"hits" : {
"total" : {
"value" : 0,
"relation" : "eq"}}}

因此 pre-filter并不会降低查询延迟,在和官方聊过之后,他们的想法是 pre-filter 最主要的作用不是降低查询延迟,而是 pre-filter 阶段可以不占用search theadpool,减少了这个线程池的占用情况。个人感觉这个收益并不大。不过未来会在这个阶段做更多的查询优化, 例如7.6中放出的 #49092,#48681

特别感谢:陆徐刚@蚂蚁

基于:Elasticsearch 7.4 & 7.6

参考

https://github.com/elastic/elasticsearch/pull/25658
https://www.amazingkoala.com.cn/Lucene/Search/2020/0427/135.html
https://lucene.apache.org/core/6_2_1/core/org/apache/lucene/index/PointValues.html
http://www.nosqlnotes.com/technotes/searchengine/lucene-invertedindex-3/
https://www.jianshu.com/p/39eb0d66d082
https://cloud.tencent.com/developer/article/1366835
https://www.elastic.co/guide/en/elasticsearch/reference/current/release-notes-7.6.0.html#

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/530048.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机专业人毕业设计外文翻译,计算机专业毕业设计外文翻译.doc

《计算机专业毕业设计外文翻译.doc》由会员分享,提供在线免费全文阅读可下载,此文档格式为doc,更多相关《计算机专业毕业设计外文翻译.doc》文档请在天天文库搜索。1、近几年来,随着计算机的普及和建筑电子产业的发展…

语音识别插件_AnsweringMachine XS: 越狱理由之二,iPhone 电话语音答录机

Apps & Tweaks| Jailbreak Guide| iDevicesTweak:AnsweringMachine XSVersion:XSRepo:http://limneos.net/iOS Support:12-13Price:3.99iOS 开发人员 Elias Limneos 开发了电话辅助系列插件,AnsweringM…

怎么在计算机里找到CF里保存的视频,电脑怎么查看穿越火线录制保存视频?操作方法...

在Win10电脑上玩穿越火线,遇到精彩时刻我们都会录制下,好跟朋友分享,但是在Win10电脑上穿越火线录制保存之后的视频,在哪看呢?有很多用户都不知道怎么在Win10电脑查看这个穿越火线录制保存的视频,这个的话&#xff0c…

ironpython this_IronPython sys._getframe not found

问题Im currently building a program in C# which will call functions in provided python script files.Some of these script files calls _getframe() in sys, which results in the error:System.MissingMemberException: module object has no attribute_getframe(Since…

计算机账务处理流程图,账务处理流程图

手工业务流程图账务处理流程主要有 5 种形式:记账凭证核算形式、科目汇总表核算形式、汇总记账凭证核算形式、日记总账核算形式、和多栏式日记账核算形式。不同的账务处理流程其差别主要体现在登记总账的方法和依据不同,其中科目汇总表核算形式最为常见&…

css滑动门的用处,CSS滑动门是什么?有什么用处?[web前端培训]

在制作网页导航时,经常会碰到导航栏长度不同,但背景相同的情形。此时如果通过拉伸背景图的方式来适应文本内容,就会造成背景图变形。在制作网页时,为了使各种特殊形状的背景能够自适应元素中的文本内容,并且不会变形&a…

vue 父链和子组件索引_vuejs填坑-父子组件之间的访问

有时候我们需要父组件访问子组件,子组件访问父组件,或者是子组件访问根组件。1. 父组件访问子组件 $children或$ref$children 返回所有子组件的实例,是一个数组显示两个组件的信息{{ msg }}{{ msg }}Vue.component(child1, {template: #child…

python多线程爬取多个网页_python多线程爬取网页

#-*- encoding:utf8 -*-‘‘‘Created on 2018年12月25日author: Administrator‘‘‘from multiprocessing.dummy import Pool as plimport csvimport requestsfrom lxml import etreedef spider(url):header {"User-Agent":"Mozilla/5.0 (Windows NT 6.1; WO…

layui 分页ajax,实现Ajax异步的layui分页

页面代码:人才推荐姓名学历技能经验住址联系方式 ${res}${data}于千万年之中时间的无涯的荒野里…时间的无涯的荒野里…--%>js代码//加载完成$(function(){var sherchkey${positioninfo.name};savePosition();//保存修改方法getPeopleList(1,5,sherchkey);//获取人才列表// …

Gen系列服务器,新计算、新体验 | 新华三全新HPE Gen10系列服务器响彻“云”端

数字经济时代的数据中心正在加速向云计算融合,用户将面临传统架构与云架构并存的混合IT模式。如何既拥有专有数据中心对数据完全可控以及对关键业务充分优化的优势,又能拥有云计算的灵活弹性?如何有效利旧并满足混合IT架构的需求?…

python 异常处理 变量_Python基础入门:从变量到异常处理

一 . 条件语句1.if-else 语句当if语句后的条件结果表达式为假&#xff0c;则执行else 语句后的代码。如若输入数字非666&#xff0c;则会输出“猜错了&#xff0c;小姐姐现在心里想的为666“2.if 语句支持嵌套hi6 hi>2 执行 if hi>7 6<7 所以无输出hi1 hi<2 执行 p…

web系统四层结构中服务器端,基于.NET平台构建四层B/S结构的动态网站

摘要&#xff1a;Web是基于Internet技术的一种应用层服务,具有后台数据库支持的n层B&#xff0f;S结构已经成为动态Web应用的主流。虽然动态网站开发工作的主要是进行服务器端应用程序的开发,但是B&#xff0f;S结构动态Web的应用要涉及浏览器、Web服务器、服务器端应用程序、数…

收藏功能_微软Edge获得了新的收藏夹菜单、PDF功能等

作为其今年早些时候概述的战略的一部分&#xff0c;微软Edge现在正在向所有Windows 10 PC推出。与经典的Edge不同&#xff0c;Chromium Edge与任何特定的Windows更新无关&#xff0c;但微软又开始为该浏览器进行了一系列令人兴奋的改进。新的Edge基于Chromium&#xff0c;它还带…

服务器LIMIT是什么信号,Postfix添加milter-limit配置方案

[安装环境]操作系统&#xff1a;CentOS 5.6MAT&#xff1a;POSTFIX2.8.4安装之前必须保证POSTFIX能正常收发信如果已经安装过Berkeley Db3以上版本可以不安装新的DB(但是注意引入db.so)[安装步骤]1、milter-limit-0.14.tar.gz及libsnert-1.71.6.tar.gz包的获取方法需要创建一个…

数据存储方式_视频监控系统的数据存储方式的概念及应用

DAS&#xff1a;直连存储&#xff0c;直连式存储与服务器主机之间的连接通常采用SCSI连接&#xff0c;SCSI通道是IO瓶颈;服务器主机SCSI ID资源有限&#xff0c;能够建立的SCSI通道连接有限。无论直连式存储还是服务器主机的扩展&#xff0c;从一台服务器扩展为多台服务器组成的…

ubuntu18 防火墙关闭_Ubuntu 18.04 关闭及开启防火墙

Ubuntu 内建使用 UFW (Uncomplicated Firewall) 作为防火墙管理工具, 一般情况下都会开启防火墙, 但有些特殊情况, 例如测试环境需要关闭防火墙作测试, 或者对网络设定进行除错等。以下是在 Ubuntu 18.04 关闭防火墙的方法。首先检查目前防火墙是否已经开启, 执行以下指令:$ su…

vue从url中获取token并加入到 请求头里_轻流amp;amp;企业微信——获取打卡数据...

企业微信开放了打卡应用的api&#xff0c;功能包括查询打卡数据&#xff0c;能获取到用户、地点、时间、打卡类型等信息&#xff0c;在轻流中可以基于以上数据做一段时间内的迟到/事假等统计&#xff0c;以及更深层数据处理&#xff0c;方便管理。第一步&#xff1a;获取access…

单片机串口通信学号显示_触摸屏与单片机串口通信测试

工业现场在使用触摸屏的时候&#xff0c;与第三方控制器进行通信连接的时候&#xff0c;一般都是使用成熟的通信协议进行通信连接。而这些协议的实现过程&#xff0c;触摸屏厂商也已经在编程环境中进行了封装集成&#xff0c;对于使用的工程师来说&#xff0c;通信的数据交换过…

2020笔记本性价比之王_2020轻薄本性价比之王_2020轻薄本哪款好

随着科技的进步&#xff0c;如今笔记本的功能愈发强大&#xff0c;接听电话、开展商务会议等&#xff0c;因此现在人们对于笔记本电脑的依赖程度愈发明显。厚重的商务本和游戏本显然不适合随身携带&#xff0c;因此轻薄本的出现受到白领们的广泛吹捧&#xff0c;那么2020哪款轻…

scp命令默认传输速度多大_每天一个linux命令(60):scp命令

scp是secure copy的简写&#xff0c;用于在Linux下进行远程拷贝文件的命令&#xff0c;和它类似的命令有cp&#xff0c;不过cp只是在本机进行拷贝不能跨服务器&#xff0c;而且scp传输是加密的。可能会稍微影响一下速度。当你服务器硬盘变为只读 read only system时&#xff0c…