中級読了 4 分

DynamoDB Auto Scaling (オートスケーリング) の設定方法

DynamoDB のオートスケーリングは、プロビジョンドテーブルの読み取りキャパシティと書き込みキャパシティを、あなたが選んだターゲット使用率に近づくように調整します。 RCU/WCU を手で調整することも、最悪ケースの予約に 24 時間ずっと支払うこともなくなります。

オートスケーリングはプロビジョンドキャパシティにしか適用されません。まだキャパシティモードを決めていないなら、オンデマンド vs プロビジョンドから始めてください。

DynamoDB テーブルでオートスケーリングを有効にするには?

コンソールでは、テーブルを開いて Additional settings → Read/write capacity → Edit と進み、Provisioned を選び、読み取りキャパシティ、書き込みキャパシティ、またはその両方について Auto scaling を On にします。

それぞれに最小値、最大値、そしてターゲット使用率 (20~90 パーセントの範囲で設定可能) を与えます。

CLI からは、aws application-autoscaling でスケーラブルターゲットを登録し、ターゲット追跡スケーリングポリシーをアタッチします。コンソールでプロビジョンドテーブルを作成した場合、オートスケーリングはデフォルトで有効です。

オートスケーリングは 2 つの CloudWatch アラームと UpdateTable

スケーリングポリシーは Application Auto Scaling に対して、テーブルの「消費キャパシティ対プロビジョンドキャパシティ」の比率を、設定した最小キャパシティと最大キャパシティの範囲内でターゲット使用率の近くに保つよう指示します。

内部では、上側と下側の境界に対して CloudWatch アラームのペアが作成されます。消費がどちらかを越えると、Application Auto Scaling が UpdateTable 呼び出しを発行してプロビジョンドキャパシティを動かします。

セットアップの前に、構造上の事実が2つ効いてきます。

  • ポリシーはテーブルごと、かつ GSI ごと。 すべてのグローバルセカンダリインデックスは自身のプロビジョンドスループットを持つので、それぞれに独自のポリシーが必要です (あるいはコンソールの「same settings for all GSIs」チェックボックス)。スケールの足りない GSI はベーステーブルの書き込みをスロットリングし得ます。 GSI がベーステーブルをスロットリングする理由を参照してください。
  • 既存テーブルに追加した GSI は、構築中はスケールしない。 AWS によれば、バックフィルが終わるまでそのキャパシティは手動で管理します。UpdateTable のインデックスの Create アクションで、バックフィルとライブの書き込みを合わせても足りる高さに ProvisionedThroughput を設定しましょう。インデックスが ACTIVE になったらスケーリングポリシーがあるかを確認し、なければ table/<table>/index/<index> に登録します。

引き受けることになるタイミング

オートスケーリングは事後反応型で、AWS はアラームのデータポイント数が調整できないことを文書化しています:

  • スケールアップは、消費キャパシティが連続2分間ターゲットを超えたあとに発動します (加えて CloudWatch のアラーム遅延が数分まで乗ります)。
  • スケールダウンは、ターゲットを下回る連続15個の1分間データポイントを待ちます。
  • どちらが発動しても、UpdateTable の呼び出しは適用までに数分かかり、その間、古いキャパシティを超えるリクエストはスロットリングされます。
DynamoDBApplicationAuto ScalingCloudWatchトラフィックDynamoDBApplicationAuto ScalingCloudWatchトラフィック更新が反映されるまで、旧上限を超えるリクエストはスロットリングされる消費量 > ターゲット、1分目消費量 > ターゲット、2分目アラーム発報UpdateTable(数分かかる)

つまり新しいキャパシティが届くのは、早くても超過の2分後で、そこに AWS が数値を示していない数分が加わります。オートスケーリングは緩やかな伸びには追随しますが、急な段差には追いつけません。

短いスパイクはたいていテーブルのベストエフォートのバーストキャパシティ (未使用キャパシティの最大 300 秒分) が吸収しますが、それを当てにしないでください。負荷を3倍にしてそのまま維持するフラッシュセールは、最小キャパシティがすでにその段差をカバーしていない限り、バーストを使い切った時点でスロットリングします。

前もって分かっている段差には、スケジュールに基づくスケーリングで到来前に床を引き上げ、それ以外の時間帯はターゲット追跡に任せましょう。両方の上下限を設定してください。そうしないと新しい最小値がターゲットに登録済みの最大値 (下の CLI 設定では 10) を超えてしまい、アクションは失敗します:

aws application-autoscaling put-scheduled-action \
    --service-namespace dynamodb \
    --scheduled-action-name pre-sale \
    --resource-id "table/TestTable" \
    --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
    --schedule "at(2026-11-27T07:00:00)" \
    --scalable-target-action MinCapacity=3000,MaxCapacity=6000

イベント後に2つ目のスケジュールアクションで両方の値を元に戻します (ここでは MinCapacity=5,MaxCapacity=10)。テーブルがそのレートを一度も処理したことがないなら、ウォームスループット (テーブルが即座に処理できるレート) を引き上げて事前ウォームもしておきましょう。これはどちらのキャパシティモードでも使えます。

オンデマンドに切り替えても問題は消えません。オンデマンドも、30 分以内にトラフィックが直前のピークの2倍を超えるとスロットリングし得ます。オンデマンドのスループット測定が、その上限と --warm-throughput コマンドを示しています。

コンソールで設定できるのは上下限と目標で、クールダウンは設定できない

既存のテーブルの場合 (AWS の手順):

  1. DynamoDB コンソール → Tables → 対象のテーブルを選びます。
  2. Additional settings タブ → Read/write capacity → Edit。
  3. Capacity mode: Provisioned。
  4. Table capacity の下で、読み取り、書き込み、またはその両方について Auto scaling を On に切り替え、それぞれに Minimum capacity units、 Maximum capacity units、Target utilization を設定します。
  5. 必要なら同じ設定をすべての GSI に適用し、Save します。

コンソールはクールダウンを公開していません。AWS は "for more advanced features like setting scale-in and scale-out cooldown times" には CLI を使うよう案内しています。

CLI ではクールダウンを設定でき、デフォルトは 0

ディメンションごとに2つの呼び出しです。スケーラブルターゲット (最小/最大の範囲) を登録し、次にターゲット追跡ポリシーをアタッチします。 AWS の CLI ウォークスルーから、テーブルの書き込みキャパシティについてそのまま引用します:

aws application-autoscaling register-scalable-target \
    --service-namespace dynamodb \
    --resource-id "table/TestTable" \
    --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
    --min-capacity 5 \
    --max-capacity 10

ポリシーの設定は JSON ファイルに置きます:

{
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
  },
  "ScaleOutCooldown": 60,
  "ScaleInCooldown": 60,
  "TargetValue": 50.0
}
aws application-autoscaling put-scaling-policy \
    --service-namespace dynamodb \
    --resource-id "table/TestTable" \
    --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
    --policy-name "MyScalingPolicy" \
    --policy-type "TargetTrackingScaling" \
    --target-tracking-scaling-policy-configuration file://scaling-policy.json

読み取りの場合は、ディメンションを dynamodb:table:ReadCapacityUnits に、メトリクスを DynamoDBReadCapacityUtilization に差し替えます。

GSI の場合は、リソース ID が table/TestTable/index/test-index になり、 dynamodb:index:* のディメンションを使います。GSI を3つ持つテーブルで両方のディメンションをスケールさせるには、ターゲット/ポリシーのペアが8組必要なので、スクリプト化しましょう。

2つのクールダウンは DynamoDB ではデフォルトが 0 で、CLI からしか設定できません。 ScaleOutCooldown はキャパシティ増加の間隔の最小秒数です (より大きなスケールアウトは、それでも即座に通ります)。

ScaleInCooldown は次の引き下げをブロックします。ただしスケールアウトは、スケールインのクールダウンを待つのではなく中断させます。

数値の選び方

ターゲット使用率は、余裕とコストのトレードオフです。ターゲットが T パーセントなら、消費キャパシティのおよそ 100/T 倍を支払うことになります。70% のターゲットは定常トラフィックの上に約1.4倍の余裕を、50% のターゲットは2倍を買います。

ターゲットが低いほど急な伸びを乗り切れ、高いほど無駄なキャパシティが減ります。

ターゲットは、オンデマンドに対する割引率も決めます。us-east-1 の定価で、使用率 70% に保たれたプロビジョンドキャパシティはリクエストあたり約2.4倍安く、50% なら約1.7倍、約29% を下回るとオンデマンドのほうが安くなります。

導出はオンデマンド vs プロビジョンドにあり、自分のワークロードの料金は料金計算ツールで算出できます。

最小キャパシティはスパイクに対する床です。オートスケーリングが反応するのに必要な数分間、すでにそこにあるキャパシティがこれです。平均トラフィックからではなく、スロットリングせずに吸収しなければならない最も鋭いバーストから決めましょう。

最大キャパシティは、バグや負荷テストが請求し得る額の上限です。現実的なピークより上に設定し、そこに到達することは通常の運用ではなくアラートとして扱いましょう。

スケールダウンにはクォータがあります。 プロビジョンドの引き下げはトークンバケットから出てきます。UTC の各日は使える4回から始まり、1時間ごとに1回ずつ (保持は最大4回まで) 貯まって、1テーブルあたり1日最大27回の引き下げになります。

そのため、スパイクのあとキャパシティはゆっくりとしか下がらず、1日に何度も振動するトラフィックは平均より高いプロビジョニングのまま1日を終えます。GSI のクォータは別枠ですが、テーブルとインデックスの両方を引き下げる1つのリクエストは、どちらか一方でもクォータが足りなければ丸ごと拒否されます。

トラフィックがそういう形なら、引き下げのクォータがないオンデマンドにテーブルを移しましょう。プロビジョンドのままにするなら、分かっている日次のピークをスケジュールしておき、オートスケーリングが事後反応のスケールインで引き下げ回数を使い果たさないようにします。

DynoTable でやってみる

最小値のサイジングは、アイテムがどれくらい大きく、いくつあるかから始まります。 DynoTable では、テーブルのツールバーにある 設定 ボタンで「テーブル設定」ダイアログが開きます。

その「概要」には DynamoDB のアイテム数とサイズの推定値 (約6時間ごとに更新) が表示され、設定 セクションでキャパシティモードと RCU/WCU を変更できます。

1つのアイテムをサイジングするには、無料のアイテムサイズ計算ツールがその RCU/WCU のフットプリントを計算します。クエリについては、Workbench のコストプレビューが Scan か Query かを示し、テーブルのメタデータが許す場合は実行前の RCU 見積もりも示します。

ホットキーとスケールしない GSI は依然としてスロットリングする

  • オートスケーリングはパーティションごとの上限を引き上げません。 ホットキーは、テーブルのキャパシティに余裕があってもスロットリングします。CloudWatch Contributor Insights で見つけて分散させましょう。ホットパーティションとアダプティブキャパシティを参照してください。
  • GSI を忘れずに。 各インデックスはそれ自身でスケールし (あるいはスロットリングし) ます。
  • リザーブドキャパシティはプロビジョンドの上にしか積み上がりません。 オートスケーリングがほとんど動かないほどワークロードが安定しているなら、次の割引はリザーブドキャパシティ (Standard テーブルクラス、プロビジョンドモード限定) です。オンデマンドのテーブルでは使えません。
  • 最初の1日は見張る。 CloudWatch でプロビジョンドの線に対して ConsumedReadCapacityUnits / ConsumedWriteCapacityUnits (1分ごとの Sum ÷ 60) を見れば、ターゲットが保たれているのか振動しているのかがすぐ分かります。Average 統計はリクエスト単位なので、線と一致しません。

キャパシティはコストモデルの1つの軸で、もう1つはクエリが何を消費するかです。 Query と Scanと SQL スキャンのコストモデルがその半分を扱います。

DynoTable をダウンロードして、テーブルのサイズとアイテム数の推定値を読み取り、クエリが Scan になるかどうかを、テーブルのメタデータが許す場合は実行前の RCU の目安とともに確認しましょう。

著者: Dmitriy · 更新日