はじめに

Lambda(Python)でDynamoDBを扱う」でDynamoDBの操作をある程度できるようになったが、大量のデータを扱う場合どうすればいいかを調べて、かなりハマってしまった。

AWS CLI のbatch-write-itemではダメ

AWSのDynamoDBのドキュメント「ステップ 2: データをテーブルにロードする」を参照にとりあえず登録をできるようにしてみた。

JSONデータのサンプルもダウンロードできるので、それを参考してJSONデータを作成。あとは、超簡単。JSONファイルを用意して、以下のコマンドを打ち込むだけの簡単なお仕事。


aws dynamodb batch-write-item --request-items file://xxx.json

・・・のはずだった。


An error occurred (ValidationException) when calling the BatchWriteItem operation: 1 validation error detected: Value 
〜 
at 'requestItems' failed to satisfy constraint: Map value must satisfy constraint: [Member must have length less than or equal to 25, Member must have length greater than or equal to 1]

上記のようなエラーがが出てだめだった。うーん。データがでかすぎ? ということで、件数を数件にして再度実行・・・登録された。

リファレンスを見てみよう。と、「batch-write-item -- AWS CLI 1.16.72 Command Reference」を参照


If one or more of the following is true, DynamoDB rejects the entire batch write operation:

・One or more tables specified in the BatchWriteItem request does not exist.
・Primary key attributes specified on an item in the request do not match those in the corresponding table's primary key schema.
・You try to perform multiple operations on the same item in the same BatchWriteItem request. ・For example, you cannot put and delete the same item in the same BatchWriteItem request.
・Your request contains at least two items with identical hash and range keys (which essentially is two put operations).
・There are more than 25 requests in the batch.
・Any individual item in a batch exceeds 400 KB.
・The total request size exceeds 16 MB.

バッチには25以上のリクエストはダメだって書いてある。ほかにもいろいろ。

ダメじゃん。てことは、別の方法考えないと・・・バッチ処理じゃないのかよ・・・

大量データはBoto 3のtable.batch_writer()で

AWS pipeline を用いてS3からデータを自動で置換入力するみたいな方法もあるみたいだけれども、いろいろと設定が面倒なのと、ただ大量にデータを設置したかっただけなので・・・なんかちがう・・・

で、悩みに悩んでたんだけども、「DynamoDB -- Boto 3 Docs 1.9.62 documentation」も見てみたら、大量に処理できるみたいなことを書いてある。

table.batch_writer() を使ってbatch.put_itemで一件ずつ入力していけば大量にできるらしい。以下はリファレンスの例


with table.batch_writer() as batch:
    batch.put_item(
        Item={
            'account_type': 'standard_user',
            'username': 'johndoe',
            'first_name': 'John',
            'last_name': 'Doe',
            'age': 25,
            'address': {
                'road': '1 Jefferson Street',
                'city': 'Los Angeles',
                'state': 'CA',
                'zipcode': 90001
            }
        }
    )
    batch.put_item(
        Item={
            'account_type': 'super_user',
            'username': 'janedoering',
            'first_name': 'Jane',
            'last_name': 'Doering',
            'age': 40,
            'address': {
                'road': '2 Washington Avenue',
                'city': 'Seattle',
                'state': 'WA',
                'zipcode': 98109
            }
        }
    )


ということなので、テストとしてプライマリーキーにid というのを設定しただけのdynamo db を作成し、1~9999のID番号の入っただけのJSONデータの処理を走らせてみた


import boto3
import json

def db_sample():
	dynamodb = boto3.resource('dynamodb')
	table = dynamodb.Table('テーブル名')
	with open("JSONファイルの場所") as json_file:
		serials = json.load(json_file)		
		with table.batch_writer() as batch:
			for se in serials:
				id = se['id']			
				batch.put_item(
					Item={
						'id': id
						}
					)

if __name__ == "__main__":
	db_sample()

時間はかかるが、データを入力を行えた。できたらなんてこともないことなんだけども・・・ね