あめがえるのITブログ

頑張りすぎない。ほどほどに頑張るブログ。

【AWS】DynamoDBのキーについて調べてみた

知ってるようでよく覚えていないDynamoDBについて調べてみた。

DynamoDB要素

パーティションキー:
 テーブル作成時に必須。ハッシュキーとも言われる。アイテムを一位に識別し、パーティションを決定するキー。ソートキーがない場合はパーティションキーで重複があってはいけない。ソートキーがある場合は、パーティションキー+ソートキーで重複があってはいけない。
ソートキー:
 テーブル作成時は必須ではないが、あとから追加できない。パーティションキーと組み合わせてアイテムを一意に識別するための2つ目のキー。
ローカルセカンダリインデックス(LSI):
 テーブル作成時は必須ではないが、あとから追加できない。2つ目のソートキーとして使用する。
グローバルセカンダリインデックス(GSI):
 後から追加可能。テーブルのキー構造とは異なるパーティション・ソートキーでアイテムを検索可能。

後からソートキーやLSIを追加したい場合

テーブルを作り直しするか、GSIを使用する。


やること

サンプルのDynamoDBテーブルを作成し、パーティションキー、ソートキー、LSI、GSIで検索をする。

実践!

1.サンプルテーブル作成
※テーブル構造はこんな感じ

 ローカルセカンダリインデックス (LSI)

Index Name Partition Key Sort Key Projection Type
AmountIndex CustomerId Amount ALL

 グローバルセカンダリインデックス (GSI)

Index Name Partition Key Sort Key Projection Type
CategoryIndex Category Amount ALL

1-1.CloudShellで下記を実行

$ aws dynamodb create-table \
    --table-name Orders \
    --attribute-definitions \
        AttributeName=CustomerId,AttributeType=S \
        AttributeName=OrderDate,AttributeType=S \
        AttributeName=Amount,AttributeType=N \
    --key-schema \
        AttributeName=CustomerId,KeyType=HASH \
        AttributeName=OrderDate,KeyType=RANGE \
    --local-secondary-indexes \
        "[
            {
                \"IndexName\": \"AmountIndex\",
                \"KeySchema\": [
                    {\"AttributeName\": \"CustomerId\", \"KeyType\": \"HASH\"},
                    {\"AttributeName\": \"Amount\", \"KeyType\": \"RANGE\"}
                ],
                \"Projection\": {\"ProjectionType\": \"ALL\"}
            }
        ]" \
    --billing-mode PAY_PER_REQUEST

1-2.作成確認

$ aws dynamodb describe-table --table-name Orders
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "Amount",
                "AttributeType": "N"
            },
            {
                "AttributeName": "CustomerId",
                "AttributeType": "S"
            },
            {
                "AttributeName": "OrderDate",
                "AttributeType": "S"
            }
        ],
        "TableName": "Orders",
        "KeySchema": [
            {
                "AttributeName": "CustomerId",
                "KeyType": "HASH"
            },
            {
                "AttributeName": "OrderDate",
                "KeyType": "RANGE"
            }
        ],
        "TableStatus": "ACTIVE",
        "CreationDateTime": "2024-12-28T15:10:33.344000+00:00",
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "ReadCapacityUnits": 0,
            "WriteCapacityUnits": 0
        },
        "TableSizeBytes": 0,
        "ItemCount": 0,
        "TableArn": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/Orders",
        "TableId": "324e6318-f1f7-4019-9ad6-248420c268d1",
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST",
            "LastUpdateToPayPerRequestDateTime": "2024-12-28T15:10:33.344000+00:00"
        },
        "LocalSecondaryIndexes": [
            {
                "IndexName": "AmountIndex",
                "KeySchema": [
                    {
                        "AttributeName": "CustomerId",
                        "KeyType": "HASH"
                    },
                    {
                        "AttributeName": "Amount",
                        "KeyType": "RANGE"
                    }
                ],
                "Projection": {
                    "ProjectionType": "ALL"
                },
                "IndexSizeBytes": 0,
                "ItemCount": 0,
                "IndexArn": "arn:aws:dynamodb:ap-northeast-1:xxxxxxxxxxxx:table/Orders/index/AmountIndex"
            }
        ],
        "DeletionProtectionEnabled": false,
        "WarmThroughput": {
            "ReadUnitsPerSecond": 12000,
            "WriteUnitsPerSecond": 4000,
            "Status": "ACTIVE"
        }
    }
}

GUIでも確認




2.サンプルデータ追加
※サンプルデータはこんな感じ

CustomerId OrderDate Amount Category
001 2023-12-01 150 Electronics
001 2023-12-02 300 Home
001 2023-12-03 1200 Electronics
002 2023-12-01 500 Fashion
002 2023-12-04 800 Electronics

2-1.CloudShellで下記を実行

$ aws dynamodb put-item \
    --table-name Orders \
    --item '{"CustomerId": {"S": "001"}, "OrderDate": {"S": "2023-12-01"}, "Amount": {"N": "150"}, "Category": {"S": "Electronics"}}'

$ aws dynamodb put-item \
    --table-name Orders \
    --item '{"CustomerId": {"S": "001"}, "OrderDate": {"S": "2023-12-02"}, "Amount": {"N": "300"}, "Category": {"S": "Home"}}'

$ aws dynamodb put-item \
    --table-name Orders \
    --item '{"CustomerId": {"S": "001"}, "OrderDate": {"S": "2023-12-03"}, "Amount": {"N": "1200"}, "Category": {"S": "Electronics"}}'

$ aws dynamodb put-item \
    --table-name Orders \
    --item '{"CustomerId": {"S": "002"}, "OrderDate": {"S": "2023-12-01"}, "Amount": {"N": "500"}, "Category": {"S": "Fashion"}}'

$ aws dynamodb put-item \
    --table-name Orders \
    --item '{"CustomerId": {"S": "002"}, "OrderDate": {"S": "2023-12-04"}, "Amount": {"N": "800"}, "Category": {"S": "Electronics"}}'

2-2.作成データ確認


3.クエリ実行
3-1.CloudShellで下記を実行
3-1-1.パーティションキーのみで検索

$ aws dynamodb query \
    --table-name Orders \
    --key-condition-expression "CustomerId = :customer_id" \
    --expression-attribute-values '{":customer_id": {"S": "001"}}' \
    --no-cli-pager
{
    "Items": [
        {
            "Amount": {
                "N": "150"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Electronics"
            },
            "OrderDate": {
                "S": "2023-12-01"
            }
        },
        {
            "Amount": {
                "N": "300"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Home"
            },
            "OrderDate": {
                "S": "2023-12-02"
            }
        },
        {
            "Amount": {
                "N": "1200"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Electronics"
            },
            "OrderDate": {
                "S": "2023-12-03"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}

3-1-2.パーティションキー+ソートキーで検索

$ aws dynamodb query \
    --table-name Orders \
    --key-condition-expression "CustomerId = :customer_id AND OrderDate >= :start_date" \
    --expression-attribute-values '{
        ":customer_id": {"S": "001"},
        ":start_date": {"S": "2023-12-02"}
    }'\
    --no-cli-pager
{
    "Items": [
        {
            "Amount": {
                "N": "300"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Home"
            },
            "OrderDate": {
                "S": "2023-12-02"
            }
        },
        {
            "Amount": {
                "N": "1200"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Electronics"
            },
            "OrderDate": {
                "S": "2023-12-03"
            }
        }
    ],
    "Count": 2,
    "ScannedCount": 2,
    "ConsumedCapacity": null
}

3-1-3.LSIで検索

$ aws dynamodb query \
    --table-name Orders \
    --index-name AmountIndex \
    --key-condition-expression "CustomerId = :customer_id" \
    --expression-attribute-values '{":customer_id": {"S": "001"}}'\
    --no-cli-pager
{
    "Items": [
        {
            "Amount": {
                "N": "150"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Electronics"
            },
            "OrderDate": {
                "S": "2023-12-01"
            }
        },
        {
            "Amount": {
                "N": "300"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Home"
            },
            "OrderDate": {
                "S": "2023-12-02"
            }
        },
        {
            "Amount": {
                "N": "1200"
            },
            "CustomerId": {
                "S": "001"
            },
            "Category": {
                "S": "Electronics"
            },
            "OrderDate": {
                "S": "2023-12-03"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}

3-1-4.GSIを作成

$ aws dynamodb update-table \
    --table-name Orders \
    --attribute-definitions \
        AttributeName=Category,AttributeType=S \
        AttributeName=Amount,AttributeType=N \
    --global-secondary-index-updates \
        "[
            {
                \"Create\": {
                    \"IndexName\": \"CategoryIndex\",
                    \"KeySchema\": [
                        {\"AttributeName\": \"Category\", \"KeyType\": \"HASH\"},
                        {\"AttributeName\": \"Amount\", \"KeyType\": \"RANGE\"}
                    ],
                    \"Projection\": {\"ProjectionType\": \"ALL\"}
                }
            }
        ]"

※グローバセカンダリインデックスが作成されたことを確認

3-1-5.GSIで検索

$ aws dynamodb query \
    --table-name Orders \
    --index-name CategoryIndex \
    --key-condition-expression "Category = :category" \
    --expression-attribute-values '{":category": {"S": "Electronics"}}'\
    --no-cli-pager
{
    "Items": [
        {
            "Amount": {
                "N": "150"
            },
            "CustomerId": {
                "S": "001"
            },
            "OrderDate": {
                "S": "2023-12-01"
            },
            "Category": {
                "S": "Electronics"
            }
        },
        {
            "Amount": {
                "N": "800"
            },
            "CustomerId": {
                "S": "002"
            },
            "OrderDate": {
                "S": "2023-12-04"
            },
            "Category": {
                "S": "Electronics"
            }
        },
        {
            "Amount": {
                "N": "1200"
            },
            "CustomerId": {
                "S": "001"
            },
            "OrderDate": {
                "S": "2023-12-03"
            },
            "Category": {
                "S": "Electronics"
            }
        }
    ],
    "Count": 3,
    "ScannedCount": 3,
    "ConsumedCapacity": null
}



感想

ちょっとDynamoさんと友達になれた!(´ω`)