メインコンテンツまでスキップ

DynamoDB

概要

MBC CQRS ServerlessはDynamoDBをプライマリデータストアとして使用し、構造化されたテーブル設計を通じてCQRSとイベントソーシングパターンを実装しています。効率的なアプリケーションを構築するには、テーブル構造を理解することが重要です。

テーブルアーキテクチャ

MBC CQRS Serverlessでは、DynamoDBテーブルは以下のタイプに整理されています:

エンティティテーブル

テーブルタイプ命名規則用途
コマンドテーブルentity-command書き込みコマンドを保存(書き込みモデル)
データテーブルentity-data現在の状態を保存(読み取りモデル)
履歴テーブルentity-historyイベントソーシング用にすべてのバージョンを保存

システムテーブル

テーブル用途
tasks長時間実行される非同期タスクの情報を保存
sequencesID生成用のシーケンスデータを保持

テーブル定義

テーブル定義はprisma/dynamodbsフォルダに保存されています。新しいエンティティテーブルを追加するには:

ステップ1: 設定でテーブルを定義

prisma/dynamodbs/cqrs.jsonにテーブル名を追加:

["cat", "dog", "order"]

ステップ2: マイグレーションを実行

ローカル開発用:

# Migrate DynamoDB tables only
npm run migrate:ddb

# Migrate both DynamoDB and RDS
npm run migrate

キー設計パターン

標準キー構造

すべてのテーブルは以下で構成される複合主キーを使用します:

キー形式
pkTYPE#tenantCodeORDER#ACME
skTYPE#codeORDER#ORD-000001

エンティティキーの例

// Order entity
const orderKey = {
pk: `ORDER#${tenantCode}`,
sk: `ORDER#${orderId}`,
};

// User entity
const userKey = {
pk: `USER#${tenantCode}`,
sk: `USER#${userId}`,
};

// Hierarchical data (e.g., organization)
const departmentKey = {
pk: `ORG#${tenantCode}`,
sk: `DEPT#${parentId}#${deptId}`,
};

テーブル属性

共通属性

すべてのエンティティテーブルはこれらの共通属性を共有します:

属性説明
pkStringパーティションキー
skStringソートキー
idString一意識別子(pk#skハッシュ)
codeStringビジネスコード
nameString表示名
tenantCodeStringテナント識別子
typeStringエンティティタイプ
versionNumber楽観的ロック用バージョン
attributesMapカスタムエンティティ属性
createdByString作成者ユーザーID
createdIpString作成者IPアドレス
createdAtString作成タイムスタンプ(ISO 8601)
updatedByString最終更新者ユーザーID
updatedIpString最終更新者IPアドレス
updatedAtString最終更新タイムスタンプ(ISO 8601)

コマンド固有の属性

属性説明
sourceStringコマンドソース識別子
requestIdStringリクエストトラッキングID

履歴固有の属性

属性説明
seqNumber履歴内のシーケンス番号

セカンダリインデックス

グローバルセカンダリインデックスの追加

デフォルトのテーブル設定にはGSIが含まれていません。クエリパターンに基づいてGSIを追加できます。一般的なパターンとして、ビジネスコードによる高速検索のためのcode-indexを追加する方法があります:

GSI定義の例(テーブル設定に追加):

{
"GlobalSecondaryIndexes": [
{
"IndexName": "code-index",
"KeySchema": [
{ "AttributeName": "tenantCode", "KeyType": "HASH" },
{ "AttributeName": "code", "KeyType": "RANGE" }
],
"Projection": { "ProjectionType": "ALL" }
}
]
}

カスタムGSIの使用例:

// Find entity by code (requires code-index GSI)
const params = {
TableName: 'entity-data',
IndexName: 'code-index',
KeyConditionExpression: 'tenantCode = :tenant AND code = :code',
ExpressionAttributeValues: {
':tenant': tenantCode,
':code': entityCode,
},
};

ベストプラクティス

キー設計

  1. パーティションキーを広く保つ: パーティション間でデータを均等に分散する
  2. 階層的なソートキーを使用する: 効率的な範囲クエリを有効にする
  3. パーティションキーにテナントを含める: データ分離を確保する

クエリ最適化

  1. ScanよりQueryを使用する: クエリでは常にパーティションキーを使用する
  2. 結果セットを制限する: 大規模データセットにはページネーションを使用する
  3. 必要な属性を射影する: 必要なフィールドのみを取得する

キャパシティプランニング

  1. オンデマンドキャパシティを使用する: 予測不可能なワークロードに推奨
  2. 消費キャパシティを監視する: CloudWatchアラームを設定する
  3. DAXを検討する: マイクロ秒レベルのレイテンシが必要な読み取り負荷の高いワークロード向け

ローカル開発

DynamoDB Local

フレームワークには開発用のDynamoDB Localが含まれています:

# Start DynamoDB Local (included in docker-compose)
docker-compose up -d dynamodb-local

# Access DynamoDB Local Admin UI
open http://localhost:8001

環境変数

# Local DynamoDB endpoint
DYNAMODB_ENDPOINT=http://localhost:8000
DYNAMODB_REGION=ap-northeast-1

関連ドキュメント