

# DynamoDB でパーティションキーを効率的に設計し、使用するためのベストプラクティス。
<a name="bp-partition-key-design"></a>

Amazon DynamoDB テーブルの各項目を一意に識別する主キーは、シンプル (パーティションキーのみ)、または複合 (パーティションキーとソートキーの組み合わせ) で構成できます。

テーブルとそのセカンダリインデックスのすべてのパーティションキーにわたって、アクティビティが均一であるアプリケーションを設計する必要があります。アプリケーションが必要とするアクセスパターンと、各テーブルとセカンダリインデックスが必要とする読み込みユニットと書き込みユニットを決定することができます。

**注記**  
アダプティブキャパシティは、オンデマンドモードとプロビジョンドキャパシティに適用されます。

DynamoDB テーブル内のすべてのパーティションは、1 秒あたり 3,000 の読み取りユニットと 1 秒あたり 1,000 の書き込みユニットを最大キャパシティとして提供するように設計されています。1 つの読み取りユニットは、最大サイズが 4 KB の項目に対する、1 秒あたり 1 回の強力な整合性のある読み込み、または 1 秒あたり 2 回の結果整合性のある読み込みを表します。1 つの書き込みユニットは、最大サイズが 1 KB の項目に対する、1 秒あたり 1 回の書き込みオペレーションを表します。

テーブルのパーティションスループット制限を評価するときは、項目のサイズを考慮する必要があります。例えば、テーブルの項目サイズが 20 KB である場合、1 回の整合性のある読み取りオペレーションでは 5 つの読み取りユニットを消費します。つまり、パーティションの制限に達する前に、その 1 つの項目に対して 1 秒あたり 600 回の整合性のある読み取りオペレーションを同時に実行できます。テーブル内のすべてのパーティションの合計スループットは、プロビジョンドモードでプロビジョニングされたスループット、またはオンデマンドモードのテーブルレベルのスループット制限によって制約される場合があります。詳細については、「[Service Quotas](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ServiceQuotas.html)」を参照してください。

**Topics**
+ [パーティションキーを設計してワークロードを DynamoDB で分散する](bp-partition-key-uniform-load.md)
+ [書き込みシャーディングを使用して DynamoDB テーブルでワークロードを均等に分散させる](bp-partition-key-sharding.md)
+ [DynamoDB でデータアップロード中の書き込みアクティビティを効率的に分散させる](bp-partition-key-data-upload.md)

# パーティションキーを設計してワークロードを DynamoDB で分散する
<a name="bp-partition-key-uniform-load"></a>

テーブルの主キーのパーティションキー部分は、テーブルのデータが格納されている論理パーティションを決定します。これにより、基本的な物理パーティションに影響を及ぼします。I/O リクエストを効率的に分散しないパーティションキー設計では、「ホット」パーティションが作成される場合があります。これにより、スロットリングが発生することや、プロビジョニングされた I/O 容量が効率的に使用されないことがあります。

テーブルのプロビジョニングされたスループットの最適な使用は、個々の項目のワークロードパターンだけでなく、パーティションキー設計にも左右されます。この操作によって、スループットレベルを達成するためにすべてのパーティションキーバリューにアクセスしたり、アクセスされるパーティションキーバリューの割合を高くしたりする必要があるわけではありません。これは、ワークロードがアクセスするパーティションキーバリューが大きくなるほど、リクエストが分割された空間に分散されることを意味します。一般的に、パーティションキー値の総数に対するアクセスされたパーティションキー値の比率が高くなるほど、プロビジョンドスループットの使用がより効率的になります。

一般的なパーティションキースキーマのプロビジョニングされたスループット効率の比較を次に示します。


****  

| パーティションキーバリュー | 均一性 | 
| --- | --- | 
| ユーザー ID (アプリケーションに多くのユーザーが存在する場合) | 良好 | 
| ステータスコード (可能性のあるステータスコードが少しだけある場合) | 不良 | 
| 項目の作成日。直近の期間 (日、時、分など) に切り上げられます。 | 不良 | 
| デバイス ID (各デバイスが比較的類似した間隔でデータにアクセスする場合)。 | 良好 | 
| デバイス ID (追跡中のデバイスが多数あり、そのうちの 1 つのデバイスが他のすべてのデバイスよりも頻繁に使用される場合) | 不良 | 

単一のテーブル内にあるパーティションキーバリューの数が少ない場合は、より明確に区別できるパーティションキーバリュー全体を対象として、書き込みオペレーションを分散することを検討してください。つまり、「ホット」パーティションキーバリュー (何度もリクエストされるパーティションキーバリュー) が原因で全体のパフォーマンス速度が低下する場合があるので、このようなパーティションキーバリューを回避するようにプライマリキー要素を構築してください。

例えば、複合プライマリキーを持つテーブルがあるとします。パーティションキーは項目の作成日を表します (直近の日付に切り上げられます)。ソートキーは項目の識別子を表します。特定の日付 (`2014-07-09` など) で、**すべて**の新しい項目が 1 つのパーティションキーバリュー (およびその物理パーティション) として書き込まれます。

テーブル全体が単一のパーティションに収まり (時間の経過に伴うデータの増加を考慮)、アプリケーションで必要となる読み込みスループットと書き込みスループットが単一のパーティションにおける読み込みと書き込みの容量を超過しない場合は、パーティション分割をしても、アプリケーションが予想外のスロットリングを受けることはありません。

NoSQL Workbench for DynamoDB を使用してパーティションキー設計を視覚化する方法については、「[NoSQL Workbench を使用したデータモデルの構築](workbench.Modeler.md)」を参照してください。

# 書き込みシャーディングを使用して DynamoDB テーブルでワークロードを均等に分散させる
<a name="bp-partition-key-sharding"></a>

Amazon DynamoDB のパーティションキースペースで効率的な書き込みの分散を行う方法として、スペースの拡張があります。これにはさまざまな方法があります。パーティションキーバリューに乱数を追加して、パーティション間で項目を分散させることができます。または、クエリ対象に基づいて計算された数値を使用することができます。

## ランダムなサフィックスを使用したシャーディング
<a name="bp-partition-key-sharding-random"></a>

パーティションキースペース全体に均等にロードを分散するための方法として、パーティションキーバリューの最後に乱数を追加する方法があります。次に、より大きなスペース全体の書き込みをランダム化します。

例えば、今日の日付を表すパーティションキーの場合は、`1` と `200` の間の乱数を選択し、それをサフィックスとして日付に連結することができます。これにより、`2014-07-09.1` や `2014-07-09.2` などのパーティションキーバリューが生成されます。この場合、最大のパーティションキーバリューは `2014-07-09.200` になります。パーティションキーをランダム化しているため、毎日のテーブルへの書き込みは複数のパーティション間で均等に分散されます。これにより、並列性が強化され、全体的なスループットが向上します。

ただし、特定の日のすべての項目を読み込むには、すべてのサフィックスの項目をクエリしてから結果をマージする必要があります。例えば、最初にパーティションキーバリュー `Query` に対して `2014-07-09.1` リクエストを発行します。次に `Query` に対して別の `2014-07-09.2` を発行します。この処理を `2014-07-09.200` まで繰り返します。最終的には、アプリケーションですべての `Query` リクエストの結果をマージする必要があります。

## 計算されたサフィックスを使用したシャーディング
<a name="bp-partition-key-sharding-calculated"></a>

ランダム化の方法は、書き込みスループットを大幅に向上させることができます。ただし、項目を書き込むときに使用されたサフィックスの値がわからないため、特定の項目を読み込むのは困難です。別の方法を使用して個々の項目の読み込みを容易にすることができます。パーティション間で項目を分散させるには、乱数を使用せずに、クエリする項目に基づいて計算できる数値を使用します。

前の例では、パーティションキーで今日の日付が使用されています。各項目にはアクセス可能な `OrderId` 属性があり、日付だけでなく、順序 ID を使用して、項目を最も頻繁に見つける必要があるとします。アプリケーションから項目をテーブルに書き込む前に、この順序 ID に基づいてハッシュサフィックスを計算し、その値をパーティションキーの日付に追加します。この計算では、1 から 200 までの数値が生成され、ランダムな方法と同様に、完全に均一に分散されます。

この計算はシンプルな計算で十分です (順序 ID の文字の UTF-8 コードポイント値を乗算して、それを 200 で割った余りに \$1 1 するなど)。パーティションキーバリューは、日付に計算結果を連結した値になります。

この方法を使用すると、書き込みがパーティションキーバリュー全体に均一に分散されます。したがって、物理パーティション全体にも均一に分散されます。これで、特定の `GetItem` 値のパーティションキーバリューを計算できるため、`OrderId` オペレーションを実行して、特定の項目や日付を簡単に読み込むことができます。

特定の日のすべての項目を読み込むには、`2014-07-09.N` キー (ここで `N` は 1 〜 200) を`Query`する必要があり、アプリケーションはすべての結果をマージする必要があります。この方法には、すべてのワークロードを利用する単一の「ホット」パーティションキーバリューを使用しないというメリットがあります。

**注記**  
大容量の時系列データを処理するために特別に設計されている効率的な方法については、「[時系列データ](bp-time-series.md)」を参照してください。

# DynamoDB でデータアップロード中の書き込みアクティビティを効率的に分散させる
<a name="bp-partition-key-data-upload"></a>

通常、他のデータソースからデータをロードする場合、Amazon DynamoDB がテーブルデータを複数のサーバーでパーティション化します。割り当てられたすべてのサーバーに同時にデータをアップロードするとパフォーマンスが向上します。

例えば、パーティションキーとして `UserID` とソートキーとして `MessageID` を含む複合プライマリキーを使用する DynamoDB テーブルにユーザーメッセージをアップロードするとします。

データをアップロードする場合、1 つのアプローチとして、ユーザーごとにすべてのメッセージ項目を別々にアップロードできます。


****  

| UserId | MessageID | 
| --- | --- | 
| U1 | 1 | 
| U1 | 2 | 
| U1 | ... | 
| U1 | ... 最大 100 | 
| U2 | 1 | 
| U2 | 2 | 
| U2 | ... | 
| U2 | ... 最大 200 | 

この場合の問題は、パーティションキーバリュー全体で DynamoDB への書き込みリクエストを分散していないことです。一度に 1 つのパーティションキーバリューを取得し、そのすべての項目をアップロードした後に、次のパーティションキーバリューに移動して同じ処理が行われます。

その裏では、DynamoDB がテーブル内のデータを複数のサーバーでパーティション化しています。テーブルにプロビジョニングされたすべてのスループットキャパシティを完全に使用するには、ワークロードをパーティションキーバリューに分散する必要があります。同じパーティションキーバリューを持つ項目に対して不均等な量のアップロード作業を指示すると、DynamoDB がテーブル用にプロビジョニングしたすべてのリソースを完全に使用することはできません。

アップロード作業を分散するには、ソートキーを使用して各パーティションキーバリューから 1 つの項目をロードし、次に各パーティションキーバリューから別の項目をロードします。


****  

| UserId | MessageID | 
| --- | --- | 
| U1 | 1 | 
| U2 | 1 | 
| U3 | 1 | 
| ... | ... | 
| U1 | 2 | 
| U2 | 2 | 
| U3 | 2 | 
| ... | ... | 

このシーケンスの各アップロードでは、それぞれ異なるパーティションキーバリューが使用されるので、多くの DynamoDB サーバーが同時にビジー状態になり、スループットパフォーマンスが向上します。