

# CloudWatch Metrics Insights 中的查询组件和语法
<a name="cloudwatch-metrics-insights-querylanguage"></a>

CloudWatch Metrics Insights 语法如下。

```
SELECT FUNCTION(metricName)
FROM namespace | SCHEMA(...)
[ WHERE labelKey OPERATOR labelValue [AND ... ] ]
[ GROUP BY labelKey [ , ... ] ]
[ ORDER BY FUNCTION() [ DESC | ASC ] ]
[ LIMIT number ]
```

Metrics Insights 查询中可能的子句如下。关键字不区分大小写，但是指标名称、命名空间和维度等标识符需区分大小写。

**SELECT**  
必需。指定用于聚合每个时间段的观测值的函数（由提供的时段确定）。还可以指定要查询的指标的名称。  
**FUNCTION** 的有效值为 `AVG`、`COUNT`、`MAX`、`MIN` 和 `SUM`。  
+ `AVG` 计算查询匹配的观测值的平均值。
+ `COUNT` 返回查询匹配的观测值的计数。
+ `MAX` 返回查询匹配的观测值的最大值。
+ `MIN` 返回查询匹配的观测值的最小值。
+ `SUM` 计算查询匹配的观测值的总和。

**FROM**  
必需。指定指标源。您可以指定包含要查询的指标的指标命名空间，也可以指定 **SCHEMA** 表函数。指标命名空间的示例包括：`"AWS/EC2"`、`"AWS/Lambda"` 以及您为自定义指标创建的指标命名空间。  
包括 **/** 或任何其他不是字母、数字或下划线的字符在内的指标命名空间必须放在双引号中。有关更多信息，请参阅 [什么内容需要引号或转义字符？](#cloudwatch-metrics-insights-syntaxdetails)。  
**SCHEMA**  
一个可以在 **FROM** 子句中使用的可选表函数。使用 **SCHEMA** 将查询结果范围缩小到仅与维度列表完全匹配的指标或没有维度的指标。  
如果您使用 **SCHEMA** 子句，它必须包含至少一个参数，并且第一个参数必须是被查询的指标命名空间。如果您仅用此命名空间参数指定 **SCHEMA**，则结果范围只限于没有任何维度的指标。  
如果您使用其他参数指定 **SCHEMA**，命名空间参数之后的其他参数必须为*标注*键。标签键必须是维度名称。如果您指定了一个或多个标签键，则结果范围仅限于具有该确切维度集的指标。这些标签键的顺序无关紧要。  
例如：  
+ **SELECT AVG(CPUUtilization) FROM "AWS/EC2"** 匹配 `AWS/EC2` 命名空间中的所有 `CPUUtilization` 指标（无论它们的维度如何），并且会返回单个聚合时间序列。
+ **SELECT AVG(CPUUtilization) FROM SCHEMA("AWS/EC2")** 只匹配 `AWS/EC2` 命名空间中没有定义任何维度的 `CPUUtilization` 指标。
+ **SELECT AVG(CPUUtilization) FROM SCHEMA("AWS/EC2", InstanceId)** 只匹配向 CloudWatch 报告且只有一个维度（即 `CPUUtilization`）的 `InstanceId` 指标。
+ **SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)** 只匹配从 `AWS/ApplicationELB` 向 CloudWatch 报告且只带有 `LoadBalancer` 和 `AvailabilityZone` 两个维度的 `RequestCount` 指标。

**WHERE**  
可选。使用一个或多个标签键的特定标签值，将结果筛选为仅与指定表达式匹配的指标。例如，**WHERE InstanceType = 'c3.4xlarge'** 将结果筛选为仅 `c3.4xlarge` 实例类型，**WHERE InstanceType \$1= 'c3.4xlarge'** 将结果筛选为除 `c3.4xlarge` 外的所有实例类型。  
在监控账户中运行查询时，可以利用 `WHERE AWS.AccountId` 将查询结果限制到指定账户。例如，`WHERE AWS.AccountId=444455556666` 仅查询账户 `444455556666` 的指标。要将查询限制为仅限监控账户本身中的指标，请使用 `WHERE AWS.AccountId=CURRENT_ACCOUNT_ID()`。  
标签值必须始终放在单引号中。  
**在 WHERE 子句中使用标签**  
可通过 `tag.keyName` 语法，按 Amazon 资源标签筛选查询结果。标签筛选遵循与维度筛选相同的运算符规则。例如：  
+ WHERE `tag.env = 'prod'`：筛选出标签为 *env=prod* 的资源对应的指标
+ WHERE `tag.department != 'test'`：排除标签为 *department=test* 的资源对应的指标
标签筛选可与维度筛选组合使用：  
`WHERE tag.env = 'prod' AND InstanceType = 'm5.large'`  
**支持的运算符**  
**WHERE** 子句支持以下运算符：  
+ **=** 标签值必须与指定的字符串匹配。
+ **\$1=** 标签值不得与指定的字符串匹配。
+ **AND** 指定的两个条件都必须为真才能匹配。您可以使用多个 **AND** 关键字来指定两个或更多条件。

**GROUP BY**  
可选。将查询结果分组为多个时间序列，每个时间序列对应指定的一个或多个标签键的不同值。例如，使用 `GROUP BY InstanceId` 为每个 `InstanceId` 值返回不同的时间序列。使用 `GROUP BY ServiceName, Operation` 为 `ServiceName` 和 `Operation` 值的每个可能组合创建不同的时间序列。  
通过 **GROUP BY** 子句，默认情况下，将使用 **GROUP BY** 子句中指定的标签序列将结果按字母升序排列。要更改结果的顺序，请在查询中添加 **ORDER BY** 子句。  
在监控账户中运行查询时，您可以使用 `GROUP BY AWS.AccountId` 来按照结果的来源账户对结果进行分组。  
**在 GROUP BY 子句中使用标签**  
可通过 `tag.keyName` 语法，按 Amazon 资源标签的值对查询结果进行分组。例如：  
+ *GROUP BY tag.environment*：按环境标签的不同取值生成独立的时间序列
+ *GROUP BY tag.team, InstanceType*：同时按标签和维度的取值进行分组
+ *GROUP BY tag.team, AWS.AccountId*：同时按标签和关联的源账户 ID 进行分组
如果某些匹配的指标不包含 **GROUP BY** 子句中指定的标签键，则会返回名为 `Other` 的空组。例如，如果指定 `GROUP BY ServiceName, Operation` 而且某些返回的指标不包括作为维度的 `ServiceName`，则这些指标将显示为将 `Other` 作为 `ServiceName` 的值。

**ORDER BY**  
可选。如果查询返回多个时间序列，则指定返回的时间序列的使用顺序。该顺序基于您在 **ORDER BY** 子句中指定的 **FUNCTION** 找到的值。**FUNCTION** 用于计算每个返回的时间序列中的单个标量值，该值用于确定顺序。  
还可以指定使用升序 **ASC** 或降序 **DESC**。如果您省略这一步，则默认为升序 **ASC**。  
例如，添加 `ORDER BY MAX() DESC` 子句将按时间范围内观察到的最大数据点以降序对结果进行排序：这意味着具有最高最大数据点的时间序列会首先返回。  
要在 **ORDER BY** 子句中使用的有效函数为 `AVG()`、`COUNT()`、`MAX()`、`MIN()` 和 `SUM()`。  
如果您将 **ORDER BY** 子句与 **LIMIT** 子句配合使用，则生成的查询为“前 N 个”查询。**ORDER BY** 对于可能返回大量指标的查询也很有用，因为每个查询返回的时间序列不超过 500 个。如果查询匹配超过 500 个时间序列，并且您使用 **ORDER BY** 子句并对时间序列进行排序，则排序中前 500 个时间序列是返回的时间序列。

**LIMIT**  
可选。将查询返回的时间序列数量限制为指定的值。您可以指定的最大值为 500，而不指定 **LIMIT** 的查询也可以返回不超过 500 个时间序列。  
将 **LIMITED** 子句与 **ORDER BY** 子句配合使用，将获得“前 N 个”查询。

## 什么内容需要引号或转义字符？
<a name="cloudwatch-metrics-insights-syntaxdetails"></a>

在查询中，标签值必须始终放在单引号中。例如，**SELECT MAX(CPUUtilization) FROM "AWS/EC2" WHERE AutoScalingGroupName = 'my-production-fleet'**。

包含字母、数字和下划线 (\$1) 以外的字符的指标命名空间、指标名称和标签键必须放在双引号中。例如，**SELECT MAX("My.Metric")**。

如果其中一个已包含双引号或单引号（如 `Bytes"Input"`），您必须用反斜杠转义每个引号，如 **SELECT AVG("Bytes\$1"Input\$1"")**。

如果指标命名空间、指标名称或标签键包含的词为 Metrics Insights 中的保留关键字，则这些词也必须放在双引号中。例如，如果您有名为 `LIMIT` 的指标，您可以使用 `SELECT AVG("LIMIT")`。将任何命名空间、指标名称或标签（即使不包含保留关键字）放在双引号中也有效。

有关保留关键字的完整列表，请参阅 [保留关键字](cloudwatch-metrics-insights-reserved-keywords.md)。

## 逐步构建丰富的查询
<a name="cloudwatch-metrics-insights-syntaxexample"></a>

本节说明了如何逐步构建一个使用所有可能子句的完整示例。

您可从以下查询开始，该查询聚合了使用 `LoadBalancer` 和 `AvailabilityZone` 两个维度收集的所有应用程序负载均衡器 `RequestCount` 指标。

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
```

如果只想查看来自特定负载均衡器的指标，您可以添加 **WHERE** 子句，将返回的指标限制为 `LoadBalancer` 维度的值为 `app/load-balancer-1` 的指标。

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
```

前面的查询将此负载均衡器的所有可用区中的 `RequestCount` 指标聚合为一个时间序列。如果想看到每个可用区的不同时间序列，可以添加 **GROUP BY** 子句。

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
```

接下来可对查询结果进行排序，优先展示数值最大的结果。以下 **ORDER BY** 子句按查询时间范围内每个时间序列报告的最大值以降序对时间序列进行排序：

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
ORDER BY MAX() DESC
```

您也可通过标签对查询结果做进一步筛选。例如，若希望仅查看带有特定环境标签的负载均衡器对应的结果，可在 WHERE 子句中添加标签筛选条件：

```
SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone) WHERE LoadBalancer = 'app/load-balancer-1' AND tag.Environment = 'prod' GROUP BY AvailabilityZone ORDER BY MAX() DESC
```

您也可依据标签值对查询结果进行分组，替代维度分组（或在维度分组基础上叠加标签值分组）。例如，按应用程序标签分组：

```
SELECT SUM(RequestCount) FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone) WHERE tag.Environment = 'prod' GROUP BY tag.Application ORDER BY MAX() DESC
```

最后，如果我们主要对“前 N 个”类型的查询感兴趣，我们可以使用 **LIMIT** 子句。这最后一个例子将结果限制为仅带有五个最高 `MAX` 值的时间序列。

```
SELECT SUM(RequestCount) 
FROM SCHEMA("AWS/ApplicationELB", LoadBalancer, AvailabilityZone)
WHERE LoadBalancer = 'app/load-balancer-1'
GROUP BY AvailabilityZone
ORDER BY MAX() DESC
LIMIT 5
```

## 跨账户查询示例
<a name="cloudwatch-metrics-insights-crossaccount"></a>

这些示例在 CloudWatch 跨账户可观测性中设置为监控账户的账户中运行时有效。

以下示例搜索源账户 123456789012 中的所有 Amazon EC2 实例并返回平均值。

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
WHERE AWS.AccountId ='123456789012'
```

以下示例查询所有关联源账户中 `AWS/EC2` 的 `CPUUtilization` 指标，并按账户 ID 和实例类型对结果进行分组。

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
GROUP BY AWS.AccountId, InstanceType
```

以下示例查询监控账户本身中的 `CPUUtilization`。

```
SELECT AVG(CpuUtilization) 
FROM "AWS/EC2" 
WHERE AWS.AccountId = CURRENT_ACCOUNT_ID()
```