DynamDBでのテーブル設計例① ~1レコードにまとめた方が良い場合~
テーブル例
実務で出くわした話です。ただ、実務そのままの実装例は扱えないので、別の例として社内文書に対するアクセス制御を考えます。社内文書はカテゴリが存在し、カテゴリごとに文書量が異なります。ただし、文書量には各カテゴリで最大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