こんばんは。先日DynamoDBを使用していて制限にひっかりましたので、備忘録として残しておきます。
公式ページ DynamoDB での制限
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Limits.html
参考にしたURL:
https://inokara.hateblo.jp/entry/2017/12/01/091105
事象
DynamoDBのテーブルからデータを取得してCSVを返すといった処理でした。
AWSコンソールからデータを確認すると該当データは1600件あるが、実際Lambda関数から取得してみると900件程度しか取得できない。
そういや、DynamoDBって制限あったよねと思い出し、上のURLを参考にしてLambda関数を修正すると1600件取得できるようになりました。
めでたし、めでたし。で終わってしまうとあれなので実際に確かめてみます。
検証
まずはテストデータを作成します。
連番と日本語が525文字の項目を2000件テーブルに登録します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import json, os import boto3 TABLE_NAME = "TESTLIMIT" WORD = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめも" def lambda_handler(event, context): db = boto3.resource("dynamodb") table = db.Table(TABLE_NAME) for i in range(1,2001): table.put_item( Item = { "ID":str(i), "WORD":WORD } ) return { 'statusCode': 200, 'body': json.dumps('Hello from Lambda!') } |
全件データを取得してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import json, os import boto3 TABLE_NAME = "TESTLIMIT" def lambda_handler(event, context): db = boto3.resource("dynamodb") table = db.Table(TABLE_NAME) res = table.scan() items = res["Items"] count = len(items) return { 'statusCode': 200, 'body': json.dumps(count) } |
実行すると654件しか取得できませんでした。
テーブルスキャンの結果をdumpさせてみると
1 2 3 4 5 6 |
{ "statusCode": 200, "body": "{\"Items\": [{\"ID\": \"228\", \"WORD\": (略) \"Count\": 654, \"ScannedCount\": 654, \"LastEvaluatedKey\": {\"ID\": \"427\"}, \"ResponseMetadata\": {\"RequestId\": \"79V2TJ2UC3L78OK6870CKI1O93VV4KQNSO5AEMVJF66Q9ASUAAJG\", \"HTTPStatusCode\": 200, \"HTTPHeaders\": {\"server\": \"Server\", \"date\": \"Sat, 30 Mar 2019 13:08:36 GMT\", \"content-type\": \"application/x-amz-json-1.0\", \"content-length\": \"1053322\", \"connection\": \"keep-alive\", \"x-amzn-requestid\": \"79V2TJ2UC3L78OK6870CKI1O93VV4KQNSO5AEMVJF66Q9ASUAAJG\", \"x-amz-crc32\": \"1952349486\"}, \"RetryAttempts\": 0}}" } |
ありました「LastEvaluatedKey」ID:427まで取得できているようですね。(※IDを文字列にしたので数字順に取得できているわけでない)
コードを修正します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
import json, os import boto3 TABLE_NAME = "TESTLIMIT" def lambda_handler(event, context): db = boto3.resource("dynamodb") table = db.Table(TABLE_NAME) res = table.scan() items = res["Items"] print(len(items)) while "LastEvaluatedKey" in res: res = table.scan(ExclusiveStartKey=res["LastEvaluatedKey"]) items.extend(res["Items"]) print(len(items)) count = len(items) return { 'statusCode': 200, 'body': json.dumps(count) } |
実行結果はこちら。
ログを確認してみると654件ずつ取得しています。
おわりに
本日はDynamoDBのScanの1MB制限について実際のデータを用いて確認しました。AWSは便利なのですが、こういった制限が結構あるかと思います。制限にはかからないだろうとタカをくくらず、制限にかかって大丈夫なプログラムを書くように心がけたいものです。