

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Bewährte Methoden für die Verwendung von Massendatenoperationen in DynamoDB
<a name="BestPractices_BulkDataOperations"></a>

DynamoDB unterstützt Massenoperationen wie `BatchWriteItem`, mit denen Sie bis zu 25 `PutItem`- und `DeleteItem`-Anforderungen zusammen ausführen können. `BatchWriteItem` unterstützt jedoch keine `UpdateItem`-Operationen. Bei Massenaktualisierungen liegt der Unterschied in den Anforderungen und der Art der Aktualisierung. Sie können andere DynamoDB verwenden, APIs z. B. `TransactWriteItems` für Batchgrößen von bis zu 100. Wenn mehr Elemente betroffen sind, können Sie Dienste wie AWS Glue Amazon EMR AWS Step Functions oder benutzerdefinierte Skripts und Tools wie DynamoDB-Shell für Massenaktualisierungen verwenden.

**Topics**
+ [Bedingte Massenaktualisierung](BestPractices_ConditionalBatchUpdate.md)
+ [Effiziente Massenoperationen](BestPractices_EfficientBulkOperations.md)

# Bedingte Massenaktualisierung
<a name="BestPractices_ConditionalBatchUpdate"></a>

DynamoDB unterstützt Massenoperationen wie `BatchWriteItem`, mit denen Sie bis zu 25 `PutItem`- und `DeleteItem`-Anforderungen in einem einzigen Batch ausführen können. `BatchWriteItem` unterstützt jedoch keine `UpdateItem`-Operationen und Bedingungsausdrücke. Um das Problem zu umgehen, können Sie andere DynamoDB verwenden, APIs z. B. `TransactWriteItems` für Batchgrößen von bis zu 100.

Wenn mehr Elemente betroffen sind und ein großer Teil der Daten geändert werden muss, können Sie Dienste wie Amazon EMR AWS Step Functions oder benutzerdefinierte Skripts und Tools wie DynamoDB-Shell für effiziente Massenaktualisierungen verwenden. AWS Glue

**Wann dieses Muster verwendet werden sollte**
+ DynamoDB-Shell ist kein Anwendungsfall, der für die Produktion unterstützt wird.
+ `TransactWriteItems` – bis zu 100 einzelne Updates mit oder ohne Bedingungen, die als ACID nach dem „alles oder nichts“-Prinzip gebündelt ausgeführt werden. `TransactWriteItems`-Aufrufe können auch mit einem `ClientRequestToken` versehen werden, falls Ihre Anwendung Idempotenz benötigt, was bedeutet, dass mehrere identische Aufrufe dieselbe Wirkung haben wie ein einziger Aufruf. Dadurch wird sichergestellt, dass Sie dieselbe Transaktion nicht mehrmals ausführen und am Ende einen falschen Datenstatus erhalten.

  Kompromiss — Es wird zusätzlicher Durchsatz verbraucht. 2 WCUs pro 1 KB Schreibvorgang anstelle der standardmäßigen 1 WGU pro 1 KB Schreibvorgang.
+ PartiQL `BatchExecuteStatement` – bis zu 25 Updates mit oder ohne Bedingungen. `BatchExecuteStatement` gibt immer eine erfolgreiche Antwort auf die gesamte Anforderung sowie eine Liste der Antworten auf einzelne Operationen zurück, wobei die Reihenfolge gewahrt bleibt.

  Kompromiss – Bei größeren Batches ist zusätzliche Client-seitige Logik erforderlich, um Anforderungen in Batches von 25 zu verteilen. Bei der Festlegung der Wiederholungsstrategie müssen individuelle Fehlerantworten berücksichtigt werden.

## Codebeispiele
<a name="bp-conditional-code-examples"></a>

Diese Codebeispiele verwenden die boto3-Bibliothek, das AWS SDK für Python. In diesen Beispielen wird vorausgesetzt, dass Sie boto3 installiert und mit den entsprechenden AWS -Anmeldeinformationen konfiguriert haben.

Gehen wir von einer Inventardatenbank für einen Elektrogerätehändler aus, der über mehrere Lager in europäischen Städten verfügt. Da es Ende des Sommers ist, möchte der Verkäufer die Tischventilatoren ausräumen, um Platz für andere Lagerbestände zu schaffen. Der Verkäufer möchte einen Preisnachlass für alle Tischventilatoren gewähren, die aus Lagern in Italien geliefert werden, aber nur, wenn ein Vorratsbestand von 20 Tischventilatoren vorhanden ist. Die DynamoDB-Tabelle heißt **inventory**. Sie hat ein Schlüsselschema mit Partitionsschlüssel **sku**, einer eindeutigen Kennung für jedes Produkt, und einen Sortierschlüssel **warehouse**, der eine Kennung für ein Lager ist.

Der folgende Python-Code zeigt, wie diese bedingte Massenaktualisierung mithilfe eines `BatchExecuteStatement`-API-Aufrufs durchgeführt wird.

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.batch_execute_statement(
        Statements=[
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITTUR1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITROM5'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN1'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN2'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
            {'Statement': 'UPDATE inventory SET price=price-5 WHERE sku=? AND warehouse=? AND quantity > 20', 'Parameters': [{'S':'F123'}, {'S':'WITVEN3'}], 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

Die Ausführung erzeugt die folgende Ausgabe für Beispieldaten:

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '40'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '33'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '35'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '38'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '30'}, 'sku': {'S': 'F123'}}]
```

Da es sich um eine begrenzte Operation für ein internes System handelt, wurden die Anforderungen an die Idempotenz nicht berücksichtigt. Es ist möglich, einen zusätzlichen Integritätsschutz festzulegen, z. B. dass Preisaktualisierungen nur dann durchgeführt werden sollten, wenn der Preis höher als 35 und weniger als 40 ist, damit die Aktualisierungen robuster sind.

Alternativ können wir dieselbe Massenaktualisierung auch mit `TransactWriteItems` durchführen, falls strengere Anforderungen an Idempotenz und ACID gelten. Es ist jedoch wichtig, daran zu denken, dass entweder alle Operationen im Transaktionspaket ausgeführt werden oder das gesamte Paket fehlschlägt.

Nehmen wir an, dann aufgrund einer Hitzewelle in Italien die Nachfrage nach Tischventilatoren stark gestiegen ist. Der Verkäufer möchte seine Kosten für Schreibtischventilatoren beim Versand aus jedem Lager in Italien um 20 Euro erhöhen, aber die Aufsichtsbehörde erlaubt diese Kostenerhöhung nur, wenn die aktuellen Kosten für den gesamten Lagerbestand unter 70 Euro liegen. Es ist wichtig, dass der Preis im gesamten Inventar nur ein einziges Mal aktualisiert wird und nur dann, wenn die Kosten in jedem Lager weniger als 70 Euro betragen.

Der folgende Python-Code zeigt, wie diese Massenaktualisierung mithilfe eines `TransactWriteItems`-API-Aufrufs durchgeführt wird.

```
import boto3

client=boto3.client("dynamodb")

before_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("Before update: ", before_image['Items'])

response=client.transact_write_items(
        ClientRequestToken='UUIDAWS124',
        TransactItems=[
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITTUR1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITROM5'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN1'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN2'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
            {'Update': { 'Key': {'sku': {'S':'F123'}, 'warehouse': {'S':'WITVEN3'}}, 'UpdateExpression': 'SET price = price + :inc', 'ConditionExpression': 'price < :cap', 'ExpressionAttributeValues': { ':inc': {'N': '20'}, ':cap': {'N': '70'}}, 'TableName': 'inventory', 'ReturnValuesOnConditionCheckFailure': 'ALL_OLD'}},
        ],
        ReturnConsumedCapacity='TOTAL'
    )

after_image=client.query(TableName='inventory', KeyConditionExpression='sku=:pk_val AND begins_with(warehouse, :sk_val)', ExpressionAttributeValues={':pk_val':{'S':'F123'},':sk_val':{'S':'WIT'}}, ProjectionExpression='sku,warehouse,quantity,price')
print("After update: ", after_image['Items'])
```

Die Ausführung erzeugt die folgende Ausgabe für Beispieldaten:

```
Before update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '60'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '53'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '55'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '58'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '50'}, 'sku': {'S': 'F123'}}]
After update:  [{'quantity': {'N': '20'}, 'warehouse': {'S': 'WITROM1'}, 'price': {'N': '80'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '25'}, 'warehouse': {'S': 'WITROM2'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '28'}, 'warehouse': {'S': 'WITROM5'}, 'price': {'N': '73'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '26'}, 'warehouse': {'S': 'WITTUR1'}, 'price': {'N': '75'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '10'}, 'warehouse': {'S': 'WITVEN1'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '20'}, 'warehouse': {'S': 'WITVEN2'}, 'price': {'N': '78'}, 'sku': {'S': 'F123'}}, {'quantity': {'N': '50'}, 'warehouse': {'S': 'WITVEN3'}, 'price': {'N': '70'}, 'sku': {'S': 'F123'}}]
```

Es gibt mehrere Ansätze für die Durchführung von Massenaktualisierungen in DynamoDB. Der geeignete Ansatz hängt von Faktoren wie den Anforderungen an die and/or ACID-Idempotenz, der Anzahl der zu aktualisierenden Elemente und der Vertrautheit mit ihnen ab. APIs

# Effiziente Massenoperationen
<a name="BestPractices_EfficientBulkOperations"></a>

**Wann dieses Muster verwendet werden sollte**

Diese Muster sind nützlich, um Massenaktualisierungen für DynamoDB-Elemente effizient durchzuführen.
+ DynamoDB-Shell ist kein Anwendungsfall, der für die Produktion unterstützt wird.
+ `TransactWriteItems` – bis zu 100 einzelne Updates mit oder ohne Bedingungen, die als Alles-oder-Nichts-ACID-Paket ausgeführt werden. 

  Kompromiss — Es wird zusätzlicher Durchsatz verbraucht, 2 WCUs pro 1 KB Schreibvorgang.
+ PartiQL `BatchExecuteStatement` – bis zu 25 Updates mit oder ohne Bedingungen.

  Kompromiss – Es ist eine zusätzliche Logik erforderlich, um Anforderungen in Batches von 25 zu verteilen.
+ AWS Step Functions — Massenoperationen mit begrenzter Geschwindigkeit für Entwickler, die damit vertraut sind. AWS Lambda

  Kompromiss – Die Ausführungszeit ist umgekehrt proportional zur Ratenbegrenzung. Limitiert durch das maximale Timeout der Lambda-Funktion. Die Funktionalität beinhaltet, dass Datenänderungen, die zwischen dem Lesen und dem Schreiben auftreten, überschrieben werden können. Weitere Informationen finden Sie unter [Backfilling an Amazon DynamoDB Time to Live attribute using Amazon EMR: Part 2](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/).
+ AWS Glue und Amazon EMR — ratenbegrenzter Massenbetrieb mit verwalteter Parallelität. Bei Anwendungen oder Updates, die nicht zeitkritisch sind, können diese Optionen im Hintergrund ausgeführt werden und verbrauchen dann nur einen kleinen Prozentsatz des Durchsatzes. Beide Dienste verwenden die emr-dynamodb-connector, um DynamoDB-Operationen auszuführen. Diese Services führen einen umfangreichen Lesevorgang aus, gefolgt von einem umfangreichen Schreibvorgang bei aktualisierten Elementen mit einer Option zur Ratenbegrenzung.

  Kompromiss – Die Ausführungszeit ist umgekehrt proportional zur Ratenbegrenzung. Die Funktionalität beinhaltet, dass Datenänderungen, die zwischen dem Lesen und dem Schreiben auftreten, überschrieben werden können. Sie können nicht aus globalen sekundären Indizes () lesen. GSIs Weitere Informationen finden Sie unter [Backfilling an Amazon DynamoDB Time to Live attribute using Amazon EMR: Part 2](https://aws.amazon.com/blogs/database/part-2-backfilling-an-amazon-dynamodb-time-to-live-attribute-using-amazon-emr/).
+ DynamoDB-Shell – Massenoperationen mit Ratenbegrenzung und SQL-ähnlichen Abfragen. Sie können aus Effizienzgründen GSIs daraus lesen.

  Kompromiss – Die Ausführungszeit ist umgekehrt proportional zur Ratenbegrenzung. Weitere Informationen finden Sie unter [Rate limited bulk operations in DynamoDB Shell](https://aws.amazon.com/blogs/database/rate-limited-bulk-operations-in-dynamodb-shell/).

## Verwenden des Musters
<a name="BestPractices_EfficientBulkOperations_UsingThePattern"></a>

Massenaktualisierungen können erhebliche Auswirkungen auf die Kosten haben, insbesondere wenn Sie den On-Demand-Durchsatzmodus verwenden. Es gibt einen Kompromiss zwischen Geschwindigkeit und Kosten, wenn Sie den Modus mit bereitgestelltem Durchsatz verwenden. Ein sehr strikt festgelegter rate-limit-Parameter kann zu einer sehr langen Verarbeitungszeit führen. Sie können die Geschwindigkeit der Aktualisierung anhand der durchschnittlichen Elementgröße und der Ratenbegrenzung grob bestimmen.

Alternativ können Sie anhand der erwarteten Dauer des Aktualisierungsvorgangs und der durchschnittlichen Elementgröße den für den Vorgang erforderlichen Durchsatz ermitteln. Die zu den einzelnen Mustern gehörenden Blog-Referenzen enthalten Einzelheiten zur Strategie, der Implementierung und den Einschränkungen bei der Verwendung des Musters. Weitere Informationen finden Sie unter [Cost-effective bulk processing with Amazon DynamoDB](https://aws.amazon.com/blogs/database/cost-effective-bulk-processing-with-amazon-dynamodb/).

Es gibt mehrere Möglichkeiten, Massenaktualisierungen für eine dynamische DynamoDB-Tabelle durchzuführen. Welcher Ansatz am besten geeignet ist, hängt von Faktoren wie den Anforderungen an die and/or ACID-Idempotenz, der Anzahl der zu aktualisierenden Punkte und der Vertrautheit ab. APIs Es ist wichtig, den Kompromiss zwischen Kosten und Zeit zu berücksichtigen. Die meisten der oben erläuterten Ansätze bieten eine Option zur Ratenbegrenzung des Durchsatzes, der von der Massenaktualisierung verwendet wird.