0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

大量データをDynamodbのBatchWriterで書き込んでも3時間程かかった

Last updated at Posted at 2024-12-17

大量のデータをDynamoDBに書き込む際、PutItemでは日が暮れてしまう。
そんな時にBatchWriterを使用して書き込みたいところ。
ただ、先日BatchWriterで100万〜200万件のデータを書き込む必要があって、
業務端末上のスクリプトで実行したところ、ありえない時間がかかった。

弊スペック

  • インターネット回線
    • 種別:CATV
    • 下り:120MB(理論値)
    • 下り:5MB(理論値)
  • 業務端末
    • CPU:Apple M1 コア8
    • Memory:16GB
    • OS:macOS Monterey

結論

170万件のデータを20万件毎に分割し、20万件毎にBatchWriterで書き込んだところ、
3時間強かかった。
BatchWriterはPutItem、DeleteItemが対象であり、それ以外はBatchWriterで
扱う事ができない

BatchWriteItem cannot update items. If you perform a BatchWriteItem operation on an existing item, that item's values will be overwritten by the operation and it will appear like it was updated. To update items, we recommend you use the UpdateItem action.
上記引用では、BatchWriteItemのAPIに触れているが、BatchWriterはBatchWriteItemをWrapして使用しているので、同じと考えて差し障りない。

サンプルコード

ダミーCSV

data.csv
user_id,date,segment,total_buys
1,2024-12-18,high,80
2,2024-12-18,low,12
3,2024-12-18,middle,67
4,2024-12-18,middle,35
5,2024-12-18,middle,45
6,2024-12-18,low,10
7,2024-12-18,high,85
8,2024-12-18,middle,30
9,2024-12-18,low,5
10,2024-12-18,high,90
11,2024-12-18,middle,50
12,2024-12-18,low,15
13,2024-12-18,high,95
14,2024-12-18,middle,40
15,2024-12-18,low,18
16,2024-12-18,high,100
17,2024-12-18,middle,60
18,2024-12-18,low,8
19,2024-12-18,high,88
20,2024-12-18,middle,70

ダミーsample.py
※実際のコードはこのようになっておりません。

sample.py
import boto3
import pandas as pd

dynamodb = boto3.resource('dynamodb')
data = pd.read_csv('data.csv')

user_table = dynamodb.Table('User')
user_buy_history_log_table = dynamodb.Table('UserBuyHistoryLog')

for index, row in data.iterrows():
    with user_buy_history_log_table.batch_writer(
        overwrite_by_pkeys=['user_id', 'date']
    ) as batch:
        # PutItem
        batch.put_item(Item={
            'user_id': int(row['user_id']),
            'date': row['date'],
            'total_buys': int(row['total_buys']),
        })

        # BatchWriterのスコープ内でUpdateItemをやってはいるが...
        user_table.update_item(
            Key={
                'id': int(row['user_id']),
            },
            UpdateExpression='SET #attr = :val',
            ExpressionAttributeNames={
                '#attr': 'segment',
            },
            ExpressionAttributeValues={
                ':val': row['segment'],
            },
        )

スクリプト実行後、どうして時間かかった?

BatchWriterにより1操作で最大25項目の追加または削除操作を含むデータサイズにして、
16MBまで可能との事。
連続したPutItem時よりも低いWCU消費で済むことができ、かつ時間が短縮されると考えていたが、3時間かかるのはおかしい結果となった。

BatchWriterを使用したUserBuyHistoryLogテーブルでは
PutItem使用してバルク処理になってたが、UserテーブルのUpdateItemは1件ずつ処理していた事で
それに引っ張られて本来のBatchWriterの恩恵を受けられなかった。

速く終わらせるには、どうすべきか

  1. 業務端末でやらない。AWSにEC2やECS/EKSのコンテナ上でバッチ処理実行
    ※ 設計次第ではLambdaを使用して並列に書き込むのもアリ。
  2. BatchWriterからUser更新に使っていたUpdateItemをスコープから外す
  3. スレットを導入し、並列に実行させる

まとめ

BatchWriterはPutItem、DeleteItemが対応しているが、それ以外は対応していない
BatchWriterはBatchWriteItemをWrapしたもの
業務端末で重たい処理は走らせず、AWS上でバッチサーバを置いて処理させるべき

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?