DynamoDBの基礎まとめ ― 料金体系とプロビジョニング
の続きとして、実際のWCUがどう発生するか検証したいと思います。
##テーブルを作成
実際のSampleTableテーブルを作って、WCUを検証してみます。
ユーザの購入履歴を想定するSampleTableを作成し、useridをPartition Key、updatedatetimeをSort Keyとします。Partition Key + Sort KeyでPrimary Keyを構成します。
##書き込み(WCU)
まず書き込みのほうで、DynamoDBはデータを書き込むためのアクションを基本二つ用意しています。
テーブルへのデータの書き込みを参考
アクション | 説明 |
---|---|
PutItem | テーブルに単一項目を書き込みます(Primary Key指定必須)。 |
BatchWriteItem | 同時に複数の項目に書き込むアクション。 |
##PythonでLambda関数
###パターン1:新規レコード挿入
それぞれデータサイズ1KB以下と1KB越え2回実施
回数 | userid | updatedatetime | itemid | itemstatus |
---|---|---|---|---|
1回目 | U00001 | 2018-04-09 09:01:00 | IT006 | good |
2回目 | U00001 | 2018-04-09 09:02:00 | IT007 | 985バイトの長い文字列 |
import boto3
import logging
dynamoDB = boto3.resource("dynamodb")
table = dynamoDB.Table("SampleTable")
def lambda_handler(event, context):
try:
result = table.put_item(
Item={
"userid" : "U00001",
"updatedatetime" : "2018-04-09 09:01:00",
"itemid" : "IT006",
"itemnumber" : 10,
"itemprice" : 100,
"itemstatus" : "good"
}
)
print(result)
except Exception as e:
logging.error("type : %s", type(e))
logging.error(e)
###パターン2:項目値更新
更新対象行のデータサイズ1KB未満で更新後サイズ不変
更新対象行のデータサイズ1KB以上で更新後サイズが1KB未満
更新対象行のデータサイズ1KB未満で更新後サイズが1KB以上
3回実行
回数 | userid | updatedatetime | 更新項目 | 更新前 | 更新後 |
---|---|---|---|---|---|
1回目 | U00001 | 2018-04-09 09:01:00 | itemnumber | 10 | 11 |
2回目 | U00001 | 2018-04-09 09:01:00 | itemstatus | good | 985バイトの長い文字列 |
3回目 | U00001 | 2018-04-09 09:02:00 | itemstatus | 985バイトの長い文字列 | good |
import boto3
import logging
dynamoDB = boto3.resource("dynamodb")
table = dynamoDB.Table("SampleTable")
def lambda_handler(event, context):
try:
result = table.update_item(
Key={
"userid" : "U00001",
"updatedatetime" : "2018-04-09 09:01:00"
},
UpdateExpression="set itemnumber = :n",
ExpressionAttributeValues={
":n" : 11
}
)
print(result)
except Exception as e:
logging.error("type : %s", type(e))
logging.error(e)
###パターン3:複数の項目同時更新
DynamoDBは1行ずつの挿入と更新が基本ですので、SQLのように一括更新ができませんでした。
以下のコードを実行してみました。updateのKey条件にPartition Keyのみ指定しても、思うようにすべてのU00001のitemnumberが11になることになりません。
The provided key element does not match the schemaエラーが出ます。
type : <class 'botocore.exceptions.ClientError'>
[ERROR] 2018-05-02T13:16:47.583Z 10f0238f-4e0b-11e8-b306-09566ca178d3 type : <class 'botocore.exceptions.ClientError'>
[ERROR] 2018-05-02T13:16:47.619Z 10f0238f-4e0b-11e8-b306-09566ca178d3 An error occurred (ValidationException) when calling the UpdateItem operation: The provided key element does not match the schema
import boto3
import logging
dynamoDB = boto3.resource("dynamodb")
table = dynamoDB.Table("SampleTable")
def lambda_handler(event, context):
try:
result = table.update_item(
Key={
"userid" : "U00001",
},
UpdateExpression="set itemnumber = :n",
ExpressionAttributeValues={
":n" : 11
}
)
print(result)
except Exception as e:
logging.error("type : %s", type(e))
logging.error(e)
一括挿入/更新はBatchWriteItemアクションを使いますが、結果的に1行ずつの挿入と更新になります。
回数 | userid | updatedatetime | itemstatus | 処理 |
---|---|---|---|---|
1回目 | U00004 | インクリメント | good | 挿入 |
2回目 | U00004 | インクリメント | 985バイトの長い文字列 | 更新 |
import boto3
import logging
dynamoDB = boto3.resource("dynamodb")
table = dynamoDB.Table("SampleTable")
def lambda_handler(event, context):
try:
with table.batch_writer() as batch:
for i in range(5):
result = batch.put_item(
Item={
"userid" : "U00004",
"updatedatetime" : "2018-04-09 09:0" + str(i) + ":00",
"itemid" : "IT00" + str(i + 1),
"itemnumber" : i + 1,
"itemprice" : 100 * (i + 1),
"itemstatus" : "good"
}
)
print(i)
print(result)
except Exception as e:
logging.error("type : %s", type(e))
logging.error(e)
##CloudWatchでWCUダッシュボートを作成
消費されたWCUを確認するには、CloudWatch -> Dashboards -> Create Dashboard -> Add metric graphで対象テーブルの
ConsumedWriteCapacityUnits
ProvisionedWriteCapacityUnits
グラフを作成します。
回数 | 消費WCU | 説明 |
---|---|---|
1-1 | 1WCU | 1KB未満のデータサイズを挿入したため、1KBに切り上げし、1WCU消費 |
1-2 | 2WCU | 1KB以上のデータサイズを挿入したため、2KBに切り上げし、2WCU消費 |
2-1 | 1WCU | 1KB未満のデータサイズに対する更新、1KBに切り上げし、1WCU消費 |
2-2 | 2WCU | 1KB未満のデータサイズに対する更新だが、更新後1KB以上となるため、2KBに切り上げし、2WCU消費 |
2-3 | 2WCU | 1KB以上のデータサイズに対して更新だが、更新後1KB未満でも、1KB未満のデータサイズを5回挿入するが、1回ずつ1KBに切り上げ、合計5KBの5WCU消費更新量が1KB以上とみなし、2WCU消費 |
3-1 | 5WCU | 1KB未満のデータサイズを5回挿入するが、1回ずつ1KBに切り上げ、合計5KBの5WCU消費 |
3-1 | 10WCU | 1KB以上のデータサイズを5回更新するが、1回ずつ2KBに切り上げ、合計10KBの10WCU消費 |
##考察
DynamoDBのWCU計算の特徴から、1レコードのデータサイズを1KB未満(あるいはKBに比例する)に抑えるのがよく、プロビジョニングする際にも挿入・更新レコード数/秒で算出するので良いです。