ホットパーティション
特定のパーティションにアクセスが集中し、スループットが低下する DynamoDB の性能問題
ホットパーティションとは
ホットパーティション (Hot Partition) は、DynamoDB で特定のパーティションにリクエストが集中し、そのパーティションのスループット上限に達してスロットリングが発生する性能問題である。テーブル全体のキャパシティに余裕があっても、1 つのパーティションが飽和した時点でリクエストは弾かれる。返る例外はキャパシティモードで違い、プロビジョンドモードでは ProvisionedThroughputExceededException、オンデマンドモードでは ThrottlingException になる。
DynamoDB はパーティションキーのハッシュ値でデータを物理パーティションに分散する。パーティションキーの設計が偏っていると、特定のパーティションにアクセスが集中する。
なぜ発生するか
DynamoDB の各パーティションには、1 秒あたり最大 3,000 RCU (読み取り) / 1,000 WCU (書き込み) の上限がある。テーブルに 10,000 WCU をプロビジョニングしても、10 パーティションに均等分散されれば各パーティションは 1,000 WCU だ。1 つのパーティションキーに書き込みが集中すると、その 1,000 WCU を超えた時点でスロットリングが発生する。
テーブル全体: 10,000 WCU (10 パーティション)
パーティション A: 8,000 WCU のリクエスト → スロットリング発生
パーティション B〜J: 各 200 WCU → 余裕あり
ホットパーティションを引き起こすキー設計
日付をパーティションキーにする
PK: "2026-04-01" ← 今日のデータに全アクセスが集中
PK: "2026-03-31" ← 昨日のデータはほぼアクセスなし
IoT データやログの蓄積で日付をパーティションキーにすると、常に「今日」のパーティションがホットになる。
ステータスをパーティションキーにする
PK: "ACTIVE" ← アクティブユーザーが大多数
PK: "INACTIVE" ← 少数
PK: "SUSPENDED" ← ごく少数
カーディナリティ (値の種類数) が低いキーは、特定の値にデータが偏る。
人気商品の ID
EC サイトで商品 ID をパーティションキーにすると、セール中の人気商品にアクセスが集中する。通常時は問題なくても、タイムセール開始時にスパイクが発生する。
対策
Write Sharding (書き込みシャーディング)
パーティションキーにランダムなサフィックスを付与し、書き込みを複数パーティションに分散する。
// ❌ 日付だけ → ホットパーティション
const pk = '2026-04-01';
// ✅ ランダムサフィックスで分散
const shardCount = 10;
const shard = Math.floor(Math.random() * shardCount);
const pk = `2026-04-01#${shard}`; // "2026-04-01#0" 〜 "2026-04-01#9"
読み取り時は全シャードに対して並列クエリし、結果をマージする。書き込みの分散と引き換えに、読み取りの複雑さが増すトレードオフがある。
サフィックスは乱数でなくてもよい。検索条件に使う属性から計算した値 (例えばユーザー ID のハッシュを shardCount で割った余り) をサフィックスにすれば、読み取り時に見るべきシャードが一意に決まり、全シャード走査が不要になる。特定のアイテムを直接引くアクセスパターンが残っているなら、乱数より先にこちらを検討する。
複合キーの設計
パーティションキーにカーディナリティの高い属性を組み合わせる。
// ❌ ステータスだけ
PK: "ACTIVE"
// ✅ ユーザー ID + ステータス
PK: "USER#usr-123"
SK: "STATUS#ACTIVE"
GSI (Global Secondary Index) でステータス別の検索が必要な場合は、GSI のパーティションキーにステータスを使いつつ、Sparse Index (該当するアイテムだけがインデックスに含まれる) で偏りを減らす。
GSI にも同じパーティション上限が効くことを忘れやすい。ベーステーブルのキー設計が良くても、カーディナリティの低い属性をそのまま GSI のパーティションキーにすれば GSI 側がホットになる。さらに厄介なのは影響の向きだ。GSI の書き込みキャパシティ不足はベーステーブルへ跳ね返り、ベーステーブルとその他の GSI への書き込みまで失敗させる (読み取り側のスロットリングはベーステーブルに影響しない)。GSI は読み取りの逃げ道ではなく、もう 1 つの書き込み経路として容量とキー設計を点検する。
DynamoDB のアダプティブキャパシティ
DynamoDB はアダプティブキャパシティにより、トラフィックが偏ったパーティションへ自動で、しかも即時にキャパシティを振り向ける。全テーブルで既定で有効・追加費用なしなので、設定作業は要らない。
効くのは 2 つの枠の内側だけだ。プロビジョンドモードではテーブルにプロビジョニングした総量を超えて配ることはできず、パーティションあたりの上限 (3,000 RCU / 1,000 WCU) 自体も動かない。1 つのパーティションキーへの需要が単独で 1,000 WCU を超えるなら、アダプティブキャパシティでは救えない。偏りが継続すれば観測に基づいてパーティションが分割されることもあるが、これは時間をかけた調整であり、突発的なスパイクには間に合わない。緩和策であって根本解決ではない。
バーストキャパシティ (直前 5 分間の未使用キャパシティを取り置く仕組み) も同様に、パーティション上限に当たったスロットリングは救えない。
検出方法
CloudWatch メトリクス
CloudWatch のキャパシティメトリクスはテーブルとインデックスの単位までしか分解できない。ConsumedWriteCapacityUnits がプロビジョンド値に届いていないのにスロットリングが出ている、という乖離までは読み取れるが、どのパーティションキーが原因かはここでは分からない。
キー単位まで降りるには CloudWatch Contributor Insights を有効にする。最もアクセスの多いキーと、最もスロットリングされたキーが可視化される。有効化すると追加の課金が発生するため、常時有効にするか調査時だけ入れるかは事前に決めておく。
# Contributor Insights の有効化
aws dynamodb update-contributor-insights \
--table-name MyTable \
--contributor-insights-action ENABLE
スロットリングの監視
パーティション上限に当たったのかどうかは、専用のメトリクスで切り分けられる。WriteKeyRangeThroughputThrottleEvents と ReadKeyRangeThroughputThrottleEvents が立っていれば、テーブルやインデックスのキャパシティではなくパーティション上限が原因だと確定できる (2026 年 8 月時点)。プロビジョンド値そのものの不足なら WriteProvisionedThroughputThrottleEvents 側が立つ。
ThrottledRequests はリクエスト単位の粗いメトリクスで、原因の切り分けには向かない。バッチリクエスト (BatchGetItem / BatchWriteItem) では全件がスロットリングされたときだけ加算され、一部だけ弾かれた場合は ReadThrottleEvents / WriteThrottleEvents にしか現れない。ThrottledRequests が 0 でも偏りは進行し得る。
オンデマンドモードでも発生する
オンデマンドキャパシティモードでもホットパーティションは発生する。オンデマンドはテーブル全体のスループットを自動スケールするが、パーティションあたりの 3,000 RCU / 1,000 WCU はキャパシティモードに関係なく効く。キー設計の問題はキャパシティモードでは解決できない。
オンデマンド固有の上限も 2 つ押さえておく。1 つはテーブルまたは個々の GSI あたり 1 秒あたり 40,000 読み取り / 40,000 書き込みリクエストユニットという既定のクォータで、超えると RequestLimitExceeded が返る (2026 年 8 月時点・Service Quotas から引き上げ可)。もう 1 つは自分で設定する最大スループットで、こちらを超えると ThrottlingException になる。いずれもテーブル単位の話で、パーティションの偏りとは別の軸だ。
症状から手を選ぶ
| 症状 | 取るべき手 | 落とし穴 |
|---|---|---|
| カーディナリティの低いキー (ステータス・区分) | パーティションキーを一意性の高い属性 (userId, orderId) へ移し、絞り込み条件はソートキーへ | GSI のパーティションキーにも同じ基準を当てる |
| 単一キーへの書き込み集中 (日付・カウンター) | Write Sharding でキー空間を広げる | 読み取りが全シャード走査になるなら計算サフィックスを選ぶ |
| 短時間のスパイクだけ | 事前のキャパシティ引き上げと、指数バックオフでの再試行 | アダプティブキャパシティもバーストキャパシティもパーティション上限は超えられない |
| GSI 側だけスロットリングしている | GSI のキー設計と射影属性を見直す | 書き込みのスロットリングはベーステーブルへ跳ね返る |
ホットパーティションの背景や設計思想は関連書籍に詳しい。
この記事は役に立ちましたか?
関連用語
DynamoDB
AWS のフルマネージド NoSQL データベースで、ミリ秒単位のレイテンシとシームレスなスケーリングを提供する
シングルテーブル設計
DynamoDB で複数のエンティティを 1 つのテーブルに格納し、キー設計で関連データを 1 回の Query にまとめる設計手法
シャーディング
データを複数のデータベースインスタンスに水平分割し、書き込みスループットとストレージ容量をスケールさせる手法
Apache Kafka
大規模なリアルタイムデータストリーミングのための分散メッセージングプラットフォーム
データベースマイグレーション戦略
本番環境のデータベーススキーマを安全に変更するための戦略とパターン
DynamoDB Streams
DynamoDB テーブルの変更をリアルタイムでキャプチャし、Lambda で処理するイベントソース