你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

查询资源消耗

适用于:✅Microsoft FabricAzure 数据资源管理器

本文档介绍作为 Kusto 查询响应的一部分返回的资源消耗信息。

执行查询时,服务不仅返回查询结果,还会返回有关查询执行期间使用的资源的详细信息。

了解查询资源消耗数据有助于优化查询性能、识别瓶颈以及规划适当的资源分配。 通过随着时间的推移监视这些指标,可以做出有关查询设计、群集配置和数据组织的明智决策,以确保 Kusto 查询的最佳性能和成本效益。

资源消耗数据作为查询响应的一部分在对象中 QueryResourceConsumption 返回,通常采用 JSON 格式。 可以在 监视工具 中或通过 编程访问查找对象。

QueryResourceConsumption 对象的结构

QueryResourceConsumption 对象通常包含以下主要部分:

  • QueryHash:查询结构的唯一标识符。 此哈希表示没有其文本值的查询,即使特定文本值不同,也允许识别类似的查询模式。 例如,类似 Events | where Timestamp > datetime(2023-01-01) 查询并且 Events | where Timestamp > datetime(2023-02-01) 具有相同的 QueryHash,因为它们共享相同的结构,只是与文本日期/时间值不同。
  • ExecutionTime:总执行时间(以秒为单位)
  • resource_usage已用资源的详细细分
  • input_dataset_statistics:有关已处理 的数据输入的 统计信息
  • dataset_statistics:有关生成的数据集的统计信息
  • cross_cluster_resource_usage:有关在相关群集中使用的资源的信息

资源使用情况详细信息

资源使用情况部分提供有关查询执行期间使用的资源的详细信息。 它包括了以下几节:

缓存使用情况

resource_usage.cache.shards 部分提供有关查询如何使用缓存的信息:

物体 资产 DESCRIPTION
hot 从热缓存提供的数据
hitbytes 从热缓存成功检索的数据量(以字节为单位)
missbytes 热缓存中未找到的数据量(以字节为单位)
retrievebytes 从存储中检索的数据量,以满足未命中数(以字节为单位)
cold 从冷缓存提供的数据
hitbytes 从冷缓存成功检索的数据量(以字节为单位)
missbytes 冷缓存中找不到以字节为单位的数据量(以字节为单位)
retrievebytes 从存储中检索的数据量,以满足未命中数(以字节为单位)
bypassbytes 绕过缓存的数据量(以字节为单位)
results_cache_origin 有关缓存和重用其结果的原始查询的信息
client_request_id 填充缓存的原始请求的唯一标识符
started_on 执行填充缓存的原始查询时的时间戳
partial_query_results 每个分片级别的缓存的统计信息(如果已启用)
hits 缓存中找到的分片级查询结果数
misses 缓存中缺少的分片级查询结果数

CPU 使用率

resource_usage.cpu 部分提供有关 CPU 消耗的信息:

物体 资产 DESCRIPTION
user 用户模式 CPU 时间
kernel 内核模式 CPU 时间
total cpu 占用的总 CPU 时间
breakdown CPU 使用率进一步细分
query execution 查询执行的 CPU 时间
query planning 查询规划的 CPU 时间

内存使用情况

resource_usage.memory 部分提供有关内存消耗的信息:

物体 资产 DESCRIPTION
peak_per_node 每个节点的内存使用率峰值(以字节为单位)

网络用途

resource_usage.network 部分提供有关网络使用情况的信息:

物体 资产 DESCRIPTION
inter_cluster_total_bytes 群集中传输的总字节数
cross_cluster_total_bytes 跨群集传输的总字节数

输入数据集统计信息

input_dataset_statistics 部分提供有关已处理的源数据的详细信息:

物体 资产 DESCRIPTION
extents 有关数据盘区的信息
total 查询引用的所有表中的盘区总数
scanned 扫描的盘区数(由查询节点检查)
scanned_min_datetime 扫描数据的最低日期/时间
scanned_max_datetime 扫描数据的最大日期/时间
rows 有关数据行的信息
total 查询引用的所有表中的行总数
scanned 扫描的行数(由查询节点检查)
rowstores 有关行存储数据的信息
scanned_rows 从行存储扫描的行数
scanned_values_size 从行存储扫描的值的大小
shards 有关分片查询的信息
total 查询引用的所有表中的分片总数
scanned 扫描的分片数(由查询节点检查)
external_data 有关外部数据的信息(如果适用)
downloaded_items 从外部数据源下载的项目数
downloaded_bytes 从外部数据源下载的字节数
iterated_artifacts 从外部数据源迭代的项目数

与监视工具集成

可以随着时间的推移收集和分析 QueryResourceConsumption 数据,以确定查询性能中的趋势和异常。 可通过以下方法获取此数据:

  • 查询执行结果
  • .show queries 命令输出
  • 导出到监视解决方案的诊断日志

监视此数据有助于识别查询优化机会,并跟踪对数据模型或查询模式的更改的影响。

查询执行结果

可以直接从查询执行结果访问 QueryResourceConsumption 数据的原始 JSON 文件。 信息显示在查询编辑器下方的结果网格中。

  1. 在查询窗格中运行查询。

  2. 浏览到查询结果的 “统计信息 ”选项卡。

    查询结果选项卡的屏幕截图,其中突出显示了“统计信息”选项卡。

  3. 查看 原始 JSAN 预览 部分,然后选择 “查看完整 JSON ”选项以滚动浏览原始 JSON。

    示例查询结果的屏幕截图,其中突出显示了原始 JSAON 预览区域。

程序化访问

在客户端应用程序中,可以通过编程方式访问 QueryResourceConsumption 信息:

// Example of accessing QueryResourceConsumption in C#
var dataSet = kustoClient.ExecuteQuery(query);
var resourceConsumption = GetQueryResourceConsumption(dataSet.Tables[2], false);
Console.WriteLine($"Execution time: {resourceConsumption.ExecutionTime}");
Console.WriteLine($"Memory peak: {resourceConsumption.ResourceUsage.Memory.PeakPerNode}");

有关详细信息,请参阅 创建应用以运行管理命令

例子

热缓存中的数据:此示例显示完全从热缓存(:517324:hitbytes:0)提供且执行时间最少(missbytes0.0045931 秒)的查询。 在热缓存中找到所有数据,导致查询执行速度非常快。

{
  "QueryHash": "add172cd28dde0eb",
  "ExecutionTime": 0.0045931,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 517324,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "00:00:00",
      "kernel": "00:00:00",
      "total cpu": "00:00:00",
      "breakdown": {
        "query execution": "00:00:00",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 1580848
    },
    "network": {
      "inter_cluster_total_bytes": 27384,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1,
      "scanned": 1,
      "scanned_min_datetime": "2016-03-17T08:24:02.6259906Z",
      "scanned_max_datetime": "2016-03-17T08:24:02.6259906Z"
    },
    "rows": {
      "total": 59066,
      "scanned": 59066
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 1,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 11473
    }
  ],
  "cross_cluster_resource_usage": {}
}

外部表中的数据:此示例显示了处理外部数据的查询。 请注意高执行时间(159.88 秒)和大量 CPU 利用率(超过 1 小时的总 CPU 时间)。 外部数据部分显示已下载 6,709 个项目,总计约 87.7 GB。 对于需要从外部源提取大量数据的查询,这比查询 Kusto 内部存储中的数据要慢得多。

{
  "QueryHash": "529656ef4099485b",
  "ExecutionTime": 159.8833962,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "01:01:13.5312500",
      "kernel": "00:00:44.9687500",
      "total cpu": "01:01:58.5000000",
      "breakdown": {
        "query execution": "01:01:58.5000000",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 26834528
    },
    "network": {
      "inter_cluster_total_bytes": 6745,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 0,
      "scanned": 0,
      "scanned_min_datetime": "0001-01-01T00:00:00.0000000Z",
      "scanned_max_datetime": "0001-01-01T00:00:00.0000000Z"
    },
    "rows": {
      "total": 0,
      "scanned": 0
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    },
    "external_data": {
      "downloaded_items": 6709,
      "downloaded_bytes": 87786879356,
      "iterated_artifacts": 6709
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 2,
      "table_size": 44
    }
  ],
  "cross_cluster_resource_usage": {}
}

来自冷缓存的数据:此示例显示了从冷缓存检索数据的查询(cold.hitbytes:127209)。 请注意,在总共 1,250 个盘区中,只扫描了 1 个,在总共 50,000 行中,仅扫描了 40 个。 这建议使用适当筛选的高效查询。 冷缓存访问通常比热缓存慢,但比直接从存储检索数据更快。

{
  "QueryHash": "480873c9b515cea8",
  "ExecutionTime": 1.4233768,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 127209,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      }
    },
    "cpu": {
      "user": "00:00:00",
      "kernel": "00:00:00",
      "total cpu": "00:00:00",
      "breakdown": {
        "query execution": "00:00:00",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 2098656
    },
    "network": {
      "inter_cluster_total_bytes": 250676,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1250,
      "scanned": 1,
      "scanned_min_datetime": "2024-01-08T07:13:13.6172552Z",
      "scanned_max_datetime": "2024-01-08T07:13:13.6172552Z"
    },
    "rows": {
      "total": 50000,
      "scanned": 40
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 1,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 123654
    }
  ],
  "cross_cluster_resource_usage": {}
}

查询缓存的结果:此示例演示查询结果缓存中提供的查询。 请注意该节的存在 results_cache_origin ,该部分指示从以前缓存的查询结果中检索结果。 执行时间极快(0.0039999 秒)显示查询结果缓存的好处,因为不需要数据处理。 缓存包含有关填充缓存(client_request_id)的原始请求的信息,以及最初执行时(started_on)。 请注意,没有从区或行扫描数据,如节中的 input_dataset_statistics 零指示,确认直接从查询缓存检索结果。

{
  "ExecutionTime": 0.0039999,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      },
      "results_cache_origin": {
        "client_request_id": "KE.DF.RunQuery;95b6d241-e684-4a43-91c8-da0d6a854e3e",
        "started_on": "2025-04-22T08:22:24.4719143Z"
      }
    },
    "cpu": {
      "user": "00:00:00.0156250",
      "kernel": "00:00:00",
      "total cpu": "00:00:00.0156250",
      "breakdown": {
        "query execution": "00:00:00.0156250",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 53440160
    },
    "network": {
      "inter_cluster_total_bytes": 13233,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 0,
      "scanned": 0,
      "scanned_min_datetime": "0001-01-01T00:00:00.0000000Z",
      "scanned_max_datetime": "0001-01-01T00:00:00.0000000Z"
    },
    "rows": {
      "total": 0,
      "scanned": 0
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 12121
    }
  ],
  "cross_cluster_resource_usage": {}
}

部分查询缓存(Per-Shard)的结果:此示例演示了受益于按分片级别缓存的查询,如本节所示 partial_query_results 。 缓存显示 1 次命中和 0 次未命中数,这意味着查询能够检索分片的预计算结果,而无需重新处理数据。 与完整的查询缓存示例不同,该 input_dataset_statistics 示例显示数据在技术上“已扫描”(59,066 行),但这可能是一个元数据作,因为实际计算是从缓存中检索到的。 请注意非常快的执行时间(0.0047499 秒),演示了部分查询缓存的性能优势。 对于重复访问具有相同筛选条件的相同数据分区的查询,每个分片缓存特别有用。

{
  "QueryHash": "da3c6dc30e7b203d",
  "ExecutionTime": 0.0047499,
  "resource_usage": {
    "cache": {
      "shards": {
        "hot": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "cold": {
          "hitbytes": 0,
          "missbytes": 0,
          "retrievebytes": 0
        },
        "bypassbytes": 0
      },
      "partial_query_results": {
        "hits": 1,
        "misses": 0
      }
    },
    "cpu": {
      "user": "00:00:00.0156250",
      "kernel": "00:00:00",
      "total cpu": "00:00:00.0156250",
      "breakdown": {
        "query execution": "00:00:00.0156250",
        "query planning": "00:00:00"
      }
    },
    "memory": {
      "peak_per_node": 1580848
    },
    "network": {
      "inter_cluster_total_bytes": 27428,
      "cross_cluster_total_bytes": 0
    }
  },
  "input_dataset_statistics": {
    "extents": {
      "total": 1,
      "scanned": 1,
      "scanned_min_datetime": "2016-03-17T08:24:02.6259906Z",
      "scanned_max_datetime": "2016-03-17T08:24:02.6259906Z"
    },
    "rows": {
      "total": 59066,
      "scanned": 59066
    },
    "rowstores": {
      "scanned_rows": 0,
      "scanned_values_size": 0
    },
    "shards": {
      "queries_generic": 0,
      "queries_specialized": 0
    }
  },
  "dataset_statistics": [
    {
      "table_row_count": 10,
      "table_size": 11473
    }
  ],
  "cross_cluster_resource_usage": {}
}