DynamoDBでGSIやLSIのキーは重複や値なしが許容されるのか確認してみた

2020.07.13

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

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

今回は、DynamoDBでGSI(グローバルセカンダリインデックス)やLSI(ローカルセカンダリインデックス)のキーは重複や値なしが許容されるのか気になったので確認してみました。

確認してみた

次のようなDynamoDBテーブルを使用して確認します。

{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "createdAt",
                "AttributeType": "N"
            },
            {
                "AttributeName": "objectId",
                "AttributeType": "S"
            },
            {
                "AttributeName": "objectType",
                "AttributeType": "S"
            },
            {
                "AttributeName": "updatedAt",
                "AttributeType": "N"
            }
        ],
        "TableName": "object-master",
        "KeySchema": [
            {
                "AttributeName": "objectType",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "createdAt",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": 1594468590.571,
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 5,
            "WriteCapacityUnits": 5
        },
        "TableSizeBytes": 404,
        "ItemCount": 4,
        "TableArn": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/object-master",
        "TableId": "2055b0a7-88c4-4223-920b-xxxxxxxxxxxx",
        "LocalSecondaryIndexes": [
            {
                "IndexName": "LSI-objectType-updatedAt",
                "KeySchema": [
                    {
                        "AttributeName": "objectType",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "updatedAt",
                        "KeyType": "RANGE"
                    }
                ],
                "Projection": {
                    "ProjectionType": "ALL"
                },
                "IndexSizeBytes": 404,
                "ItemCount": 4,
                "IndexArn": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/object-master/index/LSI-objectType-updatedAt"
            }
        ],
        "GlobalSecondaryIndexes": [
            {
                "IndexName": "GSI-objectId",
                "KeySchema": [
                    {
                        "AttributeName": "objectId",
                        "KeyType": "HASH"
                    }
                ],
                "Projection": {
                    "ProjectionType": "ALL"
                },
                "IndexStatus": "ACTIVE",
                "ProvisionedThroughput": {
                    "NumberOfDecreasesToday": 0,
                    "ReadCapacityUnits": 5,
                    "WriteCapacityUnits": 5
                },
                "IndexSizeBytes": 404,
                "ItemCount": 4,
                "IndexArn": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/object-master/index/GSI-objectId"
            }
        ]
    }
}

キーの仕様を抜粋すると以下のとおりです。

  • プライマリパーティションキー:objectType
  • プライマリソートキー:createdAt
  • GSI-objectIdパーティションキー:objectId
  • LSI-objectType-updatedAtソートキー:updatedAt

事前にテーブルには次のようにアイテムを登録しました。 image.png

重複するキーの登録

GSIのキーを重複させてみる

GSIのキーobjectIdが重複するようにアイテムを登録してみます。

$ aws dynamodb put-item --table-name object-master \
    --item '{"objectType": {"S": "Group"}, "createdAt": {"N": "55555555"}, "objectId": {"S": "g0001"}, "updatedAt": {"N": "55555555"}}'

登録できました。GSIのキーが重複するアイテムが併存できています。 image.png

GSIのキーでクエリをしてみると、GSIのキーが重複しているアイテムがすべて取得できました。 image.png

LSIのキーを重複させてみる

LSIのキーobjectType+updatedAtが重複するようにアイテムを登録してみます。

$ aws dynamodb put-item --table-name object-master \
    --item '{"objectType": {"S": "User"}, "createdAt": {"N": "66666666"}, "objectId": {"S": "u0003"}, "updatedAt": {"N": "66666666"}}'

テーブルに登録できました。LSIのキーが重複するアイテムが併存できています。 image.png

LSIのキーでクエリをしてみると、LSIのキーが重複しているアイテムがすべて取得できました。 image.png

GSIおよびLSIのキーを値なしにしてみる

プライマリキーobjectType+createdAtのみ値を持ったアイテムを登録してみます。

$ aws dynamodb put-item --table-name object-master \
    --item '{"objectType": {"S": "User"}, "createdAt": {"N": "77777777"}}'

テーブルに登録できました。 image.png

GSIでスキャンした場合は取得できませんでした。GSIのキーを持っていないアイテムはGSIには登録されないようです。 image.png

同様に、LSIでスキャンした場合も取得できませんでした。 image.png

まとめ

  • GSIやLSIのキーが重複していたり値なしのアイテムもテーブルに登録可能。
  • キーが重複しているアイテムでもインデックスの検索ですべて取得可能。
  • キーの値なしのアイテムはインデックスの検索では取得不可。

参考

以上