
DynamoDBでGSIおよびLSIを持つテーブルの作成およびクエリをコンソールから行ってみた
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
DynamoDBでは、セカンダリインデックスという仕様を使用して、プライマリキーとは別に追加でパーティションキーやソートキーをテーブルに持たせることにより、一つのテーブルで複数のユースケースによるクエリに対応させることができたり、検索効率を上げたりすることができたりします。
今回は、DynamoDBでGSI(グローバルセカンダリインデックス)およびLSI(ローカルセカンダリインデックス)を持つテーブルの作成およびクエリの実施を、AWSのマネジメントコンソールから行ってみました。
ユースケース
ユーザーオブジェクトとグループオブジェクトの管理を、次で紹介されているようなベストプラクティスに基づき単一のDynamoDBテーブルで行うとします。
一般的なルールとして、DynamoDB アプリケーションはできるだけ少ないテーブルを維持する必要があります。
そして今回は次のデータ取得のアクセスパターンを実現できるテーブルを考えてみます。
- 特定のIDのオブジェクトを取得
- 特定のタイプのオブジェクトをすべて取得
その場合は次のようなキーおよび属性による構成のテーブルが考えられます。
- プライマリパーティションキー(PK):
objectType - プライマリソートキー(SK):
createdAt - GSIのパーティションキー(GSI-PK):
objectId - LSIのソートキー(LSI):
updatedAt - 非キー属性(Attr):
objectName、member、belongingTo
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テーブルの新規作成ページを開きます。
[テーブル名]と[プライマリキー]を指定したら、[テーブル設定]で[デフォルト設定の使用]のチェックを外します。

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

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

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

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

LSIも追加できました。

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

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

クエリの実施
作成したテーブルに対して各種方法でクエリを実施してみます。
オブジェクトのアイテムは次のようにテーブルに追加しました。

プライマリキーによるクエリ
プライマリキーであるパーティションキーobjectTypeとソートキーcreatedAtによるクエリをしてみます。前述したアクセスパターンのうちだと「2. 特定のタイプのオブジェクトをすべて取得」に該当します。
オペレーション種類でクエリ、対象で[テーブル]〜を選択し、objectTypeとcreatedAtを指定すると検索ができました。また、検索結果の並び順はソートキーであるcreatedAtで昇順にソートされています。

GSIによるクエリ
GSIによるクエリをしてみます。アクセスパターンのうちだと「1. 特定のIDのオブジェクトを取得」に該当します。
オペレーション種類でクエリ、対象で[索引]GSI〜を選択し、objectIdを指定すると検索ができました。

LSIによるクエリ
LSIによるクエリをしてみます。アクセスパターンのうちだと「2. 特定のタイプのオブジェクトをすべて取得」に該当します。
オペレーション種類でクエリ、対象で[索引]LSI〜を選択し、objectTypeとupdatedAtを指定すると検索ができました。また、検索結果の並び順はソートキーであるupdatedAtで昇順にソートされており、ここがプライマリキーによるクエリとの違いとなります。

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






