DynamoDB의 기본 요약 - 쓰기 (WCU) 검증

DynamoDB의 기본 요약 - 요금 체계 및 프로비저닝
계속해서 실제 WCU가 어떻게 발생하는지 검증하고 싶습니다.

테이블 만들기



실제 SampleTable 테이블을 만들어 WCU를 확인해 봅니다.

사용자의 구매 내역을 가정하는 SampleTable을 만들고 userid를 Partition Key로, updatedatetime을 Sort Key로 설정합니다. Partition Key + Sort Key로 Primary Key를 구성합니다.

샘플 데이터 입력


쓰기(WCU)



먼저 쓰기 쪽으로 DynamoDB는 데이터를 쓰기 위한 액션을 기본 두 가지 준비하고 있습니다.
테이블에 데이터 쓰기 참고


액션
설명


PutItem
테이블에 단일 항목을 씁니다(Primary Key 지정 필수).

BatchWriteItem
동시에 여러 항목에 쓰는 작업.


파이썬에서 람다 함수



패턴 1: 새 레코드 삽입



각각 데이터 사이즈 1KB 이하와 1KB 초과 2회 실시


횟수
userid
updatedatetime
itemid
itemstatus


첫 번째
U00001
2018-04-09 09:01:00
IT006
좋은

두 번째
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 이상
세 번 실행


횟수
userid
updatedatetime
업데이트 항목
업데이트 전
업데이트 후


첫 번째
U00001
2018-04-09 09:01:00
itemnumber
10
11

두 번째
U00001
2018-04-09 09:01:00
itemstatus
좋은
985바이트의 긴 문자열

세 번째
U00001
2018-04-09 09:02:00
itemstatus
985바이트의 긴 문자열
좋은

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 작업을 사용하지만 결과적으로 한 줄씩 삽입 및 업데이트됩니다.


횟수
userid
updatedatetime
itemstatus
처리


첫 번째
U00004
증분
좋은
삽입

두 번째
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


3-2


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에 비례한다)으로 억제하는 것이 좋고, 프로비저닝할 때에도 삽입·갱신 레코드수/초로 산출하기 때문에 좋다.

좋은 웹페이지 즐겨찾기