DynamoDB Batch Write di Python (boto3 batch_writer)
batch_writer() adalah satu-satunya panggilan DynamoDB yang di Python justru lebih ringan daripada di SDK lain. Ia menyangga put dan delete, memotongnya menjadi request BatchWriteItem berisi 25, dan mengirim ulang sendiri item yang belum diproses. Yang tidak ia lakukan adalah melindungi Anda dari dua kegagalan yang merusak sebagian besar bulk load, dan keduanya muncul saat flush, bukan pada baris yang menyuplai item bermasalah itu.
Kode
import boto3
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("Music")
songs = [
{"Artist": "Arturo Sandoval", "SongTitle": "Cubano Chant", "AlbumTitle": "Danzon", "Year": 1994},
{"Artist": "Arturo Sandoval", "SongTitle": "A Mis Abuelos", "AlbumTitle": "Danzon", "Year": 1994},
{"Artist": "Arturo Sandoval", "SongTitle": "Groovin' High", "AlbumTitle": "Swingin'", "Year": 1996},
]
with table.batch_writer() as batch:
for song in songs:
batch.put_item(Item=song)
# batch_writer buffers deletes too — target a key you're NOT also putting
# (two writes to the same key in one batch are rejected as a duplicate)
batch.delete_item(Key={"Artist": "Ella Fitzgerald", "SongTitle": "Misty"})
print(f"Buffered {len(songs)} puts + 1 delete; the batch flushes on exit")Penjelasan
- Flush yang ditunda —
batch.put_item()menambahkan ke sebuah list. Tidak ada yang divalidasi, diserialisasi, atau dikirim sampai buffer mencapai 25 atau blokwithberakhir, jadi traceback untuk item bermasalah datang dari flush, bukan dari panggilanput_itemyang menyuplainya. Kalau Anda memuat dari sebuah iterator, simpan sendiri catatan apa saja yang masuk ke buffer. - Nilai Python biasa — ini API resource, jadi Anda menulis
1994, bukan{"N": "1994"}. Decimal wajib untuk apa pun yang pecahan; sebuahfloatditerima masuk ke buffer dan ditolak saat flush. batch_writer()adalah methodTable. Padanannya di sisi baca tidak:batch_get_itemberada diServiceResource, dantable.batch_get_itemtidak ada. Sama sekali tidak ada helper buffering, pemotongan, atau percobaan ulang untuk pembacaan batch.UnprocessedItems, bukan error — hanya itu percobaan ulang yang ia tangani. Tulis yang di-throttle dikirim ulang; sebuahValidationExceptionditeruskan. Lewatclient.batch_write_itemsebagai gantinya menyerahkan seluruh loop itu kepada Anda, seperti pada contoh Node.js.- Ia tidak bisa mengangkat batas layanan. 25 tulis per request, 400 KB per item, 16 MB per request, tanpa kondisi dan tanpa update, dan setiap put mengganti seluruh item yang tersimpan. Butuh pengaman, atau semua-atau-tidak-sama-sekali? TransactWriteItems.
Apa yang sebenarnya dilakukan batch_writer saat flush
Sangga 30 put dan perhatikan panggilan yang ia lakukan. Dengan membungkus table.meta.client.batch_write_item dan merekam ukuran request, terhadap DynamoDB Local 3.3.0:
batch sizes sent: [25, 5]Dua request, dipotong tepat di batas layanan, dengan sisanya di-flush oleh __exit__. Flush itu tanpa syarat: lempar sebuah RuntimeError di dalam blok dan item yang tersangga tetap ditulis dalam perjalanan keluar. Bulk load yang mati di tengah jalan meninggalkan muatan separuh jadi, bukan meja bersih.
Sekarang dua kegagalan itu. Sangga key yang sama dua kali, yang terjadi begitu data sumber Anda punya duplikat:
with table.batch_writer() as batch:
batch.put_item(Item={"Artist": "Dup", "SongTitle": "Key", "Year": 1})
batch.put_item(Item={"Artist": "Dup", "SongTitle": "Key", "Year": 2})botocore.exceptions.ClientError: An error occurred (ValidationException) when calling the
BatchWriteItem operation: Provided list of item keys contains duplicatesTak satu pun put_item protes. batch_writer() tidak melakukan deduplikasi kecuali Anda memintanya, dan memintanya berarti table.batch_writer(overwrite_by_pkeys=["Artist", "SongTitle"]). Jalankan dua put yang sama lewat itu dan item tersimpan sebagai Year: 2 — buffer menyimpan tulis terakhir per key, jadi deduplikasi itu adalah kehilangan data secara diam-diam kalau dua baris Anda sebenarnya dimaksudkan sebagai item berbeda di bawah key yang keliru Anda tetapkan.
Yang kedua murni milik boto3 dan tidak pernah sampai ke DynamoDB:
TypeError: Float types are not supported. Use Decimal types instead.Sebuah Rating bernilai 4.5 duduk di buffer tanpa keluhan lalu meledak saat flush. Decimal("4.5") bolak-balik dengan benar sebagai {"N": "4.5"}. Baca harga atau rating dari JSON dengan json.loads dan setiap angka menjadi float, jadi ini kegagalan pada percobaan pertama untuk sebagian besar skrip impor. Memberikan parse_float=Decimal ke json.loads memperbaikinya di sumbernya.
Kalau Anda berpindah antara nilai Python native dan format wire secara manual, konverter DynamoDB JSON menampilkan kedua sisi dari item yang sama sehingga Anda bisa melihat Decimal Anda sebenarnya menjadi apa.
Untuk melakukan bulk load dari CSV atau JSON tanpa menulis sendiri pemetaan tipenya, unduh DynoTable.
Contoh terkait
- DynamoDB BatchWriteItem di Node.js — loop percobaan ulang manual yang disembunyikan batch_writer.
- DynamoDB BatchWriteItem dengan AWS CLI — batch write yang sama dari shell.
- DynamoDB PutItem di Python — tulis satu item yang di-batch di sini.
- Operasi batch di DynamoDB — batas, kegagalan parsial, dan kapan batching membayar dirinya sendiri.
- "Too many items requested for the BatchWriteItem call" — lebih dari 25 request put/delete dalam satu batch.
- "Provided list of item keys contains duplicates" — dua request menyentuh key yang sama dalam satu batch.
Referensi
- Amazon DynamoDB guide (batch_writer) — Boto3 documentation
- BatchWriteItem — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Terakhir diverifikasi 2026-07-28 terhadap dokumentasi resmi AWS yang ditautkan di atas.