AWS DynamoDBのファセットとは?DynamoDB SDP 認定パートナー企業の開発エキスパートが解説😎

AWS DynamoDBのファセットとは?DynamoDB SDP 認定パートナー企業の開発エキスパートが解説😎

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは!

昨今では、サーバーレスの開発プロジェクトが増加したのに伴い、DynamoDB を使用した開発案件が大変増えてきました。わたしたちがDynamoDBの設計を行う際、NoSQLワークベンチではデータベース全体の俯瞰・把握が難しいため、独自に作成したDynamoDBのフォーマットを使用しお客様のサーバーレスプロジェクトを支援しています。

お客様のビジネスの要件定義をもとにデータモデリングを行う際、Swagger のようにコード上でデータアクセス定義ができたらなぁ…という思想から採用しました。(スプレッドシートの管理に限界を感じました…)

NoSQLWorkBench をまだ使用されていない方は、是非一度ダウンロードして使ってみてください!

本記事では、DynamoDB の設計で必須となる「ファセット」というデザインパターンについて解説をしていきます。

想定する読者

  • AWS DynamoDB を使用してプロダクト開発を行っているヒト
  • AWS DynamoDB のアーキテクチャーを行っているヒト
  • AWS DynamoDB を使用したチーム開発に悩んでいるヒト

はじめに

ファセットは DynamoDB の機能ではありません

ファセットは、GSI、LSI のような DynamoDB の機能ではありません。後述で詳しく解説していきます。

DynamoDBの設計ベストプラクティスについておさらい

DynamoDB の設計を行う際、スキーマレス、パーティションキー・ソートキーの特性を活かした以下の設計思想が望ましいとされています。

  • 最小のテーブル数で構築すること
  • クエリーを分散すること(単一のパーティションキーにアクセスが集中しないこと)
  • 関連項目をグループ化しソートすること
  • グローバルセカンダリーインデックスを使用すること

特にRDB出身の方はテーブルを正規化しがちですが、DynamoDBではできるだけ少ないテーブル数のほうが望ましいとされていますので注意しましょう。テーブル数を少なくすることで、DB構造の簡素化、バーストアクセス時のスペック調整の容易にすることができます。

その最小のテーブル数を実現するために、必須のテクニックが「ファセット」となります。

尚、DynamoDBのデザインパターンに関するAWSドキュメントはこちらをご覧ください。

ファセットは DynamoDB テーブルのアクセスパターンを定義します

 例えば、EC サイトでユーザーのプロフィール情報と、ユーザーの商品お気に入り情報を保持するテーブル構造を考えてみましょう。

ユーザーのプロフィール情報

{
  customerId: '0001',
  customerName: '田中太郎',
  email: 'yamada@example.com'
}

ユーザーのお気に入り商品情報

{
  customerId: '0001', 
  favoriteProductId: '12345'
}

上記の2つのデータの格納を考えた場合、RDB脳だと「users」「user_favorites」的な2つのテーブルを考えるはずです。

しかし、DynamoDBでは以下のように考えます。

  • テーブルは一つのみ(Userテーブル)
  • Userテーブルの中でユーザーに紐づく情報を管理
  • Userテーブルの中にプロフィール情報とお気に入り商品情報を保持

後述で具体的なDynamoDBの設計を解説しますが、まずここで肝心なのは、DynamoDB はインデックス属性以外はスキーマレスということです。簡単に言えばデータ構造の決まっていないJSONデータをバシバシいれることができるとうことです。ここで、JSONを無作為に挿入したら何のデータなのかデータの管理がしにくいのでは?と考えると思います。

ここで登場するのがファセットです!

ファセットを使用した設計を考える

まず、User テーブルに格納したい情報を、 2 つの分類に分けることができます。

  • プロフィール情報
  • お気に入り商品情報

上記の2つの情報を以下のようにDynamoDBでは設計することが出来ます。

Userテーブルのインデックス構造

属性名Key type
customerIdパーティションキー
typeソートキー
Userテーブルのインデックス構造

プロフィールファセット

{
  customerId: '0001',
  sortKey: 'profile',
  customerName: '田中太郎',
  email: 'yamada@example.com'
}

お気に入り商品 ファセット

{
  customerId: '0001', 
  sortKey: 'favoriteProduct',
  favoriteProductId: '12345'
}

上記のデータ構造を見ると、「sortKey」という属性が追加されていると思います。この「sortKey」の値で、そのItemが、何の情報なのかをわかるようにします。

前述の例の場合以下のようになります。

sortKey何の情報?
profileユーザーのプロフィール情報
favoriteProductユーザーのお気に入り商品情報

1 つの属性の値次第で、複数の意味を持つことをオーバーローディングと言います

前述のように、一つの属性の値次第でそのItemの解釈を変更する手法を、オーバーローディングと言います。

つまり、sortKeyの値によって、Item の意味が異なることになります。 今回の例では sortKey がオーバーロードされた属性です。

開発が進んでいけば、今回の sortKey のようなオーバーローディングテクニックを使用したテーブルもいくつか発生することがあるので、ファセットは確実に設計するようにしましょう。( わたしたちは独自のDynamoDB用の設計フォーマットを用いて設計を行います )

正しくファセットを設計することで規模がスケールしても、保守性高くチーム開発がしやすくなります。

まとめ

RDBでも同じことが言えますが、開発が進むに連れて DynamoDB も、テーブルがどんな情報を格納しているのかを識別するのがだんだんと複雑になってきます。

設計者は、テーブルにどのような情報が格納されているのか視覚的に判断できるよう、DynamoDB 設計の際には必ずファセットを使用しましょう。

DynamoDB の設計・サーバーレス開発は、お気軽にご相談ください。