

# 评估预置容量以在 DynamoDB 表中预置合适的容量大小
<a name="CostOptimization_RightSizedProvisioning"></a>

本节概述如何评估您的 DynamoDB 表预置大小是否合适。随着工作负载的演变，您应该相应地修改操作程序，尤其是当您的 DynamoDB 表以预置模式配置时，因为它们可能存在过度配置或配置不足的风险。

下述程序需要来自于支持您的生产应用程序的 DynamoDB 表的统计信息。要了解您的应用程序行为，应该定义一个足够长的周期，以捕捉应用程序中的数据季节性特点。例如，如果您的应用程序表现出周模式，则不妨使用三周的周期来分析应用程序吞吐量需求。

如果您不知道从哪里开始，可根据至少一个月的使用数据来进行以下计算。

在评估容量时，DynamoDB 表可以独立配置**读取容量单位 (RCU)** 和**写入容量单位 (WCU)**。如果您的表配置了任何全局二级索引 (GSI)，则需要指定它们将占用的吞吐量，这些吞吐量也将独立于基表的 RCU 和 WCU。

**注意**  
本地二级索引 (LSI) 占用基表的容量。

**Topics**
+ [如何检索 DynamoDB 表上的占用指标](#CostOptimization_RightSizedProvisioning_ConsumptionMetrics)
+ [如何识别配置不足的 DynamoDB 表](#CostOptimization_RightSizedProvisioning_UnderProvisionedTables)
+ [如何识别过度配置的 DynamoDB 表](#CostOptimization_RightSizedProvisioning_OverProvisionedTables)

## 如何检索 DynamoDB 表上的占用指标
<a name="CostOptimization_RightSizedProvisioning_ConsumptionMetrics"></a>

要评估表和 GSI 容量，请监控以下 CloudWatch 指标，然后选择适当的维度来检索表或 GSI 信息：


| 读取容量单位 | 写入容量单位 | 
| --- | --- | 
|  `ConsumedReadCapacityUnits`  |  `ConsumedWriteCapacityUnits`  | 
|  `ProvisionedReadCapacityUnits`  |  `ProvisionedWriteCapacityUnits`  | 
|  `ReadThrottleEvents`  |  `WriteThrottleEvents`  | 

您可以通过 AWS CLI 或 AWS 管理控制台 来执行此操作。

------
#### [ AWS CLI ]

在检索表占用指标之前，我们需要先使用 CloudWatch API 捕获一些历史数据点。

首先创建两个文件：`write-calc.json` 和 `read-calc.json`。这些文件将代表表或 GSI 的计算。您需要更新一些字段，如下表所示，以匹配您的环境。


| 字段名称 | 定义 | 示例 | 
| --- | --- | --- | 
| <table-name> | 您将分析的表的名称 | SampleTable | 
| <period> | 您将用来评估利用率目标的周期，以秒为单位 | 对于 1 小时的周期，应指定：3600 | 
| <start-time> | 评估间隔的开始时间，以 ISO8601 格式指定 | 2022-02-21T23:00:00 | 
| <end-time> | 评估间隔的结束时间，以 ISO8601 格式指定 | 2022-02-22T06:00:00 | 

写入计算文件将检索指定日期范围内的时间段中所预置和消耗的 WCU 数量。它还将生成用于分析的利用率百分比。`write-calc.json` 文件的完整内容应类似如下：

```
{
  "MetricDataQueries": [
    {
      "Id": "provisionedWCU",
      "MetricStat": {
        "Metric": {
          "Namespace": "AWS/DynamoDB",
          "MetricName": "ProvisionedWriteCapacityUnits",
          "Dimensions": [
            {
              "Name": "TableName",
              "Value": "<table-name>"
            }
          ]
        },
        "Period": <period>,
        "Stat": "Average"
      },
      "Label": "Provisioned",
      "ReturnData": false
    },
    {
      "Id": "consumedWCU",
      "MetricStat": {
        "Metric": {
          "Namespace": "AWS/DynamoDB",
          "MetricName": "ConsumedWriteCapacityUnits",
          "Dimensions": [
            {
              "Name": "TableName",
              "Value": "<table-name>""
            }
          ]
        },
        "Period": <period>,
        "Stat": "Sum"
      },
      "Label": "",
      "ReturnData": false
    },
    {
      "Id": "m1",
      "Expression": "consumedWCU/PERIOD(consumedWCU)",
      "Label": "Consumed WCUs",
      "ReturnData": false
    },
    {
      "Id": "utilizationPercentage",
      "Expression": "100*(m1/provisionedWCU)",
      "Label": "Utilization Percentage",
      "ReturnData": true
    }
  ],
  "StartTime": "<start-time>",
  "EndTime": "<ent-time>",
  "ScanBy": "TimestampDescending",
  "MaxDatapoints": 24
}
```

读取计算文件使用类似的文件。此文件将检索指定日期范围内的时间段中预置和消耗了多少 RCU。`read-calc.json` 文件的内容应与以下内容类似：

```
{
  "MetricDataQueries": [
    {
      "Id": "provisionedRCU",
      "MetricStat": {
        "Metric": {
          "Namespace": "AWS/DynamoDB",
          "MetricName": "ProvisionedReadCapacityUnits",
          "Dimensions": [
            {
              "Name": "TableName",
              "Value": "<table-name>"
            }
          ]
        },
        "Period": <period>,
        "Stat": "Average"
      },
      "Label": "Provisioned",
      "ReturnData": false
    },
    {
      "Id": "consumedRCU",
      "MetricStat": {
        "Metric": {
          "Namespace": "AWS/DynamoDB",
          "MetricName": "ConsumedReadCapacityUnits",
          "Dimensions": [
            {
              "Name": "TableName",
              "Value": "<table-name>"
            }
          ]
        },
        "Period": <period>,
        "Stat": "Sum"
      },
      "Label": "",
      "ReturnData": false
    },
    {
      "Id": "m1",
      "Expression": "consumedRCU/PERIOD(consumedRCU)",
      "Label": "Consumed RCUs",
      "ReturnData": false
    },
    {
      "Id": "utilizationPercentage",
      "Expression": "100*(m1/provisionedRCU)",
      "Label": "Utilization Percentage",
      "ReturnData": true
    }
  ],
  "StartTime": "<start-time>",
  "EndTime": "<end-time>",
  "ScanBy": "TimestampDescending",
  "MaxDatapoints": 24
}
```

创建文件后，即可以开始检索利用率数据。

1. 要检索写入利用率数据，请发出以下命令：

   ```
   aws cloudwatch get-metric-data --cli-input-json file://write-calc.json
   ```

1. 要检索读取利用率数据，请发出以下命令：

   ```
   aws cloudwatch get-metric-data --cli-input-json file://read-calc.json
   ```

这两个查询的结果都将是一系列 JSON 格式的数据点，将用于分析。您的结果将取决于您指定的数据点数量、周期和您自己的特定工作负载数据。它可能如下所示：

```
{
    "MetricDataResults": [
        {
            "Id": "utilizationPercentage",
            "Label": "Utilization Percentage",
            "Timestamps": [
                "2022-02-22T05:00:00+00:00",
                "2022-02-22T04:00:00+00:00",
                "2022-02-22T03:00:00+00:00",
                "2022-02-22T02:00:00+00:00",
                "2022-02-22T01:00:00+00:00",
                "2022-02-22T00:00:00+00:00",
                "2022-02-21T23:00:00+00:00"
            ],
            "Values": [
                91.55364583333333,
                55.066631944444445,
                2.6114930555555556,
                24.9496875,
                40.94725694444445,
                25.61819444444444,
                0.0
            ],
            "StatusCode": "Complete"
        }
    ],
    "Messages": []
}
```

**注意**  
如果您指定了短周期和长时间范围，则可能需要修改 `MaxDatapoints`，该值在脚本中默认设置为 24。这表示每小时一个数据点，每天 24 个数据点。

------
#### [ AWS 管理控制台 ]

1. 登录 AWS 管理控制台，并导航到 CloudWatch 服务页面。根据需要选择合适的 AWS 区域。

1. 在左侧导航栏中，找到**指标**部分，然后选择**全部指标**。

1. 这将打开一个控制面板，其中包含两个面板。顶部面板显示图形，底部面板显示用于绘图的指标。选择 **DynamoDB**。

1. 选择**表指标**。这将显示您当前所在区域中的表。

1. 使用搜索框搜索您的表名并选择写入操作指标：`ConsumedWriteCapacityUnits` 和 `ProvisionedWriteCapacityUnits`
**注意**  
本例中使用了写入操作指标，但您也可以使用这些步骤绘制读取操作指标图。

1. 选择**绘成图表的指标（2）**选项卡来修改公式。默认情况下，CloudWatch 为图表选择统计函数 **Average**。  
![\[选定的图表指标和 Average 作为默认统计函数。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning1.png)

1. 选中两个图表化指标（左侧的复选框）后，选择菜单**添加数学函数**，然后选择**常用**，再选择 **Percentage** 函数。重复该过程两次。

   第一次选择 **Percentage** 函数：  
![\[CloudWatch 控制台。已为绘成图表的指标选择百分比函数。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning2.png)

   第二次选择 **Percentage** 函数：  
![\[CloudWatch 控制台。再次为绘成图表的指标选择百分比函数。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning3.png)

1. 此时，底部菜单中应该有四个指标。我们来进行 `ConsumedWriteCapacityUnits` 计算。为了保持一致，我们需要使这些名称与在 AWS CLI 节中使用的匹配。单击 **m1 ID** 并将此值更改为 **consumedWCU**。  
![\[CloudWatch 控制台。ID 为 m1 的绘成图表的指标已重命名为 consumedWCU。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning4.png)

   将 **ConsumedWriteCapacityUnit** 标签重命名为 **consumedWCU**。  
![\[带 ConsumedWriteCapacityUnit 标签的绘成图表的指标已重命名为 consumedWCU。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning5.png)

1. 将统计函数从 **Average** 改为 **Sum**。此操作将自动创建另一个名为 **ANOMALY\$1DETECTION\$1BAND** 的指标。对于此过程的范围，我们可通过删除新生成的 **ad1 指标**上的复选框来忽略它。  
![\[CloudWatch 控制台。在绘成图表的指标的下拉列表中选择了统计信息 SUM。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning6.png)  
![\[CloudWatch 控制台。从绘成图表的指标的列表中删除 ANOMALY_DETECTION_BAND 指标。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning7.png)

1. 重复步骤 8，将 **m2 ID** 重命名为 **provisionedWCU**。保留统计函数设置为 **Average**。  
![\[CloudWatch 控制台。ID 为 m2 的绘成图表的指标重命名为 provisionedWCU。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning8.png)

1. 选择 **Expression1** 标签，并将值更新为 **m1**，将标签更新为 **Consumed WCUs**。
**注意**  
确保您只选择了 **m1**（左侧的复选框）和 **provisionedWCU** 以正确可视化数据。更新公式，方法是单击**详细信息**并将公式更改为 **consumedWCU/PERIOD(consumedWCU)**。这一步还可能生成另一个 **ANOMALY\$1DETECTION\$1BAND** 指标，但对于此过程的范围，我们可以忽略它。  

![\[已选择 m1 和 provisionedWCU。m1 的详细信息已更新为 consumedWCU/PERIOD(consumedWCU)。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning10.png)


1. 您现在应该有两个图形：一个指示表上预置的 WCU，另一个指示已使用的 WCU。您的图形形状可能与下面的不同，不过可以将其作为参考：  
![\[图中绘制了表的预置 WCU 和已使用 WCU。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning11.png)

1. 通过选择 Expression2 图形 (**e2**) 来更新百分比公式。将标签和 ID 重命名为 **utilizationPercentage**。重命名公式，以匹配 **100\$1(m1/provisionedWCU)**。  
![\[CloudWatch 控制台。Expression2 的标签和 ID 已重命名为 utilizationPercentage。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning12.png)  
![\[CloudWatch 控制台。Expression2 的百分比公式已更新为 100*(m1/provisionedWCU)。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning13.png)

1. 清除除 **utilizationPercentage** 之外的所有指标的复选框，以可视化您的利用率模式。默认间隔设置为 1 分钟，但您可以根据需要随意修改。  
![\[图中显示了所选时间间隔内的 utilizationPercentage 指标。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning14.png)

以下是一个更长的时间段和一个更大的 1 小时周期的视图。可以看到，一些间隔的利用率超过 100%，不过这种特定的工作负载具有较长的零利用率间隔。

![\[较长时段的利用率模式。它突出显示了利用率超过 100% 和零的时段。\]](http://docs.aws.amazon.com/zh_cn/amazondynamodb/latest/developerguide/images/CostOptimization/RightSizedProvisioning15.png)


此时，您可能获得与本例中的图片不同的结果。这完全取决于您的工作负载中的数据。利用率超过 100% 的间隔容易导致节流事件。DynamoDB 提供[容量暴增](burst-adaptive-capacity.md#burst-capacity)，不过一旦容量暴增，任何超过 100% 的流量都将被节流。

------

## 如何识别配置不足的 DynamoDB 表
<a name="CostOptimization_RightSizedProvisioning_UnderProvisionedTables"></a>

对于大多数工作负载，如果一个表持续消耗其配置容量超过 80%，则该表被视为配置不足。

[容量暴增](burst-adaptive-capacity.md#burst-capacity)是 DynamoDB 的一项功能，它允许客户临时消耗比最初配置更多的 RCU/WCU（超过表中定义的每秒预调配吞吐量）。创建容量暴增的目的是应对因特殊事件或使用量高峰而突然增加的流量。这种容量暴增不能永远持续下去。一旦未用的 RCU 和 WCU 耗尽，您再试图消耗比预置更多的容量时，就会被节流。当您的应用程序流量接近 80% 的利用率时，被节流的风险会大大增加。

80% 的利用率规则因数据的季节性和流量增长而异。考虑以下场景：
+ 如果您的流量在过去 12 个月中一直**稳定**在大约 90% 的利用率，那么您的表容量正合适
+ 如果您的应用程序流量在不到 3 个月内以每月 8% 的速度**增长**，那么您将达到 100% 利用率
+ 如果您的应用程序流量在略长于 4 个月内以每月 5% 的速度**增长**，那么您仍然将达到 100% 利用率

以上查询的结果可以说明您的利用率。将它们作为指导，来进一步评估其他指标，以帮助您在需要时选择增加表容量（例如：每月或每周增长率）。与您的运营团队合作，为您的工作负载和表定义一个合适的百分比。

在有些特殊场景中，当我们每天或每周进行数据分析时，会发现数据是倾斜的。例如，季节性应用程序在工作时间会出现使用量激增情况（但在工作时间之外则降至几乎为零），您可以通过[安排自动扩缩](https://docs.aws.amazon.com/autoscaling/application/userguide/examples-scheduled-actions.html)来轻松指定一天中什么时间（以及一周中的星期几）增加预置容量，以及何时减少预置容量。即使您的季节性不那么明显，也可以利用 [DynamoDB 表自动扩缩](AutoScaling.md)配置，而无需为了涵盖繁忙时间而设定较高的容量。

**注意**  
为基表创建 DynamoDB Auto Scaling 配置时，请记住为任何与该表关联的 GSI 包括另一个配置。

## 如何识别过度配置的 DynamoDB 表
<a name="CostOptimization_RightSizedProvisioning_OverProvisionedTables"></a>

从上述脚本中获得的查询结果提供了执行某些初始分析所需的数据点。如果您的数据集在多个时间间隔内显示为利用率低于 20%，则您的表可能配置过度。要进一步确定是否需要减少 WCU 和 RCU 的数量，应重新查看间隔内的其他读数。

当您的表包含多个低使用量间隔时，您其实可以利用自动扩缩策略，安排自动扩缩，或者为表配置基于利用率的默认自动扩缩策略。

如果您的工作负载具有低利用率和高节流比率（间隔内的 **Max(ThrottleEvents)/Min(ThrottleEvents)**），这说明在某些天（或几小时）内流量大增，因而造成了非常高的工作负载，但总体上流量一直较低。在这些场景中，使用[预定自动扩缩](https://docs.aws.amazon.com/autoscaling/application/userguide/examples-scheduled-actions.html)可能有所裨益。