【AWS】DynamoDBのキーについて調べてみた
知ってるようでよく覚えていないDynamoDBについて調べてみた。
DynamoDB要素
パーティションキー:
テーブル作成時に必須。ハッシュキーとも言われる。アイテムを一位に識別し、パーティションを決定するキー。ソートキーがない場合はパーティションキーで重複があってはいけない。ソートキーがある場合は、パーティションキー+ソートキーで重複があってはいけない。
ソートキー:
テーブル作成時は必須ではないが、あとから追加できない。パーティションキーと組み合わせてアイテムを一意に識別するための2つ目のキー。
ローカルセカンダリインデックス(LSI):
テーブル作成時は必須ではないが、あとから追加できない。2つ目のソートキーとして使用する。
グローバルセカンダリインデックス(GSI):
後から追加可能。テーブルのキー構造とは異なるパーティション・ソートキーでアイテムを検索可能。
後からソートキーやLSIを追加したい場合
テーブルを作り直しするか、GSIを使用する。
やること
サンプルのDynamoDBテーブルを作成し、パーティションキー、ソートキー、LSI、GSIで検索をする。
実践!
1.サンプルテーブル作成
※テーブル構造はこんな感じ
- パーティションキー (Partition Key):
CustomerId - ソートキー (Sort Key):
OrderDate
| 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さんと友達になれた!(´ω`)