📘

DynamDBでのテーブル設計例① ~1レコードにまとめた方が良い場合~

2023/11/12に公開

テーブル例

実務で出くわした話です。ただ、実務そのままの実装例は扱えないので、別の例として社内文書に対するアクセス制御を考えます。社内文書はカテゴリが存在し、カテゴリごとに文書量が異なります。ただし、文書量には各カテゴリで最大100の制限があるとします(ここがちょっと非現実的かも)。
カテゴリの量は動的に変動すると考えてください。

リレーショナルなDBであれば、こんな感じになるのかと思います。
レコードが存在しない=アクセス可にするか否かとかの話はおいときます。

社員ID カテゴリID 文書ID アクセス
1 3 1 true
2 4 1 false

DynamoDBも同じ形式でテーブルレコードを作る場合、機能自体は問題ないですがコスト面で問題が出てきます。

DynamoDBの書き込みコスト

実務の要件でもありましたが、カテゴリ等で一括してアクセス制限をしないといけないケースはよくあると思います。DynamoDBでは1レコードの更新に1WRU消費することとなり、ユーザー数を100とした場合、最大100*100の10000WRU(1レコード1KB以下とする)を毎回消費することになります。このアクセス制限の操作が行われる頻度によっては、なかなか無視できない数値になります。

1レコードに収める

1レコードへの書き込みごとに課金されるので、なるべくまとめてしまおうという話です。
この例だとPK=社員ID SK=カテゴリIDにし、アクセス制限情報について記載するオブジェクトに各文書IDとbooleanの情報をまとめることになります。
つまり、このような感じになります。

社員ID カテゴリID アクセス
1 3 { 文書ID:1 制限: true ,文書ID: 2 制限: false , ... }
2 4 { 文書ID:2 制限: true ,文書ID: 3 制限: false , ... }

先ほどレコード書き込みで10000WRU消費していましたが、このように実装すれば100~200程度には収まることになります(単純に100WRUにならないのは1レコードが1KBを超える可能性があるからです)。
また、scanやqueryでデータ取得する際も自動的にユーザ別になって少し楽になります。
ここで考えないといけないのはDynamoDBの1レコードあたりの容量制限=400KBです。
文書量の最大値が見えてない状態でこの実装を行うと最悪エラーになってしまいます。なので例では非現実といえど、カテゴリごとの文書の最大量を100としました。

Discussion