加载中

搜索分析器 (Search profiler)

Elasticsearch 拥有强大的 Profile API,可用于检查和分析搜索查询。响应会返回一个较大的 JSON 数据块,手动分析起来比较困难。

搜索分析器 (Search Profiler) 工具可以将此 JSON 输出转换为易于查看的可视化界面,从而帮助您更快地诊断和调试性能不佳的查询。

通过导航菜单或 全局搜索字段 进入 开发工具 (Developer tools) 页面,即可找到 搜索分析器

搜索分析器 会显示所搜索索引的名称、每个索引中的分片以及查询完成所用的时间。要尝试该功能,请将默认的 match_all 查询替换为您想要分析的查询,然后点击 分析 (Profile)

下面的示例展示了对 match_all 查询进行性能分析的结果。如果仔细查看 .security_7 示例索引的信息,累计时间 (Cumulative time) 字段会显示该查询执行耗时 0.028 毫秒。

Search Profiler visualization
注意

累计时间指标是各个分片时间的总和。它不一定是查询返回的实际耗时(挂钟时间)。因为分片可能在多个节点上并行处理,所以挂钟时间可能明显小于累计时间。然而,如果分片位于同一节点并串行执行,则挂钟时间会接近累计时间。

虽然累计时间指标对于比较索引和分片的性能非常有用,但它并不一定代表实际的物理查询时间。

若要查看更多性能分析信息,请点击 查看详情 (View details)。您将看到在分片上运行的查询组件的详细信息以及低级方法的耗时细分。有关更多信息,请参阅 分析查询 (Profiling queries)

默认情况下,搜索分析器 执行的所有查询都会发送到 GET /_search。它会在整个集群(所有索引、所有类型)中进行搜索。

要查询特定的索引或类型,可以使用 索引 (Index) 筛选器。

在以下示例中,查询针对 .security-7kibana_sample_data_ecommerce 索引执行。这等同于向 GET /test,kibana_1/_search 发送请求。

Filtering by index and type

为了了解查询树如何在 搜索分析器 中显示,我们来看一个更复杂的查询。

  1. 通过 控制台 (Console) 索引以下数据

    				POST test/_bulk
    					{"index":{}}
    {"name":"aaron","age":23,"hair":"brown"}
    {"index":{}}
    {"name":"sue","age":19,"hair":"red"}
    {"index":{}}
    {"name":"sally","age":19,"hair":"blonde"}
    {"index":{}}
    {"name":"george","age":19,"hair":"blonde"}
    {"index":{}}
    {"name":"fred","age":69,"hair":"blonde"}
    		
  2. 搜索分析器 中,在 索引 (Index) 字段中输入 test,以将性能分析查询限制在 test 索引中。

  3. 将查询编辑器中的默认 match_all 查询替换为一个包含两个子查询组件并包含简单聚合的查询

    {
       "query": {
          "bool": {
             "should": [
                {
                   "match": {
                      "name": "fred"
                   }
                },
                {
                   "terms": {
                      "name": [
                          "sue",
                          "sally"
                      ]
                   }
                }
             ]
          }
       },
       "aggs": {
          "stats": {
             "stats": {
                "field": "price"
             }
          }
       }
    }
    		
  4. 点击 分析 (Profile) 来分析查询并可视化结果。

    Profiling the more complicated query
    • 顶层的 BooleanQuery 组件对应于查询中的 bool。

    • 第二个 BooleanQuery 对应于 terms 查询,它在内部被转换为 Boolean 的 should 子句。它有两个子查询,对应于 terms 查询中的“sally”和“sue”。

    • 标记为 "name:fred" 的 TermQuery 对应于查询中的 match: fred。

      如果查看时间列,可以看到 自身耗时 (Self time)总时间 (Total time) 在所有行中不再相同。自身耗时 表示查询组件执行所花费的时间。总时间 是查询组件及其所有子组件执行所花费的时间。因此,像布尔查询这样的查询,其总时间通常大于自身耗时。

  5. 点击 聚合分析 (Aggregation Profile) 查看聚合分析统计信息。

    此查询在 "age" 字段上包含一个 stats 聚合。仅当被分析的查询包含聚合时,聚合分析 (Aggregation Profile) 选项卡才会启用。

  6. 点击 查看详情 (View details) 查看耗时细分。

    Drilling into the first shard's details

    有关 搜索分析器 的工作原理、时间是如何计算的以及如何解读各种结果的更多信息,请参阅 分析查询 (Profiling queries)

搜索分析器 会查询 Kibana 节点所连接的集群。它是通过针对集群执行查询并收集结果来实现的。

有时,您可能需要调查具有时间性的性能问题。例如,查询可能仅在一天中许多客户使用系统时的特定时间段很慢。您可以设置一个流程,在慢查询发生时自动对其进行分析,然后保存这些分析响应以供稍后分析。

搜索分析器 支持此工作流程,允许您将预先捕获的 JSON 粘贴到查询编辑器中。搜索分析器 将检测到您输入的是 JSON 响应(而不是查询),并将仅渲染可视化界面,而不会查询集群。

要了解其工作原理,请将以下分析响应复制并粘贴到查询编辑器中,然后点击 分析 (Profile)

{
   "took": 3,
   "timed_out": false,
   "_shards": {
      "total": 1,
      "successful": 1,
      "failed": 0
   },
   "hits": {
      "total": 1,
      "max_score": 1.3862944,
      "hits": [
         {
            "_index": "test",
            "_type": "test",
            "_id": "AVi3aRDmGKWpaS38wV57",
            "_score": 1.3862944,
            "_source": {
               "name": "fred",
               "age": 69,
               "hair": "blonde"
            }
         }
      ]
   },
   "profile": {
      "shards": [
         {
            "id": "[O-l25nM4QN6Z68UA5rUYqQ][test][0]",
            "searches": [
               {
                  "query": [
                     {
                        "type": "BooleanQuery",
                        "description": "+name:fred #(ConstantScore(*:*))^0.0",
                        "time": "0.5884370000ms",
                        "breakdown": {
                           "score": 7243,
                           "build_scorer_count": 1,
                           "match_count": 0,
                           "create_weight": 196239,
                           "next_doc": 9851,
                           "match": 0,
                           "create_weight_count": 1,
                           "next_doc_count": 2,
                           "score_count": 1,
                           "build_scorer": 375099,
                           "advance": 0,
                           "advance_count": 0
                        },
                        "children": [
                           {
                              "type": "TermQuery",
                              "description": "name:fred",
                              "time": "0.3016880000ms",
                              "breakdown": {
                                 "score": 4218,
                                 "build_scorer_count": 1,
                                 "match_count": 0,
                                 "create_weight": 132425,
                                 "next_doc": 2196,
                                 "match": 0,
                                 "create_weight_count": 1,
                                 "next_doc_count": 2,
                                 "score_count": 1,
                                 "build_scorer": 162844,
                                 "advance": 0,
                                 "advance_count": 0
                              }
                           },
                           {
                              "type": "BoostQuery",
                              "description": "(ConstantScore(*:*))^0.0",
                              "time": "0.1223030000ms",
                              "breakdown": {
                                 "score": 0,
                                 "build_scorer_count": 1,
                                 "match_count": 0,
                                 "create_weight": 17366,
                                 "next_doc": 0,
                                 "match": 0,
                                 "create_weight_count": 1,
                                 "next_doc_count": 0,
                                 "score_count": 0,
                                 "build_scorer": 102329,
                                 "advance": 2604,
                                 "advance_count": 2
                              },
                              "children": [
                                 {
                                    "type": "MatchAllDocsQuery",
                                    "description": "*:*",
                                    "time": "0.03307600000ms",
                                    "breakdown": {
                                       "score": 0,
                                       "build_scorer_count": 1,
                                       "match_count": 0,
                                       "create_weight": 6068,
                                       "next_doc": 0,
                                       "match": 0,
                                       "create_weight_count": 1,
                                       "next_doc_count": 0,
                                       "score_count": 0,
                                       "build_scorer": 25615,
                                       "advance": 1389,
                                       "advance_count": 2
                                    }
                                 }
                              ]
                           }
                        ]
                     }
                  ],
                  "rewrite_time": 168640,
                  "collector": [
                     {
                        "name": "CancellableCollector",
                        "reason": "search_cancelled",
                        "time": "0.02952900000ms",
                        "children": [
                           {
                              "name": "SimpleTopScoreDocCollector",
                              "reason": "search_top_hits",
                              "time": "0.01931700000ms"
                           }
                        ]
                     }
                  ]
               }
            ],
            "aggregations": []
         }
      ]
   }
}
		

您的输出应该看起来类似于此

Rendering pre-captured profiler JSON
© . This website operates independently and is not affiliated with or endorsed by Elasticsearch B.V. All brand names, logos, and trademarks are the property of their respective owners.