LoginSignup
10
10

More than 5 years have passed since last update.

DynamoDBの基礎まとめ ― 書き込み(WCU)検証

Last updated at Posted at 2018-05-03

DynamoDBの基礎まとめ ― 料金体系とプロビジョニング
の続きとして、実際のWCUがどう発生するか検証したいと思います。

テーブルを作成

実際のSampleTableテーブルを作って、WCUを検証してみます。
image1.png
ユーザの購入履歴を想定するSampleTableを作成し、useridをPartition Key、updatedatetimeをSort Keyとします。Partition Key + Sort KeyでPrimary Keyを構成します。

サンプルデータを投入
image2.png

書き込み(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)

挿入結果
image11.png

パターン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)

更新結果
image21.png

パターン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)

挿入/更新結果
3-1
image31.png

3-2
image32.png

CloudWatchでWCUダッシュボートを作成

消費されたWCUを確認するには、CloudWatch -> Dashboards -> Create Dashboard -> Add metric graphで対象テーブルの
ConsumedWriteCapacityUnits
ProvisionedWriteCapacityUnits
グラフを作成します。

image.png

回数 消費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に比例する)に抑えるのがよく、プロビジョニングする際にも挿入・更新レコード数/秒で算出するので良いです。

10
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
10