更新时间:2026-01-09 GMT+08:00
分享

获取Elasticsearch集群查询资源占用情况

在日常运维Elasticsearch集群的过程中,运维人员经常遇到因查询导致CPU占用率高的问题。当前,定位此类问题的方法较为繁琐,需要通过Elasticsearch API获取正在运行的任务,再结合hot threads信息,才能确定具体是哪些查询语句导致了CPU占用率升高。为了提高运维效率,CSS服务提供了支持查询资源占用溯源的功能。启用该功能后,运维人员可以通过API获取到最近时延最大、消耗CPU和内存最多的查询语句,并支持基于时间进行过滤从而快速定位到问题查询,提升故障排查的效率和准确性。

原理介绍

查询资源占用溯源功能旨在帮助用户识别和优化高资源消耗的查询,提高系统性能和资源利用率。该功能适用于大数据分析、日志处理等场景。

图1 查询资源占用溯源的原理图

在查询执行阶段,系统会记录每个子阶段(如Query、Fetch、Scroll等)的资源消耗情况,包括CPU使用率、内存占用等。这些数据会以固定时间窗口(如5分钟)为单位进行统计,统计结果中消耗最高的查询语句会被持久化存储在Top查询索引中,以便后续分析。Top查询索引会每天新建一个,用于存储当天的查询资源消耗统计数据,命名格式是top-queries-xxx(xxx是日期)。

TopN查询是指按指定指标(如CPU、内存或延迟)对查询语句进行排序,返回消耗最高的前N条记录。默认情况下,系统按延迟指标进行排序。

约束限制

  • 查询资源占用溯源的功能会增加内存缓存字段类型信息,对集群性能会有影响。
  • 满足以下条件的Elasticsearch集群默认启用查询资源占用溯源功能:集群版本号为7.10.2,镜像版本号不低于7.10.2_25.9.0_xxx。

修改查询资源占用溯源的配置

执行如下命令可修改查询资源占用溯源的配置,以合理监控资源使用情况并优化资源管理:

PUT _cluster/settings
{
  "persistent": {
    "search.insights.top_queries.cpu.enabled": true,
    "search.insights.top_queries.cpu.window_size": "10m",
    "search.insights.top_queries.cpu.top_n_size": 20,
    "search.insights.top_queries.exporter.delete_after_days": 8,
    "search.insights.top_queries.group_by": "none"
  }
}
表1 配置项说明

配置项

类型

描述

search.insights.top_queries.<metric>.enabled

Boolean

是否开启对应metric的TopN查询监控。

metric支持:latency(延迟)、cpu(CPU使用率)、memory(内存使用率)

  • true(默认值):开启查询监控。
  • false:关闭查询监控。

search.insights.top_queries.<metric>.window_size

String

窗口大小。监控数据会以固定的时间窗口(如5分钟)为单位进行统计。

metric支持:latency(延迟)、cpu(CPU使用率)、memory(内存使用率)

取值范围:1m(1分钟)、5m(5分钟)、10m(10分钟)、30m(半小时)或xh(x小时,x支持1~24)

默认值:5m

search.insights.top_queries.<metric>.top_n_size

Integer

每个时间窗监控TopN查询请求的个数。

例如,配置为20表示每个时间窗只监控Top20的查询数据。

metric支持:latency(延迟)、cpu(CPU使用率)、memory(内存使用率)

取值范围:1~100

默认值:10

search.insights.top_queries.exporter.delete_after_days

Integer

Top查询索引top-queries-xxx的保留时间,到期会被删除。

例如,配置为8表示数据只保留8天。

取值范围:1~180

默认值: 7

单位:天

search.insights.top_queries.group_by

String

是否启用查询分组功能。

取值范围:

  • none(默认值):不分组。
  • similarity:按查询特征的相似度进行分组。同一个窗口中针对同一个查询特征的多个请求只显示第一个查询请求。

查询分组功能的详细介绍请参见查询分组介绍

search.insights.top_queries.grouping.attributes.field_name

Boolean

查询特征是否区分查询字段名字。

“search.insights.top_queries.group_by”“similarity”时此配置才生效。

  • true(默认值):区分查询字段名。
  • false:忽略查询字段名。

search.insights.top_queries.grouping.attributes.field_type

Boolean

查询特征是否区分查询字段的类型。

“search.insights.top_queries.group_by”“similarity”时此配置才生效。

  • true(默认值):区分查询字段类型。
  • false:忽略查询字段类型。

获取查询资源的占用情况

执行如下命令获取指定时间范围内某查询资源的占用情况:

GET _insights/top_queries?type=cpu&from=2025-12-02T00:00:00.000Z&to=2025-12-02T17:00:00.000Z
表2 请求参数说明

参数

说明

type

指定某一查询资源的TopN情况。

取值范围:latency(延迟)、cpu(CPU使用率)、memory(内存使用率)

默认值: latency

from

指定查询时间范围的开始值。

from和to必须同时配置才生效。

默认值:无,不指定则取最近两个窗口的TopN。

to

指定查询时间范围的结束值。

from和to必须同时配置才生效。

默认值:无,不指定则取最近两个窗口的TopN。

返回示例:

{
  "top_queries": [
    {
      "timestamp": 1764662136273,                            // 查询语句发生的时间戳
      "date": "2025-12-02 07:55:36Z",                        // 查询语句发生的时间
      "id": "4a5b4b1e-b502-4621-a5c1-09b8d9a1b81c",          // 查询语句的唯一ID
      "task_resource_usages": [
        {
          "action": "indices:data/read/search[phase/query]", // Query阶段在节点FB2ixw4IQCuXzCR83GT5Yg上的CPU消耗和内存消耗
          "taskId": 1877927,
          "parentTaskId": 111295,
          "nodeId": "FB2ixw4IQCuXzCR83GT5Yg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 3017078,
            "memory_in_bytes": 102360
          }
        },
        {
          "action": "indices:data/read/search[phase/query]", // Query阶段在节点FB2ixw4IQCuXzCR83GT5Yg上的CPU消耗和内存消耗
          "taskId": 1877926,
          "parentTaskId": 111295,
          "nodeId": "FB2ixw4IQCuXzCR83GT5Yg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 5618940,
            "memory_in_bytes": 271680
          }
        },
        {
          "action": "indices:data/read/search[phase/query]", // Query阶段在节点2ICOHICoSS26YeQu5PIrlg上的CPU消耗和内存消耗
          "taskId": 107710,
          "parentTaskId": 111295,
          "nodeId": "2ICOHICoSS26YeQu5PIrlg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 8703914,
            "memory_in_bytes": 501560
          }
        },
        {
          "action": "indices:data/read/search[phase/fetch/id]", // Fetch阶段在节点FB2ixw4IQCuXzCR83GT5Yg上的CPU消耗和内存消耗
          "taskId": 1877928,
          "parentTaskId": 111295,
          "nodeId": "FB2ixw4IQCuXzCR83GT5Yg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 424055,
            "memory_in_bytes": 59000
          }
        },
        {
          "action": "indices:data/read/search[phase/fetch/id]", // Fetch阶段在节点2ICOHICoSS26YeQu5PIrlg上的CPU消耗和内存消耗
          "taskId": 107711,
          "parentTaskId": 111295,
          "nodeId": "2ICOHICoSS26YeQu5PIrlg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 1279677,
            "memory_in_bytes": 337504
          }
        },
        {
          "action": "indices:data/read/search",                // 查询开始阶段在接入节点gzsjh_47SjCe6QFs9pKjEg上的CPU消耗和内存消耗
          "taskId": 111295,
          "parentTaskId": -1,
          "nodeId": "gzsjh_47SjCe6QFs9pKjEg",
          "taskResourceUsage": {
            "cpu_time_in_nanos": 297268,
            "memory_in_bytes": 8632
          }
        }
      ],
      "source": {                                              // 具体的查询语句
        "query": {
          "match": {
            "message": {
              "query": "http",
              "operator": "OR",
              "prefix_length": 0,
              "max_expansions": 50,
              "fuzzy_transpositions": true,
              "lenient": false,
              "zero_terms_query": "NONE",
              "auto_generate_synonyms_phrase_query": true,
              "boost": 1
            }
          }
        }
      },
      "indices": [                                           // 查询的索引
        "log1"
      ],
      "total_shards": 3,                                     // 查询的总分片数
      "phase_latency_map": {                                 // 查询各个阶段的耗时
        "expand": 0,                                         // expand阶段耗时
        "query": 16,                                         // Query阶段耗时
        "fetch": 3                                           // Fetch阶段耗时
      },
      "labels": {},
      "group_by": "NONE",                                    // 查询分组类别
      "node_id": "gzsjh_47SjCe6QFs9pKjEg",                   // 接收到请求的节点ID
      "search_type": "query_then_fetch",                     // 查询类型
      "measurements": {                                      // 查询指标
        "memory": {                                          // 内存消耗
          "number": 1280736,
          "count": 1,
          "aggregationType": "NONE"
        },
        "latency": {                                          // 耗时
          "number": 20,
          "count": 1,
          "aggregationType": "NONE"
        },
        "cpu": {                                              // CPU消耗
          "number": 19340932,
          "count": 1,
          "aggregationType": "NONE"
        }
      }
    }
  ]
}

获取查询资源占用溯源插件的资源消耗情况

执行如下命令以获取查询资源占用溯源插件的资源消耗情况:

GET _insights/health_stats

返回示例:

{
  "QDyhJ8Q6Td2acc3KGQ43bQ" : {
    "ThreadPoolInfo" : {
      "query_insights_executor" : {  // 插件专用队列,用于执行分析top query的任务
        "type" : "scaling",
        "core" : 1,
        "max" : 1,
        "keep_alive" : "5m",
        "queue_size" : -1
      }
    },
    "QueryRecordsQueueSize" : 0,  // 当前在query_insights_executor队列中未处理的任务数
    "TopQueriesHealthStats" : {
      "latency" : {
        "TopQueriesHeapSize" : 0,  // 存储top queries占用的内存
        "QueryGroupCount_Total" : 0,  // 开启分组功能后当前在内存中的分组数
        "QueryGroupCount_MaxHeap" : 0  // 开启分组功能后当前在内存中的分组占用的内存
      },
      "cpu" : {
        "TopQueriesHeapSize" : 0,
        "QueryGroupCount_Total" : 0,
        "QueryGroupCount_MaxHeap" : 0
      },
      "memory" : {
        "TopQueriesHeapSize" : 0,
        "QueryGroupCount_Total" : 0,
        "QueryGroupCount_MaxHeap" : 0
      }
    },
    "FieldTypeCacheStats" : { // 缓存状态统计,启用查询分组时会将字段的mapping做缓存,避免每次查询都去获取mapping
      "size_in_bytes" : 0,
      "entry_count" : 0,
      "evictions" : 0,
      "hit_count" : 0,
      "miss_count" : 0
    }
  }
}

查询分组介绍

当某单一查询持续占用资源时,TopN统计结果可能被该查询垄断,导致其他查询信息被隐藏。查询分组功能通过特征匹配将同类查询归为一组,确保每个分组在TopN中仅显示第一个查询请求。

表3 分组方式

分组模式

描述

完整查询结构(结构+字段+类型)

精准匹配字段类型。

仅查询结构

忽略字段名和类型差异,仅区分查询逻辑结构。

仅查询结构+字段

忽略字段类型差异,区分查询逻辑结构和字段名。

仅查询结构+类型

忽略字段名差异,区分查询逻辑结构和字段类型。

启用字段类型匹配时,系统会缓存字段类型信息以提升分组效率,适用于字段类型不经常变化的场景。

配置示例

例如某个索引的mapping如下:

"mappings": {
  "properties": {
    "field1": {
      "type": "keyword"
    },
    "field2": {
      "type": "text"
    },
    "field3": {
      "type": "text"
    },
    "field4": {
      "type": "long"
    }
  }
}

对索引执行如下查询:

{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "field1": "example_value"
          }
        }
      ],
      "filter": [
        {
          "match": {
            "field2": "search_text"
          }
        },
        {
          "range": {
            "field4": {
              "gte": 1,
              "lte": 100
            }
          }
        }
      ],
      "should": [
        {
          "regexp": {
            "field3": ".*"
          }
        }
      ]
    }
  }
}
表4所示,通过不同分组方式的特征配置示例,帮助您理解每种分组方式的具体应用和效果。
表4 分组方式的特征配置示例

分组模式

特征内容

完整查询结构

bool []
  must:
    term [field1, keyword]
  filter:
    match [field2, text]
    range [field4, long]
  should:
    regexp [field3, text]

仅查询结构

bool
  must:
    term
  filter:
    match
    range
  should:
    regexp

仅查询结构+字段

bool []
  must:
    term [field1]
  filter:
    match [field2]
    range [field4]
  should:
    regexp [field3]

仅查询结构+类型

bool []
  must:
    term [keyword]
  filter:
    match [text]
    range [long]
  should:
    regexp [text]

相关文档