AWS

NoSQL初心者のためのDynamoDBデータ構造

dynamodb
koma

ご無沙汰しております!
最近たくさんの方に入社いただき、ついに平均年齢を上回ってしまったこまっちゃんです。

さて、今回はDynamoDBのデータ構造について解説したいと思います。
かくいう私はRDB設計ばかり行なっているので、DynamoDBは初心者です
あくまで現時点の情報となりますので、最新のソースのご確認をお願いいたします!

記事の対象となる方

  • RDBMS(SQL)の設計に慣れている方
  • NoSQLの設計をしたことがない/これから挑戦したいと思っている方

DynamoDBの特徴

そもそも、DynamoDBはどんな特徴があるの?というところですが、以下の様なメリットを持っています。

  • フルマネージドでサーバーレスなので、レプリケーションやスケーリングが自動で実行される
  • jsonのようなkey-value形式でデータを取得するNoSQLデータベース
  • インメモリキャッシュを保持した、低レイテンシーな読み取り
  • 自動的にスケーリングすることによる高い書き込みパフォーマンス

一方、もちろんデメリットも存在します。

  • NoSQLのため、デーブルをjoinするような複雑な検索や集計処理は難しい
  • 可用性を維持するために、データの一貫性が損なわれることがある※
    (自動的にデータをバックアップ(レプリケーション)するので、データ更新・取得がほぼ同時に起こった場合に、更新前のデータを返してしまうことがある)
注意点

「結果整合性モデル」の場合です。強力な一貫性を持たせた場合は一致しますが、読み込み時にスループットが2倍必要となります。では「強力な整合性モデル」を選択すればいいじゃない!となりますが、すると、検索に使用するGSI(グローバルセカンダリインデックス(後述))を使用できなくなります。

以上を踏まえると、DynamoDBのユースケースとしては以下のようなものがおすすめです。
複雑な検索条件があったり、テーブル同士を結合する必要があったり、集計が必要なワークロードがある場合はRDBMSの検討をすると良さそうですね。

  • ゲームなどの水平スケールが必要なシステム
  • 複雑なSQL検索条件を使用しないが、低レイテンシーが必要なシステム
  • 運用コストを下げたいケース
あわせて読みたい
Amazon DynamoDB デベロッパーガイド / ベストプラクティス / DynamoDB 用の NoSQL
Amazon DynamoDB デベロッパーガイド / ベストプラクティス / DynamoDB 用の NoSQL

DynamoDBのデータ構造

部員ひとりひとりにIDが割り振られる、以下のような部員テーブルがあったとします。

パーティションキーソートキー
ID役職名前学年
1部長鈴木春人3
2副部長武内夏美2
3部員高橋秋1
4部員横山冬樹2
部員テーブル

DynamoDBはkey-value形式であると前述しましたが、item(レコード)を取得するためのキー(プライマリキー)は2種類しか指定できません。

独立したパーティションキーのみで検索するか、パーティションキー + ソートキーの複合ユニークキーで検索するか、です。

上の表のように、IDが独立していればパーティションキーのみでitemを取得できますね。
一方、もし「役職」がパーティションキーだった場合、「部員」が重複しているので新しくソートキー(IDや名前)を指定して、キーがユニークになるようにしてあげる必要があります。

絞り込みに使用するキーを適切に指定しないと、検索範囲が広がってしまいせっかくの低レイテンシーが維持できなくなってしまうので注意しましょう。

ただし、「役職」をパーティションキーに指定するメリットもあります。例えば「部員」だけを設定した場合、DynamoDBは「部員」全員を取得することができます。

パーティションキー

ここで、パーティションキーを深掘りしてみます。DynamoDB は、itemを保存する箱(パーティション)に入れるためにパーティションキーをハッシュ化して使います。そのため、パーティションキーは必須です!複数のitemが同じパーティションキーを持っている場合、ソートキーでソートされ、まとめて箱に保存されます。

パーティションキーを設計する際は、パーティションキーへのアクセスが分散することが重要です。あるパーティションキーにアクセスが集中してしまうと、スロットリングしたり、データベースの容量を適切に使用できなくなることがあるためです(=「ホット」パーティション)。

例えば、社員が1万人いる会社があるとします。

  1. 社員IDをパーティションキーにする
  2. 出勤/欠勤のステータスをパーティションキーにする

①の場合、アクセスは分散しそうですが、②の場合「出勤」に極端にアクセスが集中してしまいそうですよね。データにどんな、どれだけのアクセスが想定されるかを考慮して設計していきましょう。

あわせて読みたい
パーティションキーを効率的に設計し、使用するためのベストプラクティス
パーティションキーを効率的に設計し、使用するためのベストプラクティス

ソートキー

前述した通り、パーティションキーが同じ場合、itemはソートキーで昇順にソートされてパーティションに保存されます。ソートキーは必須ではありませんが、範囲クエリを指定することでグループ検索をすることができたり、降順にデータを取得することも可能です。
<>, == といった演算子を使用してクエリを発行できるので、RDBMSに慣れ親しんだ人にも使いやすいキーかもしれませんね。

あわせて読みたい
ソートキーを使用してデータを整理するためのベストプラクティス
ソートキーを使用してデータを整理するためのベストプラクティス

その他の検索方法

では、「パーティションキーやソートキー以外で絞り込みを行いたい」
「ソート条件を複数指定したい」という場合、どのように設計すれば良いでしょう。

ここで活躍するのが、セカンダリインデックスです。
DynamoDBは2種類のセカンダリインデックスをサポートしています。

Local Secondary Index (LSI)

LSIには以下のような特徴があります。

  • ソートキー以外に絞り込み検索を行うkeyを持つことができる
  • パーティションキーが同一で、ソートキー以外(Attributes)を使用する検索に利用できる

例えば以下の例の場合、DWSが何年に何の曲を発表したのかは検索することができません。

パーティションキーソートキー
アーティスト名曲名発表年
DWSmore professional2010
DWSmore trust2010
DWSmore fun 2009
アーティストテーブル

しかし、「発表年」をLSIに指定することで、発表年別に絞り込みができるようになります。

パーティションキーソートキー
アーティスト名発表年曲名
DWS2009more fun
DWS2010more professional
DWS2010more trust
アーティストテーブル

DynamoDB の各テーブルには5つのLSIを設定することが可能です。LSIは以下の点が注意点として挙げられるため、一般的には次のGSIを使用することが推奨されています。

  • 複数のパーティションにまたがった検索はできない(GSIで行う)
  • テーブル作成後に追加できない(GSIは可能)

しかし、結果整合性・強い結果整合性の両方をサポートしているので、強い整合性モデルを採用する場合はLSIを使うと良いです(GSIは結果整合性のみサポート)。強い結果生合成を有効にしたい場合は、クエリでConsistentReadtrueに指定します。

Global Secondary Index (GSI)

複数のパーティションにまたがった検索が可能なため「グローバル」と名前がついています。GSIは各テーブルに20個まで設定可能です。

先ほどの例では発表年から検索を行うことができないので、GSIを使用してパーティションキーを交換することで、行いたかった検索が実現できます。

パーティションキーソートキー
発表年アーティスト名曲名
2009DWSmore fun
2010DWSmore professional
2010DWSmore trust
アーティストテーブル

LSI/GSIの細かな違いについては、ぜひ公式サイトからご確認ください。

あわせて読みたい
セカンダリインデックスを使用したデータアクセス性の向上
セカンダリインデックスを使用したデータアクセス性の向上

このように非常に便利なセカンダリインデックスですが、デメリットも存在します。インデックスはストレージやプロビジョニング済みのスループットを消費するため、設定すればするほどパフォーマンスに悪影響を及ぼしてしまいます。

セカンダリインデックスを使用する際は、インデックス数は最小限に抑えましょう頻繁にクエリを行わない属性では、極力セカンダリインデックスを作成しないようにすると良いですね。

まとめ

いかがでしたでしょうか。

DynamoDBはキーの設計が全てと言っても過言ではありません。
key-valueというシンプルな形式であるがゆえに低レイテンシーで高いスループットを誇るDynamoDBですが、SQLのような複雑なクエリや集計等は苦手です。極力シンプルな構成にし、想定されるユースケースを元に適切なキーを設定しましょう。

複雑な検索が必要なケースが多い場合は、そもそもDynamoDBを選択せず、RDSMSからデータベースを選択するのも大事な手です。

NoSQL初心者の皆さんに少しでもお役に立てたなら幸いです。

あわせて読みたい
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
AWS Black Belt Online Seminar 2018 Amazon DynamoDB Advanced Design Pattern
AUTHOR
koma
koma
エンジニア
元々製薬業界で働いており、スクールを経てDWSに入社。主にgolangを使用したバックエンド業務に携わっているが、触ったことのない技術にも楽しく挑戦していきたいと考えている。趣味はスキューバダイビング。
記事URLをコピーしました