シングルテーブル設計についてまとめてみた【DynamoDB】
本ページでは、DynamoDBで良く用いられるデザインパターンであるシングルテーブル設計について、その必要性やメリット/デメリットについて、勉強したことをメモしたいと思います。

シングルテーブル設計とは

まず、AWS DynamoDBは、AWSが提供するKey-Value型のNoSQLデータベースサービスです。DynamoDBの概要はこちらの記事にも書いていますので、参考にしてください。

そして、そのDynamoDBでよく用いられるデザインパターンが、シングルテーブル設計(Single Table Design)です。
シングルテーブル設計について、先にざっくり言ってしまうと…
です。その名前の通り、リレーショナルデータベース(RDB)であれば複数のテーブルに分割するようなデータを、一つのテーブルに集約します。
なぜシングルテーブル設計が必要?
まずそもそもNoSQLは、昔ながらのRDBに対して、柔軟性や処理速度などの向上を目指して作られたアーキテクチャです。DynamoDBも、処理の速さと拡張性・柔軟性の高さを売りにしています。
一方、それを実現するために犠牲になっていることもあります。それが、RDBで使用できたSQLのJOIN(結合)に相当する機能の非搭載です。このため、もしDynamoDBにおいて複数テーブルにまたがってデータを取得したい場合、
- テーブル1で必要なデータを取得
- テーブル1で取得したデータをもとに、テーブル2からデータ取得
- テーブル2で取得したデータをもとに、テーブル3からデータ取得
- …
といった具合に、テーブルの数だけリクエストを投げてデータ取得する必要が出てきます。明らかにスマートでないですね。取得する項目数が多ければ時間もかかってしまいます。
これを解決するため、平たく言ってしまえば、「最初からJOIN(結合)して1つのテーブルにまとめておけば、1回のクエリで全部データ取れるじゃん」という発想で生まれたのが、シングルテーブル設計です。

DynamoDBは、テーブルが非常に大きな場合においても、一貫して高いパフォーマンスを発揮することを目指したサービスです。
一方、テーブルの結合という機能は、テーブルが大きいほど処理が重くなりそうであることは直感的にも想像できますね。DynamoDBに実装されなかったのも納得です。
シングルテーブル設計のメリット
以下がシングルテーブルのメリットです。
- 大量のデータを効率よくクエリでき、高いパフォーマンスを実現できる
- クエリを効率することで、コストを削減できる
- テーブルが1つにまとまることで、運用がシンプルになる
3つめは、他2つと少し性質の違うメリットですね。AWS目線では、複数のDynamoDBテーブルというのは、AWSリソースとしてはそれぞれ別物になってしまいます。それを考えると、少ない方が運用は当然シンプルです。
シングルテーブル設計のデメリット
ずばり、設計が難しいことです。探せばベストプラクティスはありつつも、結局ケースバイケースになってしまいます。RDBではとりあえずデータ洗い出して正規化していけば良かったですが、そうはいかないのが辛いところです。
この難しさは、DBがアプリケーション上どう使われるかを意識する必要があることに加え、データ構造が人間(初心者)にとって想像/理解しにくいという点に起因している気がします。NoSQLはただでさえRDBよりイメージしにくいのに、1テーブルにいろんな種類の項目が入ってくるとなおさら整理しにくいです…

設計具体例
こちらは、AWS公式で示されている例です。InvoiceとBillという、2種類の項目が1つのテーブルで管理されています。関係的には、Invoiceが親でBillが子ですね。
さらに、ソートキーにはGSI (グローバルセカンダリインデックス) が設定されています。さすがに1テーブルにしてしまうと、パーティションキー、ソートキーだけによる細かいクエリが難しくなるため、インデックスの設定を上手く併用することが必要になります。

DynamoDB テーブルで多対多リレーションシップを管理するためのベストプラクティス – Amazon DynamoDB

シングルテーブル設計にしたかったのは分かるとして、何でこういう構造にしたのか?と気になるところですよね。それは、「こうすると欲しいデータが都合よくクエリできるから」だけだと思います。
つまり結局は、テーブル設計する前に「どんな時にどんなデータをクエリしたいか?」を考え、それを実現できるように設計するしかありません。設計の難しいところであり面白いところですね…
まとめ
ここまで、シングルテーブル設計の基本的な考え方についてまとめました。
私自身もシングルテーブル設計を取り入れて設計開発に取り組みましたが、設計がもはやパズルです。「こういうふうにキーを設定するとこれを取得しやすいけど、今度はこれが取得しにくくなるな…」といった試行錯誤をずっと繰り返している感じでした。
こうすれば上手くいく!という画一的な方法も無いため、結局このページでも有益な設計方法が提供できずに申し訳ないですが、少しでも理解の助けになれば幸いです。
