DynamoDBでGSIおよびLSIを持つテーブルの作成およびクエリをコンソールから行ってみた

2020.07.11

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

こんにちは、CX事業本部の若槻です。

DynamoDBでは、セカンダリインデックスという仕様を使用して、プライマリキーとは別に追加でパーティションキーやソートキーをテーブルに持たせることにより、一つのテーブルで複数のユースケースによるクエリに対応させることができたり、検索効率を上げたりすることができたりします。

今回は、DynamoDBでGSI(グローバルセカンダリインデックス)およびLSI(ローカルセカンダリインデックス)を持つテーブルの作成およびクエリの実施を、AWSのマネジメントコンソールから行ってみました。

ユースケース

ユーザーオブジェクトとグループオブジェクトの管理を、次で紹介されているようなベストプラクティスに基づき単一のDynamoDBテーブルで行うとします。

一般的なルールとして、DynamoDB アプリケーションはできるだけ少ないテーブルを維持する必要があります。

そして今回は次のデータ取得のアクセスパターンを実現できるテーブルを考えてみます。

  1. 特定のIDのオブジェクトを取得
  2. 特定のタイプのオブジェクトをすべて取得

その場合は次のようなキーおよび属性による構成のテーブルが考えられます。

  • プライマリパーティションキー(PK):objectType
  • プライマリソートキー(SK):createdAt
  • GSIのパーティションキー(GSI-PK):objectId
  • LSIのソートキー(LSI):updatedAt
  • 非キー属性(Attr):objectNamememberbelongingTo
objectType(PK) createdAt(SK) updatedAt(LSI) objectId(GSI-PK) objectName(Attr) member(Attr) belongingTo(Attr)
グループオブジェクト Group {Timestamp} {Timestamp} {GroupId} {GroupName} ({UserId1}, {UserId2}, {GroupId1}…)
ユーザーオブジェクト User {Timestamp} {Timestamp} {UserId} {UserName} ({Group1}, {Group2},…)

この構成のDynamoDBテーブルをマネジメントコンソールから作成してみます。

テーブルの作成

AWSのマネジメントコンソールでDynamoDBテーブルの新規作成ページを開きます。

[テーブル名]と[プライマリキー]を指定したら、[テーブル設定]で[デフォルト設定の使用]のチェックを外します。 image.png

[セカンダリインデックス]で[インデックスの追加]をクリックします。まずGSIから追加していきます。 image.png

[インデックスの追加]ダイアログが開きます。[パーティションキー]でGSIのパーティションキーとしてobjectIdを指定します。[インデックス名]はインデックス種類とキーが分かる名前としました。[射影される属性]は、GSI使用時はすべての属性の値を取得したいのですべてを指定します。最後に[インデックスの追加]をクリックします。 image.png

GSIを追加できました。再度[インデックスの追加]をクリックします。次はLSIを追加していきます。 image.png

[インデックスの追加]ダイアログが開きます。LSIのプライマリキーとして[パーティションキー]でobjectTypeを指定し、[ソートキー]でupdatedAtを追加します。GSIと同様に[インデックス名]はインデックス種類とキーが分かる名前、[射影される属性]はすべてを指定します。LSIとする場合は[ローカルセカンダリインデックスとしての作成]にチェックを入れます。(このチェックボックスは[パーティションキー]でプライマリパーティションキーを指定し、[ソートキーの追加]をチェックした時のみチェック可能となりました。)最後に[インデックスの追加]をクリックします。 image.png

LSIも追加できました。 image.png

最後に[作成]をクリックしてテーブルの作成を完了させます。 image.png

テーブルを作成できました。 image.png

クエリの実施

作成したテーブルに対して各種方法でクエリを実施してみます。

オブジェクトのアイテムは次のようにテーブルに追加しました。 image.png

プライマリキーによるクエリ

プライマリキーであるパーティションキーobjectTypeとソートキーcreatedAtによるクエリをしてみます。前述したアクセスパターンのうちだと「2. 特定のタイプのオブジェクトをすべて取得」に該当します。

オペレーション種類でクエリ、対象で[テーブル]〜を選択し、objectTypecreatedAtを指定すると検索ができました。また、検索結果の並び順はソートキーであるcreatedAtで昇順にソートされています。 image.png

GSIによるクエリ

GSIによるクエリをしてみます。アクセスパターンのうちだと「1. 特定のIDのオブジェクトを取得」に該当します。

オペレーション種類でクエリ、対象で[索引]GSI〜を選択し、objectIdを指定すると検索ができました。 image.png

LSIによるクエリ

LSIによるクエリをしてみます。アクセスパターンのうちだと「2. 特定のタイプのオブジェクトをすべて取得」に該当します。

オペレーション種類でクエリ、対象で[索引]LSI〜を選択し、objectTypeupdatedAtを指定すると検索ができました。また、検索結果の並び順はソートキーであるupdatedAtで昇順にソートされており、ここがプライマリキーによるクエリとの違いとなります。 image.png

おわりに

DynamoDBでGSIおよびLSIを持つテーブルの作成およびクエリをコンソールから行ってみたのでご紹介をしました。

RDBとは異なりNoSQLであるDynamoDBはなるべく少ないテーブルでシステムを構築するのがベストプラクティスであるため、今回のように異なる種類のデータを同じテーブル上で管理する構成はよくあるケースだと思います。そういう場合にセカンダリインデックスがとても役に立つということを今回知ることができました。

以上