結論
batch_writer() を使うべき。
理由:batch_writer() は batch_write_item() をwrapして便利に使えるようにしているものだから。
batch_write_item()
DynamoDBテーブルに対してアイテムを削除するboto3のAPIとして、delete_itemやput_itemがありますが、複数アイテムを削除しようとすると都度APIをコールするのでパフォーマンスがよくありません。※1
そこで、batch_write_item()を使って一括で削除・追加処理を実施できるのですが、以下のデメリットがあります。
- 1回のリクエストで処理できるのは25個ずつ
- 追加(削除)に失敗したアイテムに対するハンドリングは独自実装する必要がある
batch_writer()
batch_writer()はbatch_write_item()のデメリットを解消(内部で処理)してくれています。くわしくはクラスメソッドさんのこちらの記事がわかりやすいです。
自分は当初、delete_item()やput_item()を内部的に呼び出しているのだと勝手に思っていましたが、実装を確認するとbatch_write_item()を呼び出していました。
# https://github.com/boto/boto3/blob/develop/boto3/dynamodb/table.py#L63
class BatchWriter:
"""Automatically handle batch writes to DynamoDB for a single table."""
def __init__(
self, table_name, client, flush_amount=25, overwrite_by_pkeys=None
):
略
# https://github.com/boto/boto3/blob/develop/boto3/dynamodb/table.py#L141
def _flush(self):
items_to_send = self._items_buffer[: self._flush_amount]
self._items_buffer = self._items_buffer[self._flush_amount :]
response = self._client.batch_write_item(
RequestItems={self._table_name: items_to_send}
)
unprocessed_items = response['UnprocessedItems']
if not unprocessed_items:
unprocessed_items = {}
略
参考
- ※1: クラスメソッドさんの検証記事より
RCUとWCUが1に指定されているテーブルでデータ削除の検証をしてみたところ、100件の削除に10秒程度、1000件の削除に12分弱かかりました。数千レコード程度のオーダーであれば大丈夫そうですね(ちなみにDeleteItemバージョンでは100件の削除に1分30秒ほどかかっていました)