首页 > 其他分享 >ES慢查询分析——性能提升6 倍

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

时间:2024-01-03 11:34:05浏览次数:31  
标签:weight 性能 after terminate 查询 耗时 分片 create ES


问题

        生产环境频繁报警。查询跨度91天的数据,请求耗时已经来到了30+s。报警的阈值为5s。我们期望值是5s内,大于该阈值的请求,我们认为是慢查询。这些慢查询,最终排查,是因为走到了历史集群上。受到了数据迁移的一定影响,也做了一些优化,最终从30s提升到5s。

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

背景

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

单次仅检索两个字段

查询时间跨度为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%多。

ES慢查询分析——性能提升6 倍_动态截断策略_02





继续分析慢查询的分片

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

ES慢查询分析——性能提升6 倍_请求截断_03

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

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




调整terminate_after  从200->10

检索耗时进一步降低。

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

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

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

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




如何才能降低create_weight的耗时?

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

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




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

GET _cat/nodes?v

ES慢查询分析——性能提升6 倍_请求截断_07

问题解决方案

动态调整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),再去搜索一次。

索引段合并

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

调大在请求在单个节点上的最大并发度

默认情况下,一个请求在单个节点上最大并发度为5,超过5以后则需要排队,串行执行。这里先避免排队的时间。我这里给了30。 注意此参数,在负载不高,且线程池充足和堆空间充足的情况下可以这样用。其它情况不适合,在聚合请求中不建议使用!

ES慢查询分析——性能提升6 倍_请求截断_08

最终的检索效果




检索条件



ES慢查询分析——性能提升6 倍_请求截断_08




检索耗时情况

ES慢查询分析——性能提升6 倍_请求截断_10


最后 

搜索优化不是一朝一夕的事情。需要长时间的知识储备。我已经做了四年优化es搜索优化。我把一些高质量的优化提升的案例放在了我的专栏里。(目前还是免费的,未来可能会收费把...)想要做更多的搜索提升,可以看看这些文章,或许会能起到抛砖引玉的作用。


标签:weight,性能,after,terminate,查询,耗时,分片,create,ES
From: https://blog.51cto.com/u_15812686/9080818

相关文章

  • windows下logstash从文件中读数据写入es报错 Error: No such file or directory - :/d
    [2023-12-22T17:26:50,327][ERROR][logstash.javapipeline][main][897a6c7006446c97daa2ee44df7541701882ceece289ce428fcfac8aa982a0c5]Apluginhadanunrecoverableerror.Willrestartthisplugin.Pipeline_id:mainPlugin:<LogStash::Inputs::Filestar......
  • 首个支持中文及跨语言查询的开源在线反向词典
    大家好,我是Java陈序员。我们在生活中,会遇到一些有趣的人和事,或者是一些令人惊叹的风景。想表达抒发自己心情的时候,到嘴边往往却只能说一句“卧槽”!别问我为啥知道,因为“俺也一样”!今天,给大家介绍一个有趣的开源项目,让你干掉“卧槽”!项目介绍WantWords——由清华大学人工智能研究......
  • pytest自动化测试中的fixture的声明和调用
    1.fixture的声明我们使用@pytest.fixture()来声明fixture函数。fixture()即可无参数进行声明,也可以带参数声明。示例1:@pytest.fixture()无参数进行声明[email protected]#fixture()未带任何参数,声明一个fixture函数deffixture_demo():print("这个是一......
  • Python中pytest命令行实现环境切换
    前言在自动化测试过程中经常需要在不同的环境下进行测试验证,所以写自动化测试代码时需要考虑不同环境切换的情况。pytest钩子函数pytest_addoption可以很好帮我们解决这个痛点。pytest_addoption(parser, pluginmanager)注册argparse样式选项和ini样式配置值,在测试运行开始时调用......
  • 如何使用Pytest进行自动化测试
    为什么需要自动化测试自动化测试有很多优点,但这里有3个主要的点可重用性:不需要总是编写新的脚本,除非必要,即使是新的操作系统版本也不需要编写脚本。可靠性:人容易出错,机器不太可能。当运行不能跳过的重复步骤/测试时,速度会更快。全天运行:您可以在任何时间或远程启动测试。夜间运......
  • 性能篇:String慎重使用正则表达式?
    大家好,我是小米,一个热爱技术分享的小伙伴。今天,我们将深入探讨一个在编程中经常用到但却常常被忽视的话题——正则表达式。正则表达式是一个强大的文本匹配工具,然而在使用它时,我们也要注意一些性能上的问题,特别是在处理大量数据时。本文将带你一起深入了解正则表达式的性能优化和一......
  • Pytest测试框架基本使用方法详解
    pytest介绍pytest是一个非常成熟的全功能的Python测试框架,主要特点有以下几点:1、简单灵活,容易上手,文档丰富;2、支持参数化,可以细粒度地控制要测试的测试用例;3、能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests);4、......
  • Python pytest.main()运行测试用例
    前言前面一直使用命令行运行pytest用例,本篇来学下使用pytest.main()来运行测试用例pytest.main()args传一个list对象,list里面是多个命令行的参数plugins传一个list对象,list里面是初始化的时候需注册的插件不带参数运行importpytest#等同于命令行执行pytest#默认运行的是......
  • 【技术问题】less里面&代表什么
    在Less中,&符号通常用于引用父选择器。在嵌套的样式规则中,&表示对父选择器的引用,可以帮助你避免重复代码并更方便地管理样式。例如,考虑以下Less代码:.button{color:blue;&:hover{color:red;}&.active{font-weight:bold;}}在上面的例子中,&:hover引......
  • Apple iWork(Pages、Numbers、Keynote)11.0 发布
    苹果今天将其专为iOS和macOS设备设计的iWork应用套件更新为版本11,引入了许多新功能和改进功能。Pages文稿。文档高手,精美不言而喻。进一步了解Pages文稿>Numbers表格。精妙的电子表格,联手做。进一步了解Numbers表格>Keynote讲演。令人难忘的出色提案,轻松打造。进......