searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Elasticsearch profile API来定位慢查询

2023-05-04 03:28:06
275
0

     有时在发起一个查询时,他的执行过程会延迟,或者响应时间很慢。查询缓慢可能会有多种原因范围包括 shard 问题,或者计算查询中的某些元素。 从 elasticsearch 2.2版本开始提供 Profile API 供用户检查查询执行时间和其他详细信息

    在官网中,profile API的首页,有一句警告:The Profile API is a debugging tool and adds significant overhead to search execution. 意思是,查看执行计划,会增加系统的资源开销。大家在生产环境的时候,还是要慎用这个功能。

 

执行一个基础查询请求,只要在请求参数中加入 "profile":true,即可查看ES的执行计划

GET /my-index-000001/_search
{
  "profile": true,
  "query" : {
    "match" : { "message" : "GET /search" }
  }
}



查看执行结果:

{
  "took": 25,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 0.17402273,
    "hits": [...] 
  },
  "profile": {
    "shards": [
      {
        "id": "[2aE02wS1R8q_QFnYu6vDVQ][my-index-000001][0]",
        "searches": [
          {
            "query": [
              {
                "type": "BooleanQuery",
                "description": "message:get message:search",
                "time_in_nanos" : 11972972,
                "breakdown" : {
                  "set_min_competitive_score_count": 0,
                  "match_count": 5,
                  "shallow_advance_count": 0,
                  "set_min_competitive_score": 0,
                  "next_doc": 39022,
                  "match": 4456,
                  "next_doc_count": 5,
                  "score_count": 5,
                  "compute_max_score_count": 0,
                  "compute_max_score": 0,
                  "advance": 84525,
                  "advance_count": 1,
                  "score": 37779,
                  "build_scorer_count": 2,
                  "create_weight": 4694895,
                  "shallow_advance": 0,
                  "create_weight_count": 1,
                  "build_scorer": 7112295,
                  "count_weight": 0,
                  "count_weight_count": 0
                },
                "children": [
                  {
                    "type": "TermQuery",
                    "description": "message:get",
                    "time_in_nanos": 3801935,
                    "breakdown": {
                      "set_min_competitive_score_count": 0,
                      "match_count": 0,
                      "shallow_advance_count": 3,
                      "set_min_competitive_score": 0,
                      "next_doc": 0,
                      "match": 0,
                      "next_doc_count": 0,
                      "score_count": 5,
                      "compute_max_score_count": 3,
                      "compute_max_score": 32487,
                      "advance": 5749,
                      "advance_count": 6,
                      "score": 16219,
                      "build_scorer_count": 3,
                      "create_weight": 2382719,
                      "shallow_advance": 9754,
                      "create_weight_count": 1,
                      "build_scorer": 1355007,
                      "count_weight": 0,
                      "count_weight_count": 0
                    }
                  },
                  {
                    "type": "TermQuery",
                    "description": "message:search",
                    "time_in_nanos": 205654,
                    "breakdown": {
                      "set_min_competitive_score_count": 0,
                      "match_count": 0,
                      "shallow_advance_count": 3,
                      "set_min_competitive_score": 0,
                      "next_doc": 0,
                      "match": 0,
                      "next_doc_count": 0,
                      "score_count": 5,
                      "compute_max_score_count": 3,
                      "compute_max_score": 6678,
                      "advance": 12733,
                      "advance_count": 6,
                      "score": 6627,
                      "build_scorer_count": 3,
                      "create_weight": 130951,
                      "shallow_advance": 2512,
                      "create_weight_count": 1,
                      "build_scorer": 46153,
                      "count_weight": 0,
                      "count_weight_count": 0
                    }
                  }
                ]
              }
            ],
            "rewrite_time": 451233,
            "collector": [
              {
                "name": "SimpleTopScoreDocCollector",
                "reason": "search_top_hits",
                "time_in_nanos": 775274
              }
            ]
          }
        ],
        "aggregations": [],
        "fetch": {
          "type": "fetch",
          "description": "",
          "time_in_nanos": 660555,
          "breakdown": {
            "next_reader": 7292,
            "next_reader_count": 1,
            "load_stored_fields": 299325,
            "load_stored_fields_count": 5,
            "load_source": 3863,
            "load_source_count": 5
          },
          "debug": {
            "stored_fields": ["_id", "_routing", "_source"]
          },
          "children": [
            {
              "type": "FetchSourcePhase",
              "description": "",
              "time_in_nanos": 20443,
              "breakdown": {
                "next_reader": 745,
                "next_reader_count": 1,
                "process": 19698,
                "process_count": 5
              },
              "debug": {
                "fast_path": 5
              }
            },
            {
              "type": "StoredFieldsPhase",
              "description": "",
              "time_in_nanos": 5310,
              "breakdown": {
                "next_reader": 745,
                "next_reader_count": 1,
                "process": 4445,
                "process_count": 5
              }
            }
          ]
        }
      }
    ]
  }
}

由于一个搜索请求可能针对索引中的某个或多个分片执行,而一个搜索可能涵盖多个索引,因此profile响应的高层次元素是多个分片对象数组。每个分片对象列出其ID,该ID唯一标识该分片。ID格式为[节点ID][索引名称][分片ID]。
整个profile可能包括一个或多个“搜索”,其中搜索是对 underlying Lucene 索引的执行查询。大部分用户提交的请求只会针对Lucene索引执行一次搜索。但偶尔多个搜索将执行,例如包括全球聚合(这需要执行第二个“匹配全部”查询以获取全球上下文)。

 

Query阶段:

query部分包含Lucene在指定分片上执行的查询树详细的时间信息。

"query": [
    {
       "type": "BooleanQuery",
       "description": "message:get message:search",
       "time_in_nanos": "11972972",
       "breakdown": {...},               
       "children": [
          {
             "type": "TermQuery",
             "description": "message:get",
             "time_in_nanos": "3801935",
             "breakdown": {...}
          },
          {
             "type": "TermQuery",
             "description": "message:search",
             "time_in_nanos": "205654",
             "breakdown": {...}
          }
       ]
    }
]

 

根据Profile 结构,我们可以发现我们的匹配查询被 Lucene 改写成了一个布尔值查询(其中包含两个子查询:一个TermQuery)。

type字段显示的是 Lucene 类名,通常与 Elasticsearch 中相应的名称对齐。

description字段显示的是查询的解释文本,以便于区分您的查询部分(例如,"message:get"和"message:search"都是TermQuery,它们看起来非常相似)。
time_in_nanos 字段显示,这个查询整个布尔值查询执行花费了大约 11.9 毫秒。记录的时间包括所有子查询。
breakdown 字段将提供有关时间如何花费的详细信息。我们将稍后查看它。最后,children 数组列出可能存在的子查询。由于我们搜索了两个值(“get search”),我们的布尔查询包含两个子Term queries。它们具有相同的信息(type、time、 breakdown、等等)。子查询可以有自己的子查询。

 

Collector阶段:

响应的collector部分显示高级执行详细信息。 Lucene 的工作方式是定义一个“Collector”,负责协调匹配文档的遍历、评分和收集。

"collector": [
  {
    "name": "SimpleTopScoreDocCollector",
    "reason": "search_top_hits",
    "time_in_nanos": 775274
  }
]

我们看到一个名为SimpleTopScoreDocCollector的收集器被包装为可取消的收集器。

SimpleTopScoreDocCollector是Elasticsearch默认的“得分和排序”收集器。

reason字段试图用简单的英语描述类名。

time_in_nanos类似于查询树的时间:包括所有子收集器的 wall-clock 时间。类似地,子集列表了所有子收集器。

将SimpleTopScoreDocCollector包裹在可取消的收集器中的收集器是用于检测当前搜索是否被取消,并在发生时立即停止收集文档的Elasticsearch工具。
需要指出的是,收集器时间与查询时间无关。它们计算、组合并标准化独立于查询时间!由于Lucene的执行本质,不可能将收集器时间“合并”到查询部分中,因此它们显示在独立的部分中。

 

rewrite阶段:

Lucene中的所有查询都经历着一个“rewrite”过程。一个查询(及其子查询)可能多次被改写,并且过程会继续直到查询不再发生变化。

这个过程允许Lucene进行优化,例如删除冗余条件句,以更高效的执行路径替换一个查询等等。例如,Boolean → Boolean → TermQuery可以改写为TermQuery,因为在这种情况下所有布尔查询都是不必要的。

改写过程非常复杂且难以显示,因为查询可能会发生剧烈的变化。 Rather than显示中间结果,总改写时间 simply 显示为值(in nanoseconds)。这个值是累加的,它包含了所有正在改写的查询的总时间。

0条评论
0 / 1000
1****n
10文章数
0粉丝数
1****n
10 文章 | 0 粉丝
原创

Elasticsearch profile API来定位慢查询

2023-05-04 03:28:06
275
0

     有时在发起一个查询时,他的执行过程会延迟,或者响应时间很慢。查询缓慢可能会有多种原因范围包括 shard 问题,或者计算查询中的某些元素。 从 elasticsearch 2.2版本开始提供 Profile API 供用户检查查询执行时间和其他详细信息

    在官网中,profile API的首页,有一句警告:The Profile API is a debugging tool and adds significant overhead to search execution. 意思是,查看执行计划,会增加系统的资源开销。大家在生产环境的时候,还是要慎用这个功能。

 

执行一个基础查询请求,只要在请求参数中加入 "profile":true,即可查看ES的执行计划

GET /my-index-000001/_search
{
  "profile": true,
  "query" : {
    "match" : { "message" : "GET /search" }
  }
}



查看执行结果:

{
  "took": 25,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 5,
      "relation": "eq"
    },
    "max_score": 0.17402273,
    "hits": [...] 
  },
  "profile": {
    "shards": [
      {
        "id": "[2aE02wS1R8q_QFnYu6vDVQ][my-index-000001][0]",
        "searches": [
          {
            "query": [
              {
                "type": "BooleanQuery",
                "description": "message:get message:search",
                "time_in_nanos" : 11972972,
                "breakdown" : {
                  "set_min_competitive_score_count": 0,
                  "match_count": 5,
                  "shallow_advance_count": 0,
                  "set_min_competitive_score": 0,
                  "next_doc": 39022,
                  "match": 4456,
                  "next_doc_count": 5,
                  "score_count": 5,
                  "compute_max_score_count": 0,
                  "compute_max_score": 0,
                  "advance": 84525,
                  "advance_count": 1,
                  "score": 37779,
                  "build_scorer_count": 2,
                  "create_weight": 4694895,
                  "shallow_advance": 0,
                  "create_weight_count": 1,
                  "build_scorer": 7112295,
                  "count_weight": 0,
                  "count_weight_count": 0
                },
                "children": [
                  {
                    "type": "TermQuery",
                    "description": "message:get",
                    "time_in_nanos": 3801935,
                    "breakdown": {
                      "set_min_competitive_score_count": 0,
                      "match_count": 0,
                      "shallow_advance_count": 3,
                      "set_min_competitive_score": 0,
                      "next_doc": 0,
                      "match": 0,
                      "next_doc_count": 0,
                      "score_count": 5,
                      "compute_max_score_count": 3,
                      "compute_max_score": 32487,
                      "advance": 5749,
                      "advance_count": 6,
                      "score": 16219,
                      "build_scorer_count": 3,
                      "create_weight": 2382719,
                      "shallow_advance": 9754,
                      "create_weight_count": 1,
                      "build_scorer": 1355007,
                      "count_weight": 0,
                      "count_weight_count": 0
                    }
                  },
                  {
                    "type": "TermQuery",
                    "description": "message:search",
                    "time_in_nanos": 205654,
                    "breakdown": {
                      "set_min_competitive_score_count": 0,
                      "match_count": 0,
                      "shallow_advance_count": 3,
                      "set_min_competitive_score": 0,
                      "next_doc": 0,
                      "match": 0,
                      "next_doc_count": 0,
                      "score_count": 5,
                      "compute_max_score_count": 3,
                      "compute_max_score": 6678,
                      "advance": 12733,
                      "advance_count": 6,
                      "score": 6627,
                      "build_scorer_count": 3,
                      "create_weight": 130951,
                      "shallow_advance": 2512,
                      "create_weight_count": 1,
                      "build_scorer": 46153,
                      "count_weight": 0,
                      "count_weight_count": 0
                    }
                  }
                ]
              }
            ],
            "rewrite_time": 451233,
            "collector": [
              {
                "name": "SimpleTopScoreDocCollector",
                "reason": "search_top_hits",
                "time_in_nanos": 775274
              }
            ]
          }
        ],
        "aggregations": [],
        "fetch": {
          "type": "fetch",
          "description": "",
          "time_in_nanos": 660555,
          "breakdown": {
            "next_reader": 7292,
            "next_reader_count": 1,
            "load_stored_fields": 299325,
            "load_stored_fields_count": 5,
            "load_source": 3863,
            "load_source_count": 5
          },
          "debug": {
            "stored_fields": ["_id", "_routing", "_source"]
          },
          "children": [
            {
              "type": "FetchSourcePhase",
              "description": "",
              "time_in_nanos": 20443,
              "breakdown": {
                "next_reader": 745,
                "next_reader_count": 1,
                "process": 19698,
                "process_count": 5
              },
              "debug": {
                "fast_path": 5
              }
            },
            {
              "type": "StoredFieldsPhase",
              "description": "",
              "time_in_nanos": 5310,
              "breakdown": {
                "next_reader": 745,
                "next_reader_count": 1,
                "process": 4445,
                "process_count": 5
              }
            }
          ]
        }
      }
    ]
  }
}

由于一个搜索请求可能针对索引中的某个或多个分片执行,而一个搜索可能涵盖多个索引,因此profile响应的高层次元素是多个分片对象数组。每个分片对象列出其ID,该ID唯一标识该分片。ID格式为[节点ID][索引名称][分片ID]。
整个profile可能包括一个或多个“搜索”,其中搜索是对 underlying Lucene 索引的执行查询。大部分用户提交的请求只会针对Lucene索引执行一次搜索。但偶尔多个搜索将执行,例如包括全球聚合(这需要执行第二个“匹配全部”查询以获取全球上下文)。

 

Query阶段:

query部分包含Lucene在指定分片上执行的查询树详细的时间信息。

"query": [
    {
       "type": "BooleanQuery",
       "description": "message:get message:search",
       "time_in_nanos": "11972972",
       "breakdown": {...},               
       "children": [
          {
             "type": "TermQuery",
             "description": "message:get",
             "time_in_nanos": "3801935",
             "breakdown": {...}
          },
          {
             "type": "TermQuery",
             "description": "message:search",
             "time_in_nanos": "205654",
             "breakdown": {...}
          }
       ]
    }
]

 

根据Profile 结构,我们可以发现我们的匹配查询被 Lucene 改写成了一个布尔值查询(其中包含两个子查询:一个TermQuery)。

type字段显示的是 Lucene 类名,通常与 Elasticsearch 中相应的名称对齐。

description字段显示的是查询的解释文本,以便于区分您的查询部分(例如,"message:get"和"message:search"都是TermQuery,它们看起来非常相似)。
time_in_nanos 字段显示,这个查询整个布尔值查询执行花费了大约 11.9 毫秒。记录的时间包括所有子查询。
breakdown 字段将提供有关时间如何花费的详细信息。我们将稍后查看它。最后,children 数组列出可能存在的子查询。由于我们搜索了两个值(“get search”),我们的布尔查询包含两个子Term queries。它们具有相同的信息(type、time、 breakdown、等等)。子查询可以有自己的子查询。

 

Collector阶段:

响应的collector部分显示高级执行详细信息。 Lucene 的工作方式是定义一个“Collector”,负责协调匹配文档的遍历、评分和收集。

"collector": [
  {
    "name": "SimpleTopScoreDocCollector",
    "reason": "search_top_hits",
    "time_in_nanos": 775274
  }
]

我们看到一个名为SimpleTopScoreDocCollector的收集器被包装为可取消的收集器。

SimpleTopScoreDocCollector是Elasticsearch默认的“得分和排序”收集器。

reason字段试图用简单的英语描述类名。

time_in_nanos类似于查询树的时间:包括所有子收集器的 wall-clock 时间。类似地,子集列表了所有子收集器。

将SimpleTopScoreDocCollector包裹在可取消的收集器中的收集器是用于检测当前搜索是否被取消,并在发生时立即停止收集文档的Elasticsearch工具。
需要指出的是,收集器时间与查询时间无关。它们计算、组合并标准化独立于查询时间!由于Lucene的执行本质,不可能将收集器时间“合并”到查询部分中,因此它们显示在独立的部分中。

 

rewrite阶段:

Lucene中的所有查询都经历着一个“rewrite”过程。一个查询(及其子查询)可能多次被改写,并且过程会继续直到查询不再发生变化。

这个过程允许Lucene进行优化,例如删除冗余条件句,以更高效的执行路径替换一个查询等等。例如,Boolean → Boolean → TermQuery可以改写为TermQuery,因为在这种情况下所有布尔查询都是不必要的。

改写过程非常复杂且难以显示,因为查询可能会发生剧烈的变化。 Rather than显示中间结果,总改写时间 simply 显示为值(in nanoseconds)。这个值是累加的,它包含了所有正在改写的查询的总时间。

文章来自个人专栏
elasticsearch
10 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
0
0