中級読了 3 分

DynamoDB のパーティションキーの仕組み

あなたのは列ではありません — アドレスです。DynamoDB はそのキーをハッシュし、そのハッシュがどの物理マシンが項目を格納するかを決めます。キーをうまく選べば負荷は分散し、まずく選べば 1 台のサーバーが集中砲火を浴びます。

DynamoDB のパーティションキーはどう動きますか?

DynamoDB はあなたのを内部のハッシュ関数に通し、そのハッシュがどの物理パーティションが項目を格納するかを決めます。キーは SQL の列のようにソートされたりインデックスされたりしません — アドレスです。カーディナリティの高いキーを選べば負荷が多くのパーティションに分散し、低いものを選べば単一のパーティションが集中砲火を浴びます。

  • キーはソートされず、ハッシュされる。 DynamoDB はパーティションキーを内部ハッシュに通してパーティションを選びます。隣り合う 2 つの値は、ディスク上でまったく離れた場所に着地します。
  • パーティションは実在するストレージ単位。 それぞれおよそ 10 GB、毎秒 3,000 読み取りユニット、毎秒 1,000 書き込みユニットで上限に達します。あなたのトラフィックは、キーが分散するパーティションの数で割られます。
  • ホットキーが落とし穴。 ほとんどのリクエストを 1 つのパーティションキー値に集中させると、そのパーティションでスロットルされ、テーブルの残りは遊びます。
  • カーディナリティの高いキーが勝つ。 異なる、均等に叩かれるキー値が多いほど、より多くのパーティションが負荷を吸収します。

キーが実際に何をするかから始める

SQL から来ると、プライマリキーは JOINORDER BY する、ソートされインデックスされた列です。DynamoDB では パーティションキー(ハッシュキーとも呼ばれる)は別のことをします。配置 を決めるのです。

DynamoDB はパーティションキーを内部のハッシュ関数に入れます。その出力はキースペースに対応づけられ、キースペースは複数の範囲に分割されます — 各範囲は 物理パーティション が所有します。そのパーティションは実在するノード上の実在するストレージです。

つまりパーティションキーは 1 つの問いに答えます。どのマシンがこの項目を保持するか? は、あれば、そのマシン の中で 項目を順序づけるだけです。配置には一切関与しません。

1 つの書き込みをハッシュを通して追う

デバイスの読み取り値を取り込む SaaS を運営しているとします。テーブル SensorReadings はパーティションキー deviceId とソートキー readingTs を使います。deviceId = "vac-7741" の読み取り値を書き込みます。

その書き込みがたどる経路 — キーから着地するディスクまで — はこうです。

キースペースの区画PutItemdeviceId = 'vac-7741'パーティションキーをハッシュハッシュがキースペース上の1点に対応どの範囲が所有する?パーティション P2アイテムを保存、readingTs の順

vac-7741 の書き込みはキースペース内の一点にハッシュされ、その点は P2 の範囲に入り、項目は P2 に着地します — そこで readingTs で順序づけられます。

腹に落とすべきこと: "vac-7741""vac-7742" は 1 文字違いですが、そのハッシュは無関係です。ほぼ確実に異なるパーティションに存在します。パーティションのキースペースに「近く」はありません。

これは DynamoDB が元の設計から受け継いだコンシステントハッシュの考え方です — 2007 年の Amazon Dynamo 論文("Dynamo: Amazon's Highly Available Key-value Store")は、どの単一ノードもボトルネックにならないよう、まさにハッシュによってキーをノード間に分散させました。

下にパーティションキー値のリストを貼り付けて、ハッシュがそれらをバケットへどう散らすかを見てください。カーディナリティの高い集合は均等に分散し、1 つの値を使い回すとすべてが単一のバケットに積み上がります — 次のセクションで扱うです。

パーティションキーの分布

1行に1つのパーティションキーの値を入力します。値を繰り返すとホットキーをシミュレートできます。

8 バケット8 キー
  • #0
    0
  • #1
    1
  • #2
    1
  • #3
    0
  • #4
    2
  • #5
    2
  • #6
    0
  • #7
    2

これは教育用に簡略化したハッシュであり、DynamoDB の実際の内部ハッシュではありません。DynamoDB は非公開の内部関数と、テーブルに応じて増えるパーティション数を使用します — 異なるキーがどう分散し、単一のホットキーがどう積み上がるかの直感を養う目的にのみ使用してください。

これは 直感のための教育用ハッシュであって、DynamoDB の本物の内部ハッシュではありません — 実際の関数、キースペース、パーティション境界は AWS の内部仕様です。分散対偏りの感覚をつかむために使い、あるキーがどの物理パーティションに着地するかを予測するためには使わないでください。

パーティションのハードな上限を尊重する

物理パーティションは有限です。AWS DynamoDB デベロッパーガイドによれば、それぞれ最大でおよそ次を保持します。

上限パーティションあたり
ストレージ約 10 GB
読み取りスループット3,000 読み取りユニット/秒
書き込みスループット1,000 書き込みユニット/秒

パーティションが 10 GB を超えて埋まったり、プロビジョンドスループットにもっと余地が必要になったりすると、DynamoDB はそれを 分割 します — キースペースの範囲が分けられ、項目がより多くのパーティションに再分配されます。これは自動で、あなたがトリガーするものではありません。

落とし穴: 分割は 1 つのパーティションキーの項目コレクションをソートキーの境界で切り分けられるので、忙しいキーの負荷はより多くのパーティションに広がりえます。分割で救えないのは、単一のホットな 項目、単調増加するソートキー、あるいは LSI を持つテーブルです — それらはコレクションを単一のパーティションに固定します。

罠に名前を: ホットパーティション

ホットパーティション は古典的な落とし穴です。1 つのパーティションキー値(またはごく少数)がトラフィックの不均衡な割合を吸収するときに起きます。

具体的な失敗: SensorReadings をパーティションキー region に切り替え、"us-east""eu-west" のような値にします。3 つのリージョンは 3 つのキー値、つまり — せいぜい — 3 つのパーティションが実働することを意味します。"us-east" に読み取りを叩き込むと、テーブルの総プロビジョンドキャパシティが未使用のまま、3,000 RCU でスロットルします。

DynamoDB の 適応キャパシティ はこれを和らげます — 未使用のスループットを忙しいパーティションへ移し、単一の非常にホットなキーをそれ専用のパーティションに 隔離 できます。AWS は re:Invent の "Advanced Design Patterns for DynamoDB" 詳細セッションでこれを解説しました。しかし適応キャパシティは時間を稼ぐのであって、免疫ではありません。単一のホットな 項目、単調増加するソートキー、あるいは LSI は、依然として 1 つのキーを単一のパーティションに制限します。分散を前提に設計し、安全網に寄りかからないでください。

カーディナリティの高いキーを選ぶ

対処法は カーディナリティ — 異なるキー値の数と、トラフィックがそれらをどれだけ均等に叩くか、です。

  • 低いカーディナリティregionstatustrue/false): パーティションが少なく、トラフィックが集中し、早くスロットルします。
  • 高いカーディナリティdeviceIduserId、注文 ID): 多くの値が多くのパーティションにハッシュされ、負荷が分散し、余裕が育ちます。

SQL から来ると status 列をインデックスしてそれでフィルタするのは喜んでやるでしょう。DynamoDB の パーティション キーとしてはそれは罠です — 分散できないのです。カーディナリティの低い属性はフィルタとして、あるいはセカンダリインデックスのソートキーとして保ち、配置を決めるものにしては決していけません。

生来良いキーでもなお偏るとき — 一握りの巨大テナントが残りを上回るとき — サフィックスを追加 して、1 つの論理値を N 個のパーティションに扇状に広げます。例えばシャーディングされた書き込み経路には tenantId#3 です。読み取り時に再集約します。

キーが分散したら、パーティション の項目を狙うために、ソートキーへの KeyConditionExpression を書きます。コードに組み込む前に、自分自身のスキーマに対して DynamoDB 式ビルダーで 1 つ組み立てられます。

deviceId = "vac-7741" AND readingTs BETWEEN "2026-06-01" AND "2026-06-30"

これは 1 台のデバイスの 6 月ウィンドウを単一のパーティションから読みます — Scan ではなく Query です。パーティションキーがマシンを固定し、ソートキーの条件が行を絞り込みます。

落とし穴と次のステップ

  • SQL でよく読めるものでキーを選ばない。 分散するもの で選びます。カーディナリティが第一、クエリの便利さは二の次。
  • テーブルの総キャパシティがキーごとに自分のものだと思い込まない。 スループットはパーティション単位です。1 つのホットな値が、テーブルが遊んで見えるのにスロットルしえます。
  • 分割と戦わない。 それは自動でハッシュ駆動です — あなたの仕事は、分散するのに十分な数の異なるキーを与えることです。

キーがきれいに分散したら、次の判断はパーティション内で項目をどうレイアウトするか — シングルテーブル設計を参照 — と、セカンダリインデックスが 2 つ目のアクセスパターンに正しいツールとなるのはいつか、です。

DynoTable をダウンロードし、SQL Workbench でパーティションキーに対して GROUP BY を実行して、どのキーがホットパーティションになる前に項目を積み上げているかを見てください。

更新日