查询结果取交集_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,一经查实,立即删除!

相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

asp绑定gridview属性_如何在ASP.NET Core中自定义Azure Storage File Provider

主题:如何在ASP.NET Core中自定义Azure Storage File Provider作者: Lamond Lu地址: https://www.cnblogs.com/lwqlun/p/10406566.html项目源代码: https://github.com/lamondlu/AzureFileProvider背景ASP.NET Core是一个扩展性非常高的框架…

mysql中为表创建副本_如何为数据库建立一个副本?

展开全部大多情况下,需要可靠而有效地克隆 MySQL 实例e69da5e887aa62616964757a686964616f31333433643663数据。这包括 MySQL 高可用的解决方案,其中需要在将实例加入组复制集群之前配置实例,或者在经典复制模型中将其添加为 Slave。为复制拓…

win10安装mysql5.7.15_win10上如何安装mysql5.7.16(解压缩版)

注:本文涉及的是解压缩版的安装安装教程下载mysql解压缩下载的文件修改ini文件(在解压缩后的mysql文件夹中)实际上修改的是my-default.ini文件在文件中添加如下路径和地址其中的data文件夹是没有的必须自己创建。# These are commonly set, remove the # and set as…

mysql如何备份一个表单_Mysql亿级数据大表单表备份

上一篇Mysql已有亿级数据大表按时间分区,介绍了亿级数据大表如何按时间分区,也留下了一个问题:备份亿级数据大表要耗时多久。本篇将就如何备份亿级数据大表展开讨论。注意:我这里所说的备份指的是数据从一张表拷贝到另外一张表&am…

mysql mos login_MySQL 中常用的函数

一、DATE_FORMAT()需求:按照日期月份统计数据,但数据库存储的格式是 2020-10-01 10:20:45 ,因此需要格式化日期语法:DATE_FORMAT(date,format)第一个参数:指定的日期,第二个参数:需要获取的格式…

需求调研的方法及过程_培训需求调研方法

课程设计与开发是每一位职业培训师都必须会的技能,今天我们就来分享一下如何开发课程。第一节课,让我们先从培训需求调研开始。培训需求调研方法有很多,从个体层次分为:问卷法、观察法、访谈法;从组织层次分为&#xf…

将Go语言开发的Web程序部署到K8S

搭建K8S基础环境 如果已经有K8S环境的同学可以跳过,如果没有,推荐你看看我的《Ubuntu22加Minikue搭建K8S环境》,课程目录如下: Ubuntu22安装Vscode 下载:https://code.visualstudio.com/Download 安装命令&#…

mysql分表 动态扩容_数据库hash分表后的扩容方案

postgres的hash分表不停机扩容方案原来我们hash分表之后,数据扩容采用的是rehash,这样迁移全部的数据,比较麻烦。本次扩容利用hash环原理,并在此基础上做一些适应性的改动。首先假定哈希环的范围为0-1023,总共1024的数…

php mysql长连接聊天室_PHP之探索MySQL 长连接、连接池

PHP连接MysqL的方式,用的多的是MysqL扩展、MysqLi扩展、pdo_MysqL扩展,是官方提供的。PHP的运行机制是页面执行完会释放所有该PHP进程中的所有资源的,如果有多个并发访问本地的测试页面 http://127.0.0.1/1.php 根据PHP跟web服务器的不同,会开…

python 读取地震道头数据_python地震数据可视化详解

本文实例为大家分享了python地震数据可视化的具体代码,供大家参考,具体内容如下准备工作:在windows10下安装python3.7,下载参考源码到本地。1. demo绘图测试demo绘图指令cmd> python seisplot.py --demo问题1)缺少依赖包File &…