

# DynamoDB のデータモデリングの基盤
<a name="data-modeling-foundations"></a>

このセクションでは、基盤レイヤーについて、シングルテーブルとマルチテーブルという 2 種類のテーブル設計を検討します。

![\[データ、データ下のブロック、ブロック下の基盤の概念的な相互関係を示す画像。基盤を重視します。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SchemaDesignFoundation.png)


## シングルテーブル設計の基盤
<a name="data-modeling-foundations-single"></a>

DynamoDB スキーマの基盤の 1 つとして、**シングルテーブル設計**を選択できます。シングルテーブル設計とは、複数のタイプ (エンティティ) のデータを単一の DynamoDB テーブルに保存できるパターンです。複数のテーブルやテーブル間の複雑な関係を維持する必要をなくすことで、データアクセスパターンを最適化し、パフォーマンスを向上させ、コストを削減することを目的としています。これが可能なのは、DynamoDB は、同じパーティションキーを持つ項目 (項目コレクションと呼ばれます) をいずれも同じパーティションに保存するためです。この設計では、異なる種類のデータが同じテーブル内に項目として保存され、各項目は一意のソートキーで識別されます。

![\[テーブルに保存した、同じ UserId の項目コレクション内で、エンティティタイプ別に各項目を区別するためにソートキーを使用する方法を示す画像。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/SingleTableSchema.png)


**利点**:
+ データの局所性により、1 回のデータベース呼び出しで複数のエンティティタイプのクエリをサポートします。
+ 読み取りにかかる全体的な財務コストとレイテンシーコストを削減します。
  + 合計 4 KB 未満の 2 つの項目に対する単一のクエリは、結果整合性のある 0.5 RCU になります。
  + 合計 4 KB 未満の 2 つの項目に対する 2 つのクエリは、結果整合性のある 1 RCU になります (それぞれ 0.5 RCU)。
  + 2 つの別々のデータベース呼び出しを返すまでの時間は、1 回の呼び出しよりも平均して長くなります。
+ 管理するテーブルの数が減ります。
  + アクセス許可を複数の IAM ロールやポリシーにわたって管理する必要はありません。
  + テーブルの容量管理はすべてのエンティティにわたって平均化され、通常は消費パターンがより予測可能になります。
  + モニタリングに必要なアラームの数が減ります。
  + カスタマーマネージド暗号化キーは、1 つのテーブルでローテーションするだけで済みます
+ テーブルへのトラフィックをスムーズにします。
  + 複数の使用パターンを同じテーブルに集約することで、全体的な使用がよりスムーズになる傾向があり (株価指数のパフォーマンスが個々の株式よりもスムーズになる傾向があるように)、プロビジョニングモードテーブルでより高い使用率を達成するのに適しています。

**欠点**:
+ リレーショナルデータベースと比べて逆説的な設計であるため、ラーニングカーブが急になる場合があります。
+ データ要件はすべてのエンティティタイプにわたって一貫している必要があります。
  + バックアップは全部かゼロかのどちらかであるため、ミッションクリティカルでないデータは、別のテーブルに保存することを検討してください。
  + テーブルの暗号化はすべての項目間で共有されます。テナントごとに暗号化要件が異なるマルチテナントアプリケーションでは、クライアント側の暗号化が必要になります
  + 履歴データと運用データが混在するテーブルでは、低頻度アクセスストレージクラスを有効にしてもあまりメリットがありません。詳細については、[DynamoDB テーブルクラス](HowItWorks.TableClasses.md)を参照してください。
+ エンティティのサブセットのみを処理する必要がある場合でも、すべての変更されたデータは DynamoDB Streams に伝播されます。
  + Lambda を使用する場合は、Lambda イベントフィルターのおかげで請求額に影響しませんが、Kinesis Consumer Libary を使用する場合は、追加費用が発生します。
+ GraphQL を使用する場合、シングルテーブル設計の実装はより難しくなります。
+ Java の [`DynamoDBMapper`](DynamoDBMapper.md) や [Enhanced Client](DynamoDBEnhanced.md) などの上位レベルの SDK クライアントを使用する場合、同じ応答内の項目が異なるクラスに関連付けられる可能性があるため、結果の処理が難しくなりがちです。

**どのようなときに使うか**

単一テーブル設計は、複数のエンティティタイプを一緒に頻繁にクエリするアプリケーションや、異なるデータ型間の関係を維持する必要があるアプリケーションに適しています。これは、アクセスパターンがデータの局所性の恩恵を受ける場合や、複数のテーブルを管理するオーバーヘッドを最小限に抑えたい場合に特に効果的です。

## マルチテーブル設計の基盤
<a name="data-modeling-foundations-multi"></a>

DynamoDB スキーマの別の基盤として、マルチテーブル設計を選択できます****。マルチテーブル設計は、DynamoDB のテーブルごとに 1 つのタイプ (エンティティ) のデータを保存する従来のデータベース設計に近いパターンです。各テーブル内のデータは引き続きパーティションキー別に整理されるため、単一のエンティティタイプ内のパフォーマンスとスケーラビリティは最適化されますが、複数のテーブルにわたるクエリは個別に実行する必要があります。

![\[フォーラムのリストといくつかの集計データを含むフォーラムテーブルを示す画像。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/MultipleTable1.png)


![\[所属する特定のフォーラムごとに分割されたスレッドのリストを含むスレッドテーブルを示す画像。\]](http://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/images/DataModeling/MultipleTable2.png)


**利点**:
+ シングルテーブル設計に慣れていないユーザーでも簡単に設計できます。
+ 各リゾルバーが単一のエンティティ (テーブル) にマッピングされるため、GraphQL リゾルバーの実装が容易になります。
+ エンティティタイプ別に異なるデータ要件が許容されます。
  + ミッションクリティカルな個々のテーブルのバックアップを作成できます 
  + テーブル暗号化はテーブルごとに管理できます。テナントごとに暗号化要件が異なるマルチテナントアプリケーションでは、個別のテナントテーブルにより、お客様ごとに独自の暗号化キーを使用できます。
  + 低頻度アクセスストレージクラスは、履歴データを含むテーブルでのみ有効にして、コスト削減のメリットを最大限に実現できます。詳細については、[DynamoDB テーブルクラス](HowItWorks.TableClasses.md)を参照してください。
+ 各テーブルには独自の変更データストリームがあり、単一のモノリシックプロセッサではなく、項目の種類ごとに専用の Lambda 関数を設計できます。

**欠点**:
+ 複数のテーブルにわたるデータを必要とするアクセスパターンの場合は、DynamoDB からの複数回の読み取りが必要になり、クライアントコードでのデータの処理/結合が必要になることがあります。
+ 複数のテーブルの操作とモニタリングには、より多くの CloudWatch アラームが必要であり、各テーブルを個別にスケールする必要があります
+ 各テーブルのアクセス許可を個別に管理する必要があります。今後テーブルを追加する場合は、必要な IAM ロールやポリシーの変更が必要になります。

**どのようなときに使うか**

アプリケーションのアクセスパターンで複数のエンティティやテーブルをまとめてクエリする必要がない場合は、マルチテーブル設計が適切かつ十分なアプローチです。