🗄️

Amazon DynamoDBの設計の前に知っておきたかった基礎知識

2024/06/19に公開

最近、お仕事でIoTなシステムの構築をしていたのですが、そこでDynamoDBを用いたデータの永続化を設計する機会がありました。
これまでも利用はしていたのですが、RDBでは持ちづらいから、Lambdaでアクセスするから、などといった消去法的な採用が多く、今回改めてインプットしておこうと思い立ちました。
本投稿では、現時点(2024年6月)でのDynamoDBの基本的な概念や設計のポイント、運用にあたっての注意点などをまとめます。

Amazon DynamoDBとは

AWSが提供するNoSQLデータベースです。CAP定理のAPを重視したシンプルなデータベースとなっています。
DynamoDBは、もともとRDBの性能不良に起因した2004年のシステム障害を受けて、Amazonでのユースケースに合わせて開発されたもの[1]です。複雑なクエリやトランザクションなどの機能を落として、その代わりにRDBよりも高いスケーラビリティを達成しています。

  • スキーマレスなキーバリューストア
    • プライマリキー以外のキーは全て任意
  • 永続ストレージ
    • ElastiCacheのように揮発せずに残り続ける
  • サーバーレス、水平方向スケール
    • パーティションキーによってデータは分散される
    • キャパシティに応じて内部的にスケールする

DynamoDBのデータ構造

DynamoDBのデータは3つのコンポーネントで構成されます。

  • テーブル(Table) ... データのコレクション
    • 例: ソーシャルゲームのユーザーデータ
  • 項目(Item) ... テーブル内のひとまとまりのデータで、プライマリキーで識別する
    • 例: ユーザーAの情報、ユーザーBの情報
    • 最大400KB
  • 属性(Attribute) ... 項目内のプリミティブなデータで、型を持つ単一の値
    • 例: ユーザーAの所持ポイント、ユーザーBが持っているアイテムリスト
    • ネストされた属性では最大32レベルまでの入れ子が可能

データ型

DynamoDBのデータ型は以下です[2]。日時や空間データなどの用途に対応したデータ型はありません。

  • スカラー型
    • 数値(N) ... 最大38桁
    • 文字列(S) ... UTF-8、最大400KB、インデックスとして使わない場合は最小0B
      • PKとして使う場合は、最大1024B
    • バイナリ(B)
      • PKとして使う場合は、最大1024B
      • DynamoDBとのやりとりは、Base64でエンコードする必要がある
    • ブール(BOOL)
    • null(NULL)
  • ドキュメント型 ... 入れ子の属性を持つ、最大32レベル
    • リスト(L) ... ["Cookies", "Coffee", 3.14159]
    • マップ(M) ... {Day: "Monday", UnreadEmails: 42}
  • セット型 ... 複数のスカラー値を持つ、セット内の要素は全て同じ型
    • 文字セット(SS) ... ["Black", "Green", "Red"]
    • 数値セット(NS)
    • バイナリセット(BS)

キーの命名規則

キーの命名規則は以下のとおりです[2:1]。特筆すべきところはないです。

  • エンコードは、UTF-8
  • テーブルとインデックスは、3~255文字で、a-zA-Z0-9_-.のみ使える
  • 属性名は、1文字以上、64KB未満
  • #: は予約語なので使えない

プライマリキー

テーブルごとにプライマリキーを設定が必須です。テーブル作成時にプライマリキーとして用いる属性を指定します。
プライマリキーは2通りの設定方法があります。

  • パーティションキーのみ
    • 例: ユーザーID
  • パーティションキー + ソートキー
    • 例: ユーザーID + タイムスタンプ

注意点として、以前は、パーティションキーはハッシュキー、ソートキーはレンジキーとそれぞれ呼ばれていました。後述するAPIにもその名残がありますが、適宜読み替える必要があります。

パーティション

DynamoDBは複数のストレージサーバーにデータが分散して格納されています。項目ごとの物理的な格納場所(パーティション)は、パーティションキーから得られるハッシュ値によって決められます。パーティションごとに提供できるキャパシティに上限がある(1000WCU、3000RCU)[3]ため、特定のパーティションにアクセスが集中しないようにパーティションキーを設計する必要があります。内部ではソートキーも用いて分散されるモードもあるそうですが、ユーザーからコントロールできないので、それ前提で設計するのは危険です。

パーティション内ではソートキーの順番で格納されます。後述するクエリでの範囲アクセスなどに利用されるので、こちらも慎重に設計する必要があります。

TTL

有効期限タイムスタンプを定義することで、項目が不要になる日時を示すことができます[4]。後述しますが、DynamoDBにはストレージ容量に応じたコストがかかるので、ログなど一方的に増えるデータには有効にしておきましょう。

  • テーブルでTTL属性を決めて有効化する
    • aws dynamodb update-time-to-live --table-name User --time-to-live-specification "Enabled=true, AttributeName=ttl"
  • 項目ごとにTTL属性を付与する(付与されていない項目は削除されない)
    • タイムスタンプはUnix time(秒単位)
  • DynamoDBでは有効期限が切れた項目を数日以内に自動的に削除する
    • 書き込みスループットは消費しない
EXP=`date -d '+7 days' +%s`
aws  dynamodb put-item --table-name Todo --item '{"id": {"N": "1"}, "ttl": {"N": "'$EXP'"}}'

セカンダリインデックス

テーブルのプライマリキー以外に、(パーティションキーやソートキーに相当する)インデックスを作成する仕組みとして、GSIとLSIの2つの方法があります。

グローバルセカンダリインデックス(GSI)

プライマリキーとは異なるパーティションキーとソートキーで作成されるインデックスです。
元のテーブルとは別にGSI用のテーブルが作られて、元のテーブルの更新がGSIにもコピーされる、という仕組みになっています。

  • 元テーブルに項目を追加・削除すると、そのテーブルに紐づく全てのGSIが結果整合性モデルを使用して非同期に更新される
    • ほぼ瞬時だが、不整合が発生する時間帯が生まれる
  • 読み込み・書き込みのキャパシティユニットを、元テーブルとは別にセットする必要がある
    • 同期のため、書き込みキャパシティユニットをセットする必要がある(スロットリングを避けるために元テーブルと同じにするのが望ましい)
  • 1テーブルに20個まで作成可能
  • 読み込みでは、結果整合性のみをサポート
  • 射影された属性のみをリクエストできる

ローカルセカンダリインデックス(LSI)

パーティションキーは元テーブルと同じで、ソートキーだけ異なるインデックスです。GSIと異なりパーティションのデータの物理的な実体は1つで、LSIはそれらへのリンクとなっています。RDBのインデックスに近いイメージを持つと良さそうです。

  • 1テーブルに5個まで
  • 特定のパーティションキーに紐づく項目の合計サイズが最大10GB
  • テーブル作成時にのみ定義可能
  • 読み込みでは、結果整合性・強い整合性をサポート
  • ベーステーブルのキャパシティユニットが消費される
  • インデックスに射影されていない属性を取得できる(ベーステーブルから取ってきてくれる)

DynamoDBのAPI

よくあるToDoの情報を持つテーブルを例に、APIの使い方をまとめます。

ローカルでDynamoDBを動かしたい場合、Docker環境ではamazon/dynamodb-localが利用できます。以下の記事も参考にしてみてください。

https://qiita.com/to-fmak/items/3a6df367196ed216b1a4

テーブル作成

テーブルの作成時には、テーブル名、プライマリキー、キャパシティユニットを指定します。UserIdがパーティションキー、CreatedAtがソートキーとなっています。

aws dynamodb create-table \
  --table-name Todo \
  --attribute-definitions \
    AttributeName=UserId,AttributeType=N \
    AttributeName=CreatedAt,AttributeType=S \
  --key-schema \
    AttributeName=UserId,KeyType=HASH \
    AttributeName=CreatedAt,KeyType=RANGE \
  --provisioned-throughput \
    ReadCapacityUnits=10,WriteCapacityUnits=5

書き込み

テーブルに設定されたプライマリキーを全て指定して、項目の作成・更新・削除を行います。200(OK)を受信したら、これは正常に完了して永続的に保持されたことを意味します。

  • PutItem ... 項目の新規作成(すでに項目が存在する場合は、置き換えられる)
    • aws dynamodb put-item --table-name Todo --item '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"},"Subject":{"S":"first todo item."},"Done":{"BOOL":false}}'
    • 属性が数値型(N)であったとしても、値はダブルクオーテーションで囲む必要があります
  • UpdateItem ... 既存の項目の属性の更新(項目が無ければ、新規作成)
    • aws dynamodb update-item --table-name Todo --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}' --update-expression "SET Done = :done" --expression-attribute-values '{":done":{"BOOL":true}}'
    • 上の操作で、PutItemで作った項目のDone属性がtrueに更新されます
  • DeleteItem ... 項目の削除
    • aws dynamodb delete-item --table-name Todo --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}'
  • BatchWriteItem ... 最大25個の項目を一括で書き込む
    • 全てのリクエストに失敗しない限り、失敗扱いにならないので注意
    • aws dynamodb batch-write-item --request-items '{"Todo":[{"PutRequest":{"Item":{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}}},{"PutRequest":{"Item":{"UserId":{"N":"2"},"CreatedAt":{"S":"2024-06-05T09:16:35"}}}}]}'

アトミックカウンタ

値のインクリメントを1つのupdate-itemで実現できます。

# 予めインクリメントする属性をセットしておく必要がある
aws dynamodb update-item \
  --table-name Todo \
  --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}' \
  --update-expression "SET NumViews = :numViews" --expression-attribute-values '{":numViews":{"N":"0"}}'

aws dynamodb update-item \
  --table-name Todo \
  --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}' \
  --update-expression "SET NumViews = NumViews + :incr" \
  --expression-attribute-values '{":incr":{"N":"1"}}' \
  --return-values UPDATED_NEW
# {
#     "Attributes": {
#         "NumViews": {
#             "N": "1"
#         }
#     }
# }

条件付き書き込み

デフォルトでは無条件での上書きだが、—-condition-expressionで条件付けできる。

  • 条件がfalseになっても、書き込みキャパシティは消費される
  • 例: 同じプライマリキーを持つ既存の項目がない場合のみ、PutItemを成功させる
  • 例: 値が一致する場合のみ、UpdateItemを成功させる
aws dynamodb update-item \
  --table-name Todo \
  --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}' \
  --update-expression "SET DoneAt = :doneAt" \
  --condition-expression "Done = :done" \
  --expression-attribute-values '{":doneAt":{"S":"2024-06-07T11:21:41"},":done":{"BOOL":true}}'

読み取り

GetItemとBatchGetItem

プライマリキーを指定して、項目の読み取りを行います。

  • 全ての属性を返すので、プロジェクション式で絞る
  • 整合性レベルの指定 (—consistent-read | —no-consistent-read)もできます
  • BatchGetItemでは最大100個の項目を一括で読み取ることができます
aws dynamodb get-item \
  --table-name Todo \
  --key '{"UserId":{"N":"1"},"CreatedAt":{"S":"2024-06-05T09:16:34"}}' \
  --projection-expression "UserId, CreatedAt, Done"
# {
#     "Item": {
#         "Done": {
#             "BOOL": true
#         },
#         "UserId": {
#             "N": "1"
#         },
#         "CreatedAt": {
#             "S": "2024-06-05T09:16:34"
#         }
#     }
# }

整合性

DynamoDBでは、2種類の読み取り整合性をサポートしています。

  • 結果整合性のある読み込み(デフォルト)
    • GSIとストリームからの読み取りは、こちらのみサポート
    • 最近完了した書き込みオペレーションの結果が、レスポンスに反映されないことがある
  • 強力な整合性のある読み込み
    • テーブルとLSIのみがサポート
    • 成功した以前の全ての書き込みオペレーションからの更新を反映して、最新データを返す

マルチリージョンのレプリケーション (グローバルテーブル) は、通常1秒以内にレプリケーションされる。

クエリ

プライマリキーまたはセカンダリインデックスの値に基づいて項目を検索・取得します。

以下のクエリでは、UserIdが1かつCreatedAtが2024-06-01以降で、さらにSubjectに"first"を含む項目を取得しています。
パーティションキーは必須で、かつ、等価条件のみですが、ソートキーについてはいくつかの条件式を使うこともできます。

aws dynamodb query \
  --table-name Todo \
  --key-condition-expression "UserId = :userId and CreatedAt >= :createdAt" \
  --filter-expression "contains(Subject, :keyword)" \
  --expression-attribute-values '{":userId":{"N":"1"},":createdAt":{"S":"2024-06-01T00:00:00"},":keyword":{"S":"first"}}'

--key-condition-expressionで、プライマリキー・セカンダリインデックスの値を指定します。

--filter-expression(フィルタ式)では、クエリの結果から更にプライマリキー・セカンダリインデックス以外の項目で絞り込むことができます。
消費する読み込みキャパシティはフィルタ式の適用前の項目サイズによって決まります。フィルタ式で絞り込んだからといって、必要な読み取りキャパシティが減るわけではない点に注意です。

スキャン

テーブルまたはセカンダリインデックスの全ての項目を取得するAPIで、クエリと違い、プライマリーキーやセカンダリインデックスを用いずに、全ての属性を使って検索できます。
こちらもフィルタ式による絞り込みが行えますが、消費する読み取りキャパシティはテーブルやセカンダリインデックスが持つ全ての項目を取得したものとして計算されます。

aws dynamodb scan \
  --table-name Todo \
  --filter-expression "Subject = :subject" \
  --expression-attribute-values '{":subject":{"S":"first todo item."}}'

キャパシティ

DynamoDBではテーブルやGSIの単位で、読み書きで許容するキャパシティを設定できます。

ユニット

DynamoDBで読み書きを行うと、項目のサイズとトランザクション/整合性レベルに応じたキャパシティが消費されます。このキャパシティの単位がユニットで、書き込みの場合はWCU、読み取りの場合はRCUと呼びます。

  • 書き込みリクエスト
    • 1KB以下の場合
      • 通常リクエストは、1.0ユニット
      • トランザクションリクエストは、2.0ユニット
    • 1KB以上の場合は、1KB単位 (切り上げ) で比例してかかる
      • 2.6KBのトランザクションは、6.0ユニット必要
  • 読み取りリクエスト
    • 4KB以下の項目の場合
      • 強力な整合性のあるリクエストは、1.0ユニット
      • 結果整合性のあるリクエストは、0.5ユニット
      • トランザクションリクエストは、2.0ユニット
    • 4KB単位(切り上げ)でかかる
      • 7KBの整合性のあるリクエストは、2.0ユニット必要

キャパシティモード

DynamoDBでは、このキャパシティユニットの確保の仕方によって、2つの方法(キャパシティモード)をサポートしています。

プロビジョンドモード

プロビジョンドモードでは、予め必要なキャパシティを設定する方法です。アクセストラフィックが予測可能で、かつ、推移が緩やかなケースに適しています。

  • 1秒あたりに読み書き可能なキャパシティの上限値を設定する
    • 書き込みキャパシティユニット(WCU)、読み取りキャパシティユニット(RCU)と呼ばれる
    • (例) 10RCUであれば、1秒間あたり1KB以下の項目に対して結果整合性のある読み取りリクエストが10回できる
  • WCU/RCUに対して時間課金される
    • 料金は以下の通り(2024/6/6時点[5])で、書き込みは読み取りの5倍かかることを頭に入れておくと良いです
      • 0.000742 USD/WCU/hour
      • 0.0001484 USD/RCU/hour
    • (例) 10RCUを24時間継続させると、0.035616 USDかかる計算になります
  • WCUとRCUはオートスケーリングも設定可能
    • 消費したキャパシティの割合に応じて、上限・下限内でWCU/RCUを自動的に変更する
  • DynamoDBは未使用のWCU/RCUを最大5分間保持しており、多少のスパイクであればスロットリングされないようになっている
    • ただし、バックグラウンドメンテナンスなどで予告なしに消費される可能性があるため、それをあてに設計を行うのは危険

オンデマンドモード

オンデマンドモードでは、予めキャパシティを設定せず、必要なときに必要な分だけ瞬時にスケールさせる方法です。アクセストラフィックが予測不可能だったり、急激なスパイクが発生するケースに適しています。

  • 直前のトラフィックレベルまで~10msで自動的に拡張・縮小する
    • 実際に消費したユニットになるので、書き込み要求ユニット(WRU)、読み取り要求ユニット(RRU)と呼ばれる
  • このWRU/RRUに対して課金される(つまりpay-per-request)
    • 料金は以下の通り(2024/6/6時点[6])で、プロビジョンドモード同様に書き込みは読み取りの5倍かかります
      • 1.4269 USD/100万WRU
      • 0.285 USD/100万RRU

ストレージコスト

キャパシティのついでにストレージコストについても触れておきます。DynamoDBではストレージサイズに対しても料金が発生します。プロビジョンド/オンデマンドでストレージ料金は変わりません[5:1][6:1]

  • Standardテーブルクラス ... 0.285 USD/GB/month
  • Standard-IAテーブルクラス ... 0.114 USD/GB/month

設計プラクティス

設計のプラクティスについてまとめておきます。

RDBとの違いを押さえる

自分もそうでしたが、RDBでのデータ設計に馴染んだ人がDynamoDBの設計に取り組むときには、コンセプトの違いから戸惑ってしまうことが多いかと思います。RDBと比較した時のDynamoDBの特徴を整理しておきます。

  1. (キーに用いられない)属性はスキーマレスで、いつでも自由に追加して良い
  2. 1つのテーブルで保持できるデータ量は無限(項目は最大400KB)
  3. パーティションキーに基づいてデータが分散保持される
  4. テーブルやGSIごとに読み書きのキャパシティが設定できる
  5. テーブルをまたぐクエリやトランザクションはサポートされない

少数のテーブルに集約する

RDBの設計では正規化 + 外部キーでテーブルを分割していくのがセオリーでした。
よくあるToDoアプリの設計では、ユーザー情報、ToDoアイテム情報、タグ情報、コメント情報、ユーザーロール情報などを別々のテーブルに分けて、それぞれが持つIDを外部キーにして持たせることで、できるだけ重複させないようにしていました。

DynamoDBでは、スキーマレスで保持できる項目数にも限りがなく、また、テーブルをまたいだクエリやトランザクションはサポートされていないこともあって、概念としてまとまりがあれば1つのテーブルに集約することが推奨されています。

1つのパーティションキーへのアクセスが集中しないようにする

パーティションキー単位でストレージサーバーが分散されますので、1つのパーティションキーに極端に大量のアクセスが行われると、テーブルやGSIに設定されたキャパシティを超えていなかったとしても、スロットリングが発生する可能性があります。
そのため、パーティションキーは適度にアクセスが分散するように設計しなければなりません。

例えば以下のようなテーブルですと、パーティションキー(PK)のTodoには大量の項目が作成されそうです。カーディナリティの高い別の属性をパーティションキーにする、または、そもそも別の情報であればテーブルを分ける、といった判断が必要になります。

| Kind(PK) | Id(SK) | CreatedAt | Name | Subject | CreatedBy |
|--|--|--|--|--|
| User | 1 | 2024-02-03T11:24:11 | Tanaka | | |
| Todo | 10 | 2024-06-05T09:16:34 | | first todo item. | 1 |

スキャンしない

スキャンではテーブルやセカンダリインデックスの項目数に応じた読み取りキャパシティが必要になります。そのため、数百万以上の項目を持つテーブルに対するスキャンは致命的です。
そのため、スキャンする必要がないように、クエリとセカンダリインデックスをうまく使いこなす必要があります。

クエリのパターンを頭に入れておく

まずはクエリでソートキーに適用できる条件式についてきちんと理解しておく必要があります。
以下は条件式の一覧です[7]。文字列の後方一致でクエリできない点は注意です。

  • a = b
  • a < b, a <= b, a > b, a >= b
  • a BETWEEN b AND c
  • begins_with(a, substr)
    • 文字列が指定した文字列で始まる(前方一致)場合に真

これを踏まえると、一般的にソートキーは順序や階層の関係を値に表現できているものの方が望ましいです。

  • 時刻情報は、時間的順序とDynamoDBでのソート順とが一致するのが望ましい
    • 🙆‍♀ ISO8601(文字列型)やUnix Timestamp(数値型)
    • 🙅 RFC2822 Fri Jun 14 10:06:59 JST 2024
  • 何らかの階層情報は、先頭から末尾にかけて、大項目->小項目の順序になるのが望ましい
    • 🙆‍♀ /usr/local/bin/aws
    • 🙅 news.yahoo.co.jp

ユースケースに対応したセカンダリインデックスを作る

スキャンを避けるため、アクセスパターンごとに適切なキャパシティを割り当てるために、アプリケーションからのユースケースに対応したGSI・LSIを設定しましょう。
例えばToDoアプリであれば、以下のようなユースケースが考えられます。

  • ユーザーごとの今月締切のToDoアイテム一覧を参照する
    • => PK: UserId, SK: DueDate
  • 今日作成された全て(あるいは特定ユーザー)のToDoアイテム一覧を参照する
    • => PK: CreatedDate (CreatedAtから日付部分を抜き出す), SK: UserId

1つのソートキーに複数の値を混ぜ込む

テーブルやセカンダリインデックスにセット可能なキー項目は2つ(PK+SK)だけなので、3つ以上の項目でクエリしたい場合は工夫が必要です。
例えば、ToDoアプリで "特定のユーザーについて今日締め切りで未完了のToDoアイテム一覧" を取得する、といったユースケースでは、UserId(N)・DueDate(S)・Done(BOOL)でクエリしないといけません。

こういった場合、項目を文字列にして、それらをデリミタ(#, /, .など)で連結したものを新たな項目として作り、それをキーにするというやり方がよく採られます。
上のユースケースにあてはめて、UserIdをPKとすると、SKはDueDate#Done(例: 2024-06-05#0)もしくはDone#DueDate(例: 0#2024-06-05)となります。Doneはfalseなら0、trueなら1に置き換えています。
このような文字列にすることで、比較演算子や前方一致を使ったクエリがしやすくなります。

DueDate#Doneにするか、Done#DueDateにするかは他のユースケース次第になります。前者であれば締切日による全件取得、後者であれば完了フラグによる全件取得に、それぞれ使い回せます。

LSIよりもGSIを使う

GSIと比較すると、LSIは制約が多くて使いづらいものです。
また、それぞれアクセスパターンが異なるプライマリキーや複数のLSIの間でベーステーブルのキャパシティを共有することになるので、キャパシティ設計が困難になります。

GSIは後からでも設定できますので、必要に応じて、LSIからGSIへ移行していくと良さそうです。

特にログなどのデータでLSIを使う場合、TTLをセットして、各パーティションキーの項目の合計サイズが10GBを超えないようにしましょう。

消費するキャパシティを確認する

特にクエリでですが、どの程度キャパシティを消費するのかわかりにくいことがあります。そういうときは、--return-consumed-capacityを指定することで、クエリ実行時に消費したキャパシティを確認できます[8]

aws dynamodb query \
  --table-name Todo \
  --key-condition-expression "UserId = :userId and CreatedAt >= :createdAt" \
  --filter-expression "contains(Subject, :keyword)" \
  --expression-attribute-values '{":userId":{"N":"1"},":createdAt":{"S":"2024-06-01T00:00:00"},":keyword":{"S":"first"}}' \
  --return-consumed-capacity TOTAL
{
    "Items": [
        {
            "Done": {
                "BOOL": false
            },
            "UserId": {
                "N": "1"
            },
            "Subject": {
                "S": "first todo item."
            },
            "CreatedAt": {
                "S": "2024-06-05T09:16:34"
            }
        }
    ],
    "Count": 1,
    "ScannedCount": 1,
    "ConsumedCapacity": {
        "TableName": "Todo",
        "CapacityUnits": 0.5
    }
}

オンデマンド? プロビジョンド?

キャパシティを設定する必要がなく、裏で高速にスケールしてくれるオンデマンドモードの方が便利で運用も楽ですが、ユニットあたりの料金差がかなり大きいことは認識しておいたほうがいいです。仮にプロビジョンドで設定したキャパシティを100%使いきったケースと比較すると、オンデマンドのほうが7倍くらい高くなります。
もちろんそんな理想的なアクセスは考えにくいので、実際のアクセスパターンを見極めて、適切なモードを選択しましょう。

テーブルやGSIを作成後も、キャパシティモードは変更できます(前回のモード変更から24時間以上経過していれば)。なので、アクセスが読めない最初はオンデマンド、アクセスが読めてきたらプロビジョンドに変更することもできます。

まとめ

今回はDynamoDBで設計するために、予め知っておきたかった情報をまとめました。他にもDynamoDB StreamsやDAXなどの周辺機能も多々ありますので、そういった機能の活用も視野にいれたアーキテクチャを検討する必要があります。

参考

https://docs.aws.amazon.com/dynamodb/
https://speakerdeck.com/_kensh/dynamodb-design-practice

脚注
  1. https://aws.amazon.com/jp/blogs/news/happy-birthday-dynamodb/ ↩︎

  2. https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html ↩︎ ↩︎

  3. https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/bp-partition-key-design.html ↩︎

  4. https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/TTL.html ↩︎

  5. https://aws.amazon.com/jp/dynamodb/pricing/provisioned/ ↩︎ ↩︎

  6. https://aws.amazon.com/jp/dynamodb/pricing/on-demand/ ↩︎ ↩︎

  7. https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Query.KeyConditionExpressions.html ↩︎

  8. https://awscli.amazonaws.com/v2/documentation/api/latest/reference/dynamodb/query.html ↩︎

Discussion