Python'da DynamoDB Toplu Yazma (boto3 batch_writer)

batch_writer(), Python'ın diğer SDK'lardan daha az iş çıkardığı tek DynamoDB çağrısıdır. Put ve delete işlemlerini tamponlar, onları 25'lik BatchWriteItem isteklerine böler ve işlenmemiş öğeleri kendisi yeniden gönderir. Yapmadığı şey, çoğu toplu yüklemeyi bozan iki başarısızlıktan sizi korumaktır — ve ikisi de bozuk öğeyi veren satırda değil, boşaltma sırasında yüzeye çıkar.

Kod

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")

Açıklama

  • Ertelenmiş boşaltmabatch.put_item() bir listeye ekleme yapar. Tampon 25'e ulaşana ya da with bloğu bitene kadar hiçbir şey doğrulanmaz, serileştirilmez ya da gönderilmez; dolayısıyla bozuk bir öğenin traceback'i onu veren put_item çağrısından değil, boşaltmadan gelir. Bir yineleyiciden yüklüyorsanız, tampona neyin girdiğine dair kendi kaydınızı tutun.
  • Düz Python değerleri — bu kaynak API'sidir, dolayısıyla {"N": "1994"} değil 1994 yazarsınız. Kesirli her şey için Decimal gerekir; bir float tampona kabul edilir ve boşaltmada reddedilir.
  • batch_writer() bir Table metodudur. Okuma tarafındaki karşılığı değildir: batch_get_item, ServiceResource'ta bulunur ve table.batch_get_item diye bir şey yoktur. Toplu okumalar için hiç tamponlama, parçalama ya da yeniden deneme yardımcısı yoktur.
  • Hatalar değil, UnprocessedItems — ele aldığı tek yeniden deneme budur. Kısıtlanan bir yazma yeniden gönderilir; bir ValidationException yukarı yayılır. Bunun yerine client.batch_write_item üzerinden gitmek, Node.js örneğinde olduğu gibi bütün döngüyü size bırakır.
  • Hizmet sınırlarını kaldıramaz. İstek başına 25 yazma, öğe başına 400 KB, istek başına 16 MB, koşul yok ve güncelleme yok; her put saklanan öğenin tamamını değiştirir. Bir koruma ya da hep-ya-hiç mi gerekiyor? TransactWriteItems.

batch_writer boşaltmada gerçekte ne yapar

30 put tamponlayın ve yaptığı çağrıları izleyin. table.meta.client.batch_write_item'ı sarmalayıp istek boyutlarını kaydederek, DynamoDB Local 3.3.0'a karşı:

batch sizes sent: [25, 5]

İki istek, hizmet sınırında kesilmiş, artanı __exit__ tarafından boşaltılmış. O boşaltma koşulsuzdur: bloğun içinde bir RuntimeError fırlatın, tamponlanan öğeler çıkış yolunda yine de yazılır. Yarı yolda ölen bir toplu yükleme, temiz bir sayfa değil, kısmi bir yükleme bırakır.

Şimdi iki başarısızlık. Aynı anahtarı iki kez tamponlayın — kaynak verinizde bir tekrar olduğu anda olan da budur:

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 duplicates

Hiçbir put_item şikâyet etmedi. batch_writer(), siz istemedikçe yinelenenleri ayıklamaz; istemek de table.batch_writer(overwrite_by_pkeys=["Artist", "SongTitle"]) demektir. Aynı iki put'u ondan geçirin, öğe Year: 2 olarak saklanır — tampon anahtar başına son yazmayı tutar; dolayısıyla iki satırınız yanlış kurguladığınız bir anahtar altında farklı öğeler olacaktıysa bu ayıklama sessiz veri kaybıdır.

İkincisi yalnızca boto3'e aittir ve DynamoDB'ye hiç ulaşmaz:

TypeError: Float types are not supported. Use Decimal types instead.

4.5'lik bir Rating tamponda şikâyetsiz oturur ve boşaltmada patlar. Decimal("4.5"), {"N": "4.5"} olarak doğru gidip gelir. Bir fiyatı ya da puanı JSON'dan json.loads ile okuyun, her sayı bir float olur; dolayısıyla bu, çoğu içe aktarma betiği için daha ilk çalıştırmada gelen bir başarısızlıktır. json.loads'a parse_float=Decimal geçmek bunu kaynağında düzeltir.

Yerel Python değerleri ile tel biçimi arasında elle gidip geliyorsanız, DynamoDB JSON dönüştürücüsü aynı öğenin her iki tarafını gösterir; böylece Decimal'inizin gerçekte neye dönüştüğünü görebilirsiniz.

Tür eşlemesini kendiniz yazmadan CSV ya da JSON'dan toplu yükleme yapmak için DynoTable'ı indirin.

İlgili örnekler

Kaynaklar

En son 2026-07-28 tarihinde yukarıda bağlantısı verilen resmi AWS belgelerine karşı doğrulandı.

Console olmadan DynamoDB ile çalış

DynamoDB’nin çalıştıramadığı gerçek SQL’i çalıştıran hızlı bir DynamoDB masaüstü istemcisi — JOINs, GROUP BY, toplamalar — görsel düzenleme ve kendi Bedrock anahtarların üzerinde bir yapay zekâ aracısıyla.

30 günlük ücretsiz deneme, kredi kartı yok — ardından süre sınırı olmayan Ücretsiz plan.