ES慢查询分析——性能提升6 倍

news2024/11/20 13:45:41

问题

        生产环境频繁报警。查询跨度91天的数据,请求耗时已经来到了30+s。报警的阈值为5s。

背景

查询关键词简单,为‘北京’

单次仅检索两个字段

查询时间跨度为91天,覆盖数据为450亿数据

问题分析

使用profle分析,复现监控报警的语句,确实慢。集群分片太多,这里放一个分片的内容。

 {
        "id" : "[YWAxM5F9Q0G1PXfTtYZKkzQ][_20230921-000001][3]",
        "searches" : [
          {
            "query" : [
              {
                "type" : "FunctionScoreQuery",
                "description" : "function score (+((title:北京)^2.0 | content:北京) +publish_time:[1687431307000 TO 1695254417999] +es_insert_time:[-9223372036854775808 TO 1703084327999], functions: [{scriptScript{type=stored, lang='null', idOrCode='search-score', options=null, params={}}}])",
                "time" : "10s",
                "time_in_nanos" : 10079315883,
                "breakdown" : {
                  "set_min_competitive_score_count" : 0,
                  "match_count" : 150,
                  "shallow_advance_count" : 0,
                  "set_min_competitive_score" : 0,
                  "next_doc" : 2646164,
                  "match" : 996954485,
                  "next_doc_count" : 154,
                  "score_count" : 31,
                  "compute_max_score_count" : 0,
                  "compute_max_score" : 0,
                  "advance" : 1035917137,
                  "advance_count" : 16,
                  "score" : 3532211704,
                  "build_scorer_count" : 40,
                  "create_weight" : 3965124112,
                  "shallow_advance" : 0,
                  "create_weight_count" : 1,
                  "build_scorer" : 546462281
                },

 

在Elasticsearch Profile API结果中,主要关注查询的timebreakdown字段,这提供了查询执行的总时间和各个步骤的时间分解。在这个例子中,查询的总时间为10秒。

具体来看,主要的时间花费在FunctionScoreQuerycreate_weight步骤上,该步骤耗时为3,965,124,112纳秒(大约3.97秒)。create_weight是在查询执行之前创建用于评分的权重的阶段。

以下是一些步骤的关键信息:

  • create_weight步骤耗时最长,可能是性能瓶颈。
  • build_scorer步骤也占用了大量时间,这通常是评分过程中的一个重要步骤。
  • next_doc步骤的时间比较大,这可能涉及到遍历文档的过程。

疑问?为什么 create_weight 过程耗时会这么长

从我的查询条件来看,请求是很简单的,没有复杂的条件,为什么 create_weight 过程耗时会这么长?

create_weight阶段的耗时主要取决于查询中使用的权重计算方式以及索引的结构和数据量。在你提供的Profile API结果中,create_weight的耗时非常大,说明这个步骤在整个查询过程中占用了大量的时间。

有几个潜在的原因可能导致create_weight步骤的性能下降:

  1. 脚本复杂性: 如果你在Function Score Query中使用了复杂的脚本,脚本的执行可能会消耗大量的时间。检查你的脚本逻辑,尽量确保它是高效的。
  2. 文档数和大小: 如果你的索引中包含大量的文档或者文档非常大,创建权重可能会变得更加耗时。在这种情况下,考虑优化索引结构、调整分片数量等。
  3. Function Score Query的配置: 如果在Function Score Query中使用了复杂的函数或者过多的函数,计算每个文档的权重可能会更加耗时。检查你的Function Score Query配置,确保它符合你的需求。

create_weight 究竟在干什么,源码?

这里主要是lucene去IO底层文件。这里比较明显的是性能问题。

第一个尝试,去掉脚本排序

脚本排序的时间会算在create_weight过程中(猜想,待验证)

测试把我的搜索条件,去掉脚本排序。原来是15s,现在是10s,脚本排序的耗时在我请求中,占据了30%多。

继续分析慢查询的分片

其中,耗时最长的分片还是,create_weight 过程耗时最严重。

耗时发生在我的title字段上的这个子查询上。

调整terminate_after  从200->10

检索耗时进一步降低。

其中还是有耗时长的个别分片

整个请求6.2s,在这个分片上的请求就花了6s,并且时间还是花在了create_weight上。

如何才能降低create_weight的耗时?

降低terminate_after的值可以降低,代价是影响整体的排序效果。

减少段的个数,可以减少耗时。通过段合并。因为可以减少段的遍历。

 

疑问?是不是在查询的时候负载高?

GET _cat/nodes?v

问题解决方案

动态调整terminate_after

  并非所有的请求,都需要每个分片都200条数据。特别在大的时间跨度下,分片可能会非常多,动辄几千个,以2000个分片算,最多会匹配2000*200=400000数据。加上脚本排序,这40W数据,都需要参与分数的计算,最终才能角逐出top20的数据。最终的结果是请求耗时长。

  实际上,terminate_after的取值,是可以动态调整的。检索分为乐观和悲观情况,乐观情况下,数据分布是均匀的,在分片上分配是均匀的,且检索条件命中的数据较多。在悲观情况下,检索的数据分布不均匀,且搜索的条件比较特殊,命中的数据很少,或者命中的数据在分片上分布不均匀。

  大多数情况下,数据分布是均匀的,检索的数据量越大,分布可能越均匀。例如检索3个月,总数据大约450亿数据,随便一个搜索条件,搜索的数据大概率是大于10000条的。所以可以设计一个动态调整方案,来调整terminate_after的取值,能够获取更好的性能,提升200%-300%。另外需要一个悲观情况下的担保机制,避免在悲观情况下检索丢失数据。

  terminate_after的值是限定在分片上的,假如一个索引有10个分片,如果设置terminate_after为200,则最后返回的数据总量为 10*200=2000条。考虑到分页为500页,每页20条数据,共计可以翻页10000条数据。如何设置terminate_after的值呢?要考虑到翻页的情况。

  请求的入参,一般包含了翻页和每页的条数。 期望数据总量= 页码* 每页的数量。  es的召回总量为= 分片数*terminate_after数量*偏差。偏差可以算0.1,预期10倍可以弥补数据分布不均匀带来的影响。分片数暂时可以按每天15个来算。 页码* 每页的数量 = 分片数*terminate_after数量*偏差 。可以得出  terminate_after数量 = 页码* 每页的数量 / (分片数*偏差)。terminate_after数量不足10则向上取正为10。 当查询的天数小于7天,则可以直接取值为200。

  担保机制,需要解决悲观情况下的问题。根据es返回的数据总量。 如果返回的数据总量小于期望的数据总量,则触发担保机制。需要调大terminate_after的值(暂定为500),再去搜索一次。

索引段合并

  段合并可以提升减速效果。

最终的检索效果

检索条件

检索耗时情况

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

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

相关文章

Go在Win10上接收UDP组播数据

第一步、绑定本机某张网卡的IP和端口,本代码选择IP为0.0.0.0,端口为8000;第二步、加入组播,组播地址为“224.0.0.1”;第三步、循环接收UDP组播数据; 代码 package mainimport ("fmt""golang…

从 Linux Crontab 到 K8s CronJob,定时任务正在经历怎样的变革

作者:黄晓萌(学仁) 背景 Job 表示短周期的作业,定时 Job 表示按照预定的时间运行Job,或者按照某一频率周期性的运行 Job。比如: 许多传统企业使用 Linux 自带的 crontab 来做定时任务的方案,该方案非常简单&#xff…

“巴渝工匠杯”2022年重庆市职业院校技能大赛(高职组)云计算样题

“巴渝工匠杯”2022年重庆市职业院校技能大赛(高职组)云计算样题 需要软件包环境可私信博主 【赛程名称】云计算赛项第一场次-私有云 某企业拟使用OpenStack搭建一个企业云平台,以实现资源池化弹性管理、企业应用集中管理、统一安全认证和授…

PostGIS学习教程十五:几何图形的有效性

PostGIS学习教程十五:几何图形的有效性 在90%的情况下,“为什么我的查询给了我一个’TopologyException’错误"的问题的答案是"一个或多个输入的几何图形是无效的”,这就引出了这样一个问题:几何图形"无效"是什么意思&a…

从计算机内存结构到iOS

一、冯.诺伊曼结构 当前计算机都是冯.诺伊曼结构(Von Neumann architecture),是指存储器存放程序的指令以及数据,在程序运行时根据需要提供给CPU使用。 冯.诺伊曼瓶颈 在目前的科技水平之下,CPU与存储器之间的读写速…

【C Primer Plus第六版 学习笔记】第十四章 结构和其他数据形式

有基础,进阶用,个人查漏补缺 建立结构声明:描述该对象由什么组成,即结构布局 格式: 关键字 标记(可选){结构 }; 举例: struct book{char title[2];char author[4];float …

Xcode 编译速度慢是什么原因?如何提高编译速度?

作为一个开发者,我们都希望能够高效地开发应用程序,而编译速度是影响开发效率的重要因素之一。然而,有时候我们会发现在使用 Xcode 进行开发时,译速度非常慢,这给我们带来了不少困扰。那么,为什么 Xcode 的…

分页合理化是什么?

一、前言 大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。 只要是干过后台系统的同学应该都做过分页查…

神经网络介绍

目录 知识点介绍 知识点介绍 前馈神经网络:(前馈网络的数据只向一个方向传播) RNN循环神经网络,下图中多个 RNN 层都是“同一个层”,这一点与之前的神经网络是不一样的。

怎么下载landsat 8影像并在ArcGIS Pro中进行波段组合

Landsat 8(前身为Landsat数据连续性任务,或 LDCM)于2013年2月11日由 Atlas-V火箭从加利福尼亚州范登堡空军基地发射升空,这里为大家介绍一下该数据的下载的方法,希望能对你有所帮助。 注册账号 如果之前已经注册过的…

5、IDEA集成Git

IDEA集成Git 1. 配置Git忽略文件2. 定位Git程序3. 初始化本地库、添加暂存区、提交到本地库4. 切换版本5. 创建分支和切换分支6. 合并分支7. 解决冲突 1. 配置Git忽略文件 问题1:为什么要忽略他们? 与项目的实际功能无关,不参与服务器上部署…

学习笔记12——Spring的注解配置

学习笔记系列开头惯例发布一些寻亲消息 链接:https://baobeihuijia.com/bbhj/contents/3/192486.html SSM框架——注解配置(Component Autowired 加载SpringConfig) 注解开发(Component注解、config扫描 加载SpringConfig&a…

https密钥认证、上传镜像实验

一、第一台主机通过https密钥对认证 1、安装docker服务 (1)安装环境依赖包 yum -y install yum-utils device-mapper-persistent-data lvm2 (2)设置阿里云镜像源 yum-config-manager --add-repo http://mirrors.aliyun.com/do…

EB tresos 配置I2c - 实现与PF8200的读写操作

文章目录 前言一、EB工具链配置1、I2c模块1)新建模块2)配置General3)配置I2cChannel 2、Port模块1)配置SDA2)配置SCL 二、代码分析1、申明一个I2c配置结构体数组,用于I2c所有读操作。2、搭建读操作函数 三、…

GitLab 删除或移动项目

首先明说,删除后无法恢复 第一步:找到要删除的项目 第二步:进入目录后,左侧菜单,设置 >>> 通用,拉到最下面找到“高级”,点击右侧“展开” 第三步:点击“展开”后往下拉&a…

亚马逊云科技 re:Invent 2023 产品体验:亚马逊云科技产品应用实践 王炸产品 Amazon Q,你的 AI 助手

意料之中 2023年9月25日,亚马逊宣布与 Anthropic 正式展开战略合作,结合双方在更安全的生成式 AI 领域的先进技术和专业知识,加速 Anthropic 未来基础模型的开发,并将其广泛提供给亚马逊云科技的客户使用。 亚马逊云科技开发者社…

Python 实现Excel和CSV之间的相互转换

通过使用Python编程语言,编写脚本来自动化Excel和CSV之间的转换过程,可以批量处理大量文件,定期更新数据,并集成转换过程到自动化工作流程中。本文将介绍如何使用第三方库Spire.XLS for Python 实现: 使用Python将Exc…

ServletConfig对象.

是什么 ServletConfig是javax.servlet.包下的一个接口,ServletConfig它是Servlet的一个配置对象; ServletConfig是由tomcat容器创建,通过init方法传入给Servlet; ServletConfig对象如何获取? 在GenericServlet里面定义了&#x…

根据DCT特征训练CNN

记录一次改代码的挣扎经历: 看了几篇关于DCT频域的深度模型文献,尤其是21年FcaNet:基于DCT 的attention model,咱就是说想试试将我模型的输入改为分组的DCT系数,然后就开始下面的波折了。 第一次尝试&#xf…

【SpringCloud】-OpenFeign实战及源码解析、与Ribbon结合

一、背景介绍 二、正文 OpenFeign是什么? OpenFeign(简称Feign)是一个声明式的Web服务客户端,用于简化服务之间的HTTP通信。与Nacos和Ribbon等组件协同,以支持在微服务体系结构中方便地进行服务间的通信&#xff1b…