

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.

# Arbeiten mit Tabellen, Elementen, Abfragen, Scans und Indizes
<a name="WorkingWithDynamo"></a>

Dieser Abschnitt enthält Details zum Arbeiten mit Tabellen, Elementen, Abfragen und mehr in Amazon DynamoDB.

**Topics**
+ [Arbeiten mit Tabellen und Daten in DynamoDB](WorkingWithTables.md)
+ [Globale Tabellen: multiaktive, regionsübergreifende Replikation](GlobalTables.md)
+ [Arbeiten mit Elementen und Attributen in DynamoDB](WorkingWithItems.md)
+ [Verbessern des Datenzugriffs mit sekundären Indizes in DynamoDB](SecondaryIndexes.md)
+ [Verwalten komplexer Workflows mit DynamoDB-Transaktionen](transactions.md)
+ [Ändern der Datenerfassung mit Amazon DynamoDB](streamsmain.md)

# Arbeiten mit Tabellen und Daten in DynamoDB
<a name="WorkingWithTables"></a>

In diesem Abschnitt wird beschrieben, wie Sie die AWS Command Line Interface (AWS CLI) und die verwenden, AWS SDKs um Tabellen in Amazon DynamoDB zu erstellen, zu aktualisieren und zu löschen.

**Anmerkung**  
Sie können auch die entsprechenden Aufgaben mithilfe der AWS-Managementkonsole durchführen. Weitere Informationen finden Sie unter [Verwenden der Konsole](AccessingDynamoDB.md#ConsoleDynamoDB).

Außerdem erhalten Sie weitere Informationen zur Durchsatzkapazität mithilfe von DynamoDB-Auto-Scaling oder durch die manuelle Festlegung des bereitgestellten Durchsatzes.

**Topics**
+ [Grundlegende Operationen für DynamoDB-Tabellen](WorkingWithTables.Basics.md)
+ [Überlegungen bei der Auswahl einer Tabellenklasse in DynamoDB](WorkingWithTables.tableclasses.md)
+ [Hinzufügen von Tags und Labels zu Ressourcen in DynamoDB](Tagging.md)

# Grundlegende Operationen für DynamoDB-Tabellen
<a name="WorkingWithTables.Basics"></a>

Ähnlich wie andere Datenbanksysteme speichert Amazon DynamoDB Daten in Tabellen. Sie können Ihre Tabellen mit einigen grundlegenden Operationen verwalten.

**Topics**
+ [Erstellen einer Tabelle](#WorkingWithTables.Basics.CreateTable)
+ [Beschreiben einer Tabelle](#WorkingWithTables.Basics.DescribeTable)
+ [Aktualisieren einer Tabelle](#WorkingWithTables.Basics.UpdateTable)
+ [Löschen einer Tabelle](#WorkingWithTables.Basics.DeleteTable)
+ [Löschschutz verwenden](#WorkingWithTables.Basics.DeletionProtection)
+ [Auflisten von Tabellennamen](#WorkingWithTables.Basics.ListTables)
+ [Beschreiben der bereitgestellten Durchsatzkontingente](#WorkingWithTables.Basics.DescribeLimits)

## Erstellen einer Tabelle
<a name="WorkingWithTables.Basics.CreateTable"></a>

Verwenden Sie `CreateTable`, um eine Tabelle in Amazon DynamoDB zu erstellen. Zum Erstellen einer Tabelle müssen Sie folgende Informationen angeben:
+ **Tabellenname.** Der Name muss den Benennungsregeln von DynamoDB entsprechen und für das aktuelle AWS Konto und die Region eindeutig sein. So können Sie beispielsweise eine `People`-Tabelle in USA Ost (Nord-Virginia) und eine andere `People`-Tabelle in Europa (Irland) erstellen. Allerdings würden sich diese beiden Tabellen vollständig unterscheiden. Weitere Informationen finden Sie unter [Unterstützte Datentypen und Benennungsregeln in Amazon DynamoDB](HowItWorks.NamingRulesDataTypes.md).
+ **Primärschlüssel.** Der Primärschlüssel kann aus einem Attribut (Partitionsschlüssel) oder zwei Attributen (Partitionsschlüssel und Sortierschlüssel) bestehen. Sie müssen die Attributnamen, Datentypen und die Rolle der einzelnen Attribute angeben: `HASH` (für einen Partitionsschlüssel) und `RANGE` (für einen Sortierschlüssel). Weitere Informationen finden Sie unter [Primärschlüssel](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.PrimaryKey).
+ **Durchsatzeinstellungen (für bereitgestellte Tabellen).** Im Modus bereitgestellter Kapazität müssen Sie die Anfangseinstellungen für den Lese- und Schreibdurchsatz für die Tabelle angeben. Sie können diese Einstellungen später anpassen oder das DynamoDB-Auto-Scaling aktivieren, um die Einstellungen für Sie zu verwalten. Weitere Informationen erhalten Sie unter [DynamoDB – Modus mit bereitgestellter Kapazität](provisioned-capacity-mode.md) und [Automatische Verwaltung der Durchsatzkapazität mit DynamoDB-Auto-Scaling](AutoScaling.md).

### Beispiel 1: Erstellen einer On-Demand-Tabelle
<a name="create-payperrequest-example"></a>

So erstellen Sie dieselbe Tabelle `Music` im On-Demand-Modus

```
aws dynamodb create-table \
    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --billing-mode=PAY_PER_REQUEST
```

Die `CreateTable`-Operation gibt Metadaten für die Tabelle, wie unten gezeigt, zurück.

```
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/Music",
        "AttributeDefinitions": [
            {
                "AttributeName": "Artist",
                "AttributeType": "S"
            },
            {
                "AttributeName": "SongTitle",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 0,
            "ReadCapacityUnits": 0
        },
        "TableSizeBytes": 0,
        "TableName": "Music",
        "BillingModeSummary": {
            "BillingMode": "PAY_PER_REQUEST"
        },
        "TableStatus": "CREATING",
        "TableId": "12345678-0123-4567-a123-abcdefghijkl",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "Artist"
            },
            {
                "KeyType": "RANGE",
                "AttributeName": "SongTitle"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1542397468.348
    }
}
```

**Wichtig**  
 Wenn `DescribeTable` für eine On-Demand-Tabelle aufgerufen wird, werden Lesekapazitätseinheiten und Schreibkapazitätseinheiten auf 0 eingestellt. 

### Beispiel 2: Erstellen einer Tabelle im Modus bereitgestellter Kapazität
<a name="create-provisioned-example"></a>

Das folgende AWS CLI Beispiel zeigt, wie eine Tabelle () erstellt wird. `Music` Der Primärschlüssel besteht aus `Artist` (Partitionsschlüssel) und `SongTitle` (Sortierschlüssel), die beide vom Datentyp `String` sind. Der maximale Durchsatz für diese Tabelle ist 10 Lesekapazitätseinheiten und 5 Schreibkapazitätseinheiten.

```
aws dynamodb create-table \
    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5
```

Die `CreateTable`-Operation gibt Metadaten für die Tabelle, wie unten gezeigt, zurück.

```
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/Music",
        "AttributeDefinitions": [
            {
                "AttributeName": "Artist",
                "AttributeType": "S"
            },
            {
                "AttributeName": "SongTitle",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 5,
            "ReadCapacityUnits": 10
        },
        "TableSizeBytes": 0,
        "TableName": "Music",
        "TableStatus": "CREATING",
        "TableId": "12345678-0123-4567-a123-abcdefghijkl",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "Artist"
            },
            {
                "KeyType": "RANGE",
                "AttributeName": "SongTitle"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1542397215.37
    }
}
```

Das Element `TableStatus` gibt den aktuellen Status der Tabelle an (`CREATING`). Es kann eine Weile dauern die Tabelle zu erstellen, abhängig von den Werten die Sie für `ReadCapacityUnits` und `WriteCapacityUnits` angeben. Größere Werte für diese erfordern, dass DynamoDB der Tabelle mehr Ressourcen zuweist.

### Beispiel 3: Erstellen Sie eine Tabelle mit der Tabellenklasse DynamoDB Standard-Infrequent Access
<a name="create-infrequent-access-example"></a>

So erstellen Sie dieselbe `Music`-Tabelle mit der Tabellenklasse DynamoDB Standard-Infrequent Access.

```
aws dynamodb create-table \
    --table-name Music \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --table-class STANDARD_INFREQUENT_ACCESS
```

Die `CreateTable`-Operation gibt Metadaten für die Tabelle, wie unten gezeigt, zurück.

```
{
    "TableDescription": {
        "TableArn": "arn:aws:dynamodb:us-east-1:123456789012:table/Music",
        "AttributeDefinitions": [
            {
                "AttributeName": "Artist",
                "AttributeType": "S"
            },
            {
                "AttributeName": "SongTitle",
                "AttributeType": "S"
            }
        ],
        "ProvisionedThroughput": {
            "NumberOfDecreasesToday": 0,
            "WriteCapacityUnits": 5,
            "ReadCapacityUnits": 10
        },
        "TableClassSummary": {
            "LastUpdateDateTime": 1542397215.37,
            "TableClass": "STANDARD_INFREQUENT_ACCESS"
        },
        "TableSizeBytes": 0,
        "TableName": "Music",
        "TableStatus": "CREATING",
        "TableId": "12345678-0123-4567-a123-abcdefghijkl",
        "KeySchema": [
            {
                "KeyType": "HASH",
                "AttributeName": "Artist"
            },
            {
                "KeyType": "RANGE",
                "AttributeName": "SongTitle"
            }
        ],
        "ItemCount": 0,
        "CreationDateTime": 1542397215.37
    }
}
```

## Beschreiben einer Tabelle
<a name="WorkingWithTables.Basics.DescribeTable"></a>

Um Details über eine Tabelle anzuzeigen, verwenden Sie die `DescribeTable`-Operation. Sie müssen den Tabellennamen angeben. Die Ausgabe von `DescribeTable` erfolgt in demselben Format wie bei `CreateTable`. Sie enthält den Zeitstempel, mit dem die Tabelle erstellt wurde, ihr Schlüsselschema, ihre bereitgestellten Durchsatzeinstellungen, ihre geschätzte Größe und alle vorhandenen sekundären Indexe.

**Wichtig**  
 Wenn `DescribeTable` für eine On-Demand-Tabelle aufgerufen wird, werden Lesekapazitätseinheiten und Schreibkapazitätseinheiten auf 0 eingestellt. 

**Example**  

```
aws dynamodb describe-table --table-name Music
```

Die Tabelle ist einsatzbereit, wenn der `TableStatus` sich von `CREATING` in `ACTIVE` ändert.

**Anmerkung**  
Wenn Sie eine `DescribeTable`-Anforderung sofort nach der `CreateTable`-Anforderung ausgeben, kann DynamoDB möglicherweise einen Fehler (`ResourceNotFoundException`) zurückgeben. Der Grund hierfür ist, dass `DescribeTable` eine Eventually Consistent-Abfrage verwendet und dass die Metadaten für Ihre Tabelle zu diesem Zeitpunkt möglicherweise nicht verfügbar sein könnten. Warten Sie einige Sekunden und versuchen Sie dann die `DescribeTable`-Anforderung erneut.  
Für Abrechnungszwecke beinhalten Ihre DynamoDB-Speicherkosten einen Overhead pro Artikel von 100 Byte. (Weitere Informationen finden Sie unter [DynamoDB-Preise](https://aws.amazon.com/dynamodb/pricing/).) Diese zusätzlichen 100 Byte pro Element werden nicht in Kapazitätseinheitenberechnungen oder durch die `DescribeTable`-Operation verwendet. 

## Aktualisieren einer Tabelle
<a name="WorkingWithTables.Basics.UpdateTable"></a>

Die `UpdateTable`-Operation ermöglicht es Ihnen einen der folgenden Schritte ausführen:
+ Ändern Sie die bereitgestellten Durchsatzeinstellungen (für Tabellen im Modus bereitgestellter Kapazität).
+ Ändern Sie den read/write Kapazitätsmodus der Tabelle.
+ Bearbeiten Sie globale sekundäre Indizes für die Tabelle (siehe [Verwenden globaler sekundärer Indizes in DynamoDB](GSI.md)).
+ Aktivieren oder Deaktivieren von DynamoDB Streams für die Tabelle (siehe [Ändern Sie die Datenerfassung für DynamoDB Streams](Streams.md)).

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie die Einstellungen für den bereitgestellten Durchsatz einer Tabelle geändert werden.  

```
aws dynamodb update-table --table-name Music \
    --provisioned-throughput ReadCapacityUnits=20,WriteCapacityUnits=10
```

**Anmerkung**  
Wenn Sie eine `UpdateTable`-Anforderung ausgeben, ändert sich der Tabellenstatus von `AVAILABLE` in `UPDATING`. Die Tabelle steht vollständig zur Verfügung, während sie `UPDATING`. Wenn dieser Vorgang abgeschlossen ist, ändert sich der Status der Tabelle von `UPDATING` in `AVAILABLE`.

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie der read/write Kapazitätsmodus einer Tabelle in den On-Demand-Modus geändert wird.  

```
aws dynamodb update-table --table-name Music \
    --billing-mode PAY_PER_REQUEST
```

## Löschen einer Tabelle
<a name="WorkingWithTables.Basics.DeleteTable"></a>

Sie können eine ungenutzte Tabelle mit der `DeleteTable`-Operation entfernen. Das Löschen einer Tabelle ist ein unwiederbringlicher Vorgang. Informationen zum Löschen einer Tabelle mit der AWS-Managementkonsole finden Sie unter [Schritt 6: (Optional) Löschen der DynamoDB-Tabelle, um Ressourcen zu bereinigen](getting-started-step-6.md).

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie eine Tabelle gelöscht wird.  

```
aws dynamodb delete-table --table-name Music
```

Wenn Sie eine `DeleteTable`-Anforderung ausgeben, ändert sich der Tabellenstatus von `ACTIVE` in `DELETING`. Es kann eine Weile dauern die Tabelle zu löschen, abhängig von den verwendeten Ressourcen (z. B. die in der Tabelle gespeicherten Daten und alle Streams oder Indizes der Tabelle).

Wenn die `DeleteTable`-Operation abschließt, ist die Tabelle in DynamoDB nicht mehr vorhanden.

## Löschschutz verwenden
<a name="WorkingWithTables.Basics.DeletionProtection"></a>

Mit der Löschschutz-Eigenschaft können Sie eine Tabelle vor dem versehentlichen Löschen schützen. Wenn Sie diese Eigenschaft für Tabellen aktivieren, können Sie sicherstellen, dass Tabellen nicht versehentlich während regulärer Tabellenverwaltungsvorgängen durch Ihre Administratoren gelöscht werden. Auf diese Weise können Sie Störungen des normalen Geschäftsbetriebs vermeiden.

 Der Tabelleneigentümer oder ein autorisierter Administrator steuert die Löschschutz-Eigenschaft für jede Tabelle. Die Löschschutz-Eigenschaft ist bei Tabellen standardmäßig deaktiviert. Dies umfasst globale Replikate und Tabellen, die aus Backups wiederhergestellt wurden. Wenn der Löschschutz für eine Tabelle deaktiviert ist, kann die Tabelle von allen Benutzern gelöscht werden, die durch eine Identity and Access Management (IAM)-Richtlinie autorisiert wurden. Wenn der Löschschutz für eine Tabelle aktiviert ist, kann die Tabelle von niemandem gelöscht werden. 

Wenn Sie diese Einstellung ändern möchten, rufen Sie **Zusätzliche Einstellungen** für die Tabelle auf, navigieren Sie zum Bereich **Löschschutz** und wählen Sie **Löschschutz aktivieren** aus. 

Die Löschschutz-Eigenschaft wird von der DynamoDB-Konsole, der API, CLI/SDK und CloudFormation unterstützt. Die API `CreateTable` unterstützt die Löschschutz-Eigenschaft während der Tabellenerstellung und die API `UpdateTable` unterstützt Änderungen an der Löschschutz-Eigenschaft für vorhandene Tabellen.

**Anmerkung**  
Wenn ein AWS Konto gelöscht wird, werden alle Daten dieses Kontos, einschließlich der Tabellen, weiterhin innerhalb von 90 Tagen gelöscht.
Wenn DynamoDB keinen Zugriff mehr auf einen kundenverwalteten Schlüssel hat, der zum Verschlüsseln einer Tabelle verwendet wurde, wird die Tabelle trotzdem archiviert. Bei der Archivierung wird ein Backup der Tabelle erstellt und das Original gelöscht.

## Auflisten von Tabellennamen
<a name="WorkingWithTables.Basics.ListTables"></a>

Die `ListTables` Operation gibt die Namen der DynamoDB-Tabellen für das AWS Girokonto und die Region zurück.

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie die DynamoDB-Tabellennamen aufgelistet werden.  

```
aws dynamodb list-tables
```

## Beschreiben der bereitgestellten Durchsatzkontingente
<a name="WorkingWithTables.Basics.DescribeLimits"></a>

Der `DescribeLimits` Vorgang gibt die aktuellen Lese- und Schreibkapazitätskontingente für das aktuelle AWS Konto und die Region zurück.

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie die aktuell bereitgestellten Durchsatzquoten beschrieben werden.  

```
aws dynamodb describe-limits
```
Die Ausgabe zeigt die oberen Kontingente der Lese- und Schreibkapazitätseinheiten für das aktuelle AWS Konto und die Region.

Weitere Informationen zu diesen Kontingenten und zum Anfordern einer Kontingenterhöhung finden Sie unter [Standardkontingente für den Durchsatz](ServiceQuotas.md#default-limits-throughput).

# Überlegungen bei der Auswahl einer Tabellenklasse in DynamoDB
<a name="WorkingWithTables.tableclasses"></a>

DynamoDB bietet zwei Tabellenklassen an, mit denen Sie Ihre Kosten optimieren können. Die DynamoDB-Standard-Tabellenklasse ist die Standardeinstellung und wird für die große Mehrheit der Workloads empfohlen. Die Tabellenklasse DynamoDB Standard-Infrequent Access (DynamoDB Standard-IA) ist für Tabellen optimiert, in denen Speicher die dominierenden Kosten sind. Zum Beispiel sind Tabellen, die selten aufgerufene Daten speichern, wie Anwendungsprotokolle, alte Social-Media-Posts, E-Commerce-Bestellhistorie und frühere Spielerrungenschaften, gute Kandidaten für die Standard-IA Tabellenklasse.

Jede DynamoDB-Tabelle ist einer Tabellenklasse zugeordnet. Alle der Tabelle zugeordneten sekundären Indizes verwenden dieselbe Tabellenklasse. Sie können Ihre Tabellenklasse beim Erstellen Ihrer Tabelle festlegen (standardmäßig DynamoDB Standard) und die Tabellenklasse einer vorhandenen Tabelle mithilfe der AWS CLI oder AWS des AWS-Managementkonsole SDK aktualisieren. DynamoDB unterstützt auch die Verwaltung Ihrer Tabellenklasse mithilfe von AWS CloudFormation Tabellen mit nur einer Region (Tabellen, die keine globalen Tabellen sind). Jede Tabellenklasse bietet unterschiedliche Preise für die Datenspeicherung sowie für Lese- und Schreibanfragen. Wenn Sie eine Tabellenklasse für Ihre Tabelle auswählen, müssen Sie Folgendes beachten:
+ Die DynamoDB Standard-Tabellenklasse bietet niedrigere Durchsatzkosten als DynamoDB Standard-IA und ist die kostengünstigste Option für Tabellen, bei denen der Durchsatz die dominierenden Kosten darstellt. 
+ Die DynamoDB Standard-IA Tabellenklasse bietet niedrigere Speicherkosten als DynamoDB Standard und ist die kostengünstigste Option für Tabellen, in denen der Speicher die dominierenden Kosten darstellt. Wenn der Speicher 50% der Durchsatzkosten (Lese- und Schreibvorgänge) einer Tabelle unter Verwendung der DynamoDB Standard-Tabellenklasse übersteigt, kann die DynamoDB Standard-IA Tabellenklasse Ihnen dabei helfen, Ihre Gesamttabellenkosten zu senken. 
+ DynamoDB-Standard-IA-Tabellen bieten die gleiche Leistung, Haltbarkeit und Verfügbarkeit wie DynamoDB-Standardtabellen. 
+ Der Wechsel zwischen den DynamoDB-Standard- und DynamoDB-Standard-IA Tabellenklassen erfordert keine Änderung Ihres Anwendungscodes. Sie verwenden dieselben DynamoDB APIs - und Service-Endpunkte, unabhängig von der Tabellenklasse, die Ihre Tabellen verwenden. 
+ DynamoDB-Standard-IA-Tabellen sind mit allen vorhandenen DynamoDB-Funktionen wie Auto Scaling, On-Demand-Modus time-to-live (TTL), On-Demand-Backups, point-in-time Recovery (PITR) und globalen Sekundärindizes kompatibel.

Die kostengünstigste Tabellenklasse für Ihre Tabelle hängt von den erwarteten Speicher- und Durchsatznutzungsmustern Ihrer Tabelle ab. Mit Kosten- und Nutzungsberichten und dem Cost Explorer können Sie sich die historischen Speicher- und AWS Durchsatzkosten und die AWS Nutzung Ihrer Tabelle ansehen. Verwenden Sie diese historischen Daten, um die kostengünstigste Tabellenklasse für Ihre Tabelle zu ermitteln. Weitere Informationen zur Verwendung von AWS Kosten- und Nutzungsberichten und dem AWS Cost Explorer finden Sie in der [Dokumentation zu AWS Billing and Cost Management](https://docs.aws.amazon.com/account-billing/index.html). Siehe [Amazon-DynamoDB Preise](https://aws.amazon.com/dynamodb/pricing/on-demand/) für weitere Informationen zu Tabellenklassenpreisen.

**Anmerkung**  
Eine Tabellenklassenaktualisierung ist ein Hintergrundprozess. Sie können während einer Tabellenklassenktualisierung weiterhin normal auf Ihre Tabelle zugreifen. Die Zeit zum Aktualisieren Ihrer Tabellenklasse hängt von Ihrem Tabellenverkehr, der Speichergröße und anderen verbundenen Variablen ab. In einem zurückliegenden Zeitraum von 30 Tagen sind nicht mehr als zwei Tabellenklassenaktualisierungen in Ihrer Tabelle zulässig.

# Hinzufügen von Tags und Labels zu Ressourcen in DynamoDB
<a name="Tagging"></a>

Sie können Amazon-DynamoDB-Ressourcen mit *Tags* markieren. Tags helfen Ihnen, Ihre Ressourcen auf unterschiedliche Weise zu kategorisieren, z. B. nach Zweck, Besitzer, Umgebung oder anderen Kriterien. Tags können Sie bei Folgendem unterstützen:
+ Eine Ressource basierend auf den Tags, die Sie ihr zugeordnet haben, schnell zu erkennen.
+ Sehen Sie sich AWS Rechnungen an, aufgeschlüsselt nach Stichwörtern.
**Anmerkung**  
Alle lokalen sekundären Indizes (LSI) und globalen sekundären Indizes (GSI) im Zusammenhang mit markierten Tabellen werden automatisch mit denselben Tags gekennzeichnet. Derzeit kann die Nutzung des DynamoDB-Streams nicht markiert werden.

Tagging wird von AWS Diensten wie Amazon EC2, Amazon S3, DynamoDB und mehr unterstützt. Effizientes Tagging kann Kosteneinblicke bereitstellen, mit denen Sie Berichte für Services erstellen können, die ein spezifisches Tag aufweisen.

Gehen Sie wie folgt vor, um sich mit dem Taggen vertraut zu machen:

1. Lesen Sie [Markierungseinschränkungen in DynamoDB](#TaggingRestrictions).

1. Tags mit [Markieren von Ressourcen in DynamoDB](Tagging.Operations.md) erstellen.

1. Verwenden Sie diese Option[Verwenden von DynamoDB-Tags zum Erstellen von Kostenzuordnungsberichten](#CostAllocationReports), um Ihre AWS Kosten pro aktivem Tag nachzuverfolgen.

Schließlich wird empfohlen, optimale Tagging-Strategien zu befolgen. Weitere Informationen finden Sie unter [AWS -Markierungsstrategien](https://d0.awsstatic.com/aws-answers/AWS_Tagging_Strategies.pdf).

## Markierungseinschränkungen in DynamoDB
<a name="TaggingRestrictions"></a>

 Jedes Tag besteht aus einem Schlüssel und einem Wert, die Sie beide selbst definieren. Beachten Sie die folgenden Einschränkungen: 
+  Jede DynamoDB-Tabelle kann nur über ein Tag mit demselben Schlüssel verfügen. Wenn Sie versuchen, ein vorhandenes Tag (derselbe Schlüssel) hinzuzufügen, wird der vorhandene Tag-Wert auf den neuen Wert aktualisiert. 
+  Bei Tag-Schlüsseln und -Werten muss die Groß- und Kleinschreibung beachtet werden. 
+  Die maximale Schlüssellänge beträgt 128 Unicode-Zeichen. 
+ Die maximale Wertlänge beträgt 256 Unicode-Zeichen. 
+  Namen dürfen Buchstaben, Leerzeichen und Zahlen sowie die folgenden Sonderzeichen enthalten: `+ - = . _ : /` 
+  Die maximale Anzahl an Tags pro Ressource beträgt 50.
+ Die maximale Größe, die für alle Tags in einer Tabelle unterstützt wird, beträgt 10 KB.
+ AWS-zugewiesenen Tagnamen und -werten wird automatisch das `aws:` Präfix zugewiesen, das Sie nicht zuweisen können. AWS-zugewiesene Tagnamen werden nicht auf das Tag-Limit von 50 oder das maximale Größenlimit von 10 KB angerechnet. Von Benutzern zugewiesene Tag-Namen haben das Präfix `user:` im Kostenzuordnungsbericht. 
+  Sie können die Anwendung eines Tags nicht rückdatieren. 

# Markieren von Ressourcen in DynamoDB
<a name="Tagging.Operations"></a>

Sie können die Amazon DynamoDB DynamoDB-Konsole oder die AWS Command Line Interface (AWS CLI) verwenden, um Tags hinzuzufügen, aufzulisten, zu bearbeiten oder zu löschen. Anschließend können Sie diese benutzerdefinierten Tags aktivieren, damit sie in der AWS Fakturierung und Kostenmanagement -Konsole zur Nachverfolgung der Kostenzuordnung erscheinen. Weitere Informationen finden Sie unter [Verwenden von DynamoDB-Tags zum Erstellen von Kostenzuordnungsberichten](Tagging.md#CostAllocationReports). 

 Für die Massenbearbeitung können Sie auch den Tag-Editor in der AWS-Managementkonsole verwenden. Weitere Informationen finden Sie unter [Arbeiten mit dem Tag Editor](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/tag-editor.html).

 Informationen zum Verwenden der DynamoDB-API stattdessen finden Sie unter den folgenden Operationen in der [Amazon-DynamoDB-API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/):
+ [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html)
+ [UntagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UntagResource.html)
+ [ListTagsOfResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListTagsOfResource.html)

**Topics**
+ [Festlegen von Berechtigungen zum Filtern nach Tags](#Tagging.Operations.permissions)
+ [Hinzufügen von Tags zu neuen oder vorhandenen Tabellen (AWS-Managementkonsole)](#Tagging.Operations.using-console)
+ [Hinzufügen von Tags zu neuen oder vorhandenen Tabellen (AWS CLI)](#Tagging.Operations.using-cli)

## Festlegen von Berechtigungen zum Filtern nach Tags
<a name="Tagging.Operations.permissions"></a>

Wenn Sie Tags zum Filtern Ihrer Tabellenliste in der DynamoDB-Konsole verwenden möchten, stellen Sie sicher, dass die Richtlinien der Benutzer Zugriff auf die folgenden Vorgänge enthalten:
+ `tag:GetTagKeys`
+ `tag:GetTagValues`

Sie können auf diese Vorgänge zugreifen, indem Sie eine neue IAM-Richtlinie an Ihren Benutzer anhängen. Führen Sie dazu die folgenden Schritte aus.

1. Wechseln Sie mit einem Admin-Benutzer zur [IAM-Konsole](https://console.aws.amazon.com/iam/).

1. Wählen Sie im linken Navigationsbereich „Richtlinien“ aus

1. Wählen Sie Richtlinie erstellen.

1. Fügen Sie das folgende Richtliniendokument in den JSON-Editor ein.

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "tag:GetTagKeys",
                   "tag:GetTagValues"
               ],
               "Resource": "*"
           }
       ]
   }
   ```

------

1. Schließen Sie den Assistenten ab, und weisen Sie der Richtlinie einen Namen zu (z. B. `TagKeysAndValuesReadAccess`).

1. Wählen Sie im linken Navigationsmenü „Benutzer“ aus.

1. Wählen Sie in der Liste den Benutzer aus, den Sie normalerweise für den Zugriff auf die DynamoDB-Konsole verwenden.

1. Wählen Sie „Berechtigungen hinzufügen“ aus.

1. Wählen Sie die Option Vorhandene Richtlinien direkt anfügen aus.

1. Wählen Sie in der Liste die Richtlinie aus, die Sie zuvor erstellt haben.

1. Schließen Sie den Assistenten ab.

## Hinzufügen von Tags zu neuen oder vorhandenen Tabellen (AWS-Managementkonsole)
<a name="Tagging.Operations.using-console"></a>

Sie können die DynamoDB-Konsole verwenden, um neuen Tabellen Tags hinzuzufügen, wenn Sie sie erstellen, oder um Tags für vorhandene Tabellen hinzuzufügen, zu bearbeiten oder zu löschen.

**Markieren von Ressourcen bei der Erstellung (Konsole)**

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie im Navigationsbereich **Tables** (Tabellen) und anschließend **Create table** (Tabelle erstellen) aus.

1. Geben Sie auf der Seite **DynamoDB-Tabelle erstellen** einen Namen und einen Primärschlüssel ein. Wählen Sie im Abschnitt **Tags** (Tags) **Add new tag** (Neuen Tag hinzufügen) und geben Sie die Tags ein, die Sie verwenden möchten.

   Informationen zur Tag-Struktur finden Sie unter [Markierungseinschränkungen in DynamoDB](Tagging.md#TaggingRestrictions). 

   Weitere Informationen zum Erstellen von Tabellen finden Sie unter [Grundlegende Operationen für DynamoDB-Tabellen](WorkingWithTables.Basics.md).

**Markieren vorhandener Ressourcen (Konsole)**

Öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie im Navigationsbereich **Tables** (Tabellen) aus.

1. Wählen Sie eine Tabelle in der Liste aus und wählen Sie dann die Registerkarte **Additional settings** (Zusätzliche Einstellungen). Sie können Ihre Tags im Abschnitt **Tags** unten auf der Seite hinzufügen, bearbeiten oder löschen.

## Hinzufügen von Tags zu neuen oder vorhandenen Tabellen (AWS CLI)
<a name="Tagging.Operations.using-cli"></a>

Die folgenden Beispiele zeigen, wie Sie die verwenden AWS CLI , um Tags anzugeben, wenn Sie Tabellen und Indizes erstellen, und um vorhandene Ressourcen zu taggen.

**Markieren von Ressourcen bei der Erstellung (AWS CLI)**
+ Im folgenden Beispiel wird eine neue `Movies`-Tabelle erstellt und das `Owner`-Tag mit dem Wert `blueTeam` hinzugefügt: 

  ```
  aws dynamodb create-table \
      --table-name Movies \
      --attribute-definitions AttributeName=Title,AttributeType=S \
      --key-schema AttributeName=Title,KeyType=HASH \
      --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
      --tags Key=Owner,Value=blueTeam
  ```

**Markieren vorhandener Ressourcen (AWS CLI)**
+ Im folgenden Beispiel wird das `Owner`-Tag mit dem Wert `blueTeam` für die Tabelle `Movies` hinzugefügt: 

  ```
  aws dynamodb tag-resource \
      --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies \
      --tags Key=Owner,Value=blueTeam
  ```

**Auflisten aller Tags für eine Tabelle (AWS CLI)**
+ Im folgenden Beispiel werden alle Tags aufgelistet, die mit der Tabelle `Movies` verknüpft sind:

  ```
  aws dynamodb list-tags-of-resource \
      --resource-arn arn:aws:dynamodb:us-east-1:123456789012:table/Movies
  ```

## Verwenden von DynamoDB-Tags zum Erstellen von Kostenzuordnungsberichten
<a name="CostAllocationReports"></a>

AWS verwendet Tags, um die Ressourcenkosten in Ihrem Kostenverteilungsbericht zu organisieren. AWS bietet zwei Arten von Kostenzuordnungs-Tags:
+ Ein von AWS-generierter Tag. AWS definiert, erstellt und wendet dieses Tag für Sie an.
+ Benutzerdefinierte Tags. Sie definieren und erstellen diese Tags und wenden sie an.

Sie müssen beide Arten von Tags separat aktivieren, bevor sie in Cost Explorer oder einem Kostenzuordnungsbericht angezeigt werden können. 

 Um AWS-generierte Tags zu aktivieren: 

1.  Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die Billing and Cost Management-Konsole von zu [https://console.aws.amazon.com/billing/Hause aus\$1/](https://console.aws.amazon.com/billing/home#/.). 

1.  Wählen Sie im Navigationsbereich die Option **Cost Allocation Tags** (Kostenzuordnungs-Tags) aus. 

1.  Wählen Sie unter **AWS-generierte Kostenzuordnungs-Tags** die Option **Aktivieren**. 

 So aktivieren Sie benutzerdefinierte Tags: 

1.  Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die Billing and Cost Management-Konsole von zu [https://console.aws.amazon.com/billing/Hause aus\$1/](https://console.aws.amazon.com/billing/home#/.). 

1.  Wählen Sie im Navigationsbereich die Option **Cost Allocation Tags** (Kostenzuordnungs-Tags) aus. 

1.  Wählen Sie unter **User-Defined Cost Allocation Tags** (Benutzerdefinierte Kostenzuordnungs-Tags) die Option **Activate** (Aktivieren) aus. 

 Nachdem Sie Stichwörter erstellt und aktiviert haben, AWS wird ein Kostenzuordnungsbericht generiert, in dem Ihre Nutzung und die Kosten nach Ihren aktiven Stichwörtern gruppiert sind. Der Kostenzuordnungsbericht enthält alle Ihre AWS Kosten für jeden Abrechnungszeitraum. Der Bericht enthält getaggte und nicht getaggte Ressourcen, sodass Sie die Gebühren für Ressourcen übersichtlich verwalten können. 

**Anmerkung**  
 Derzeit werden alle Daten, die aus DynamoDB weitergeleitet werden, im Kostenzuordnungsbericht nicht nach Tags aufgeschlüsselt. 

 Weitere Informationen finden Sie unter [Verwendung von Kostenzuordnungs-Tags](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html). 

# Globale Tabellen: multiaktive, regionsübergreifende Replikation
<a name="GlobalTables"></a>

*Globale Tabellen in Amazon DynamoDB* sind ein vollständig verwaltetes Feature für multiregionale und multiaktive Datenbanken, das sich durch eine benutzerfreundliche Datenbankreplikation und schnelle und lokale Lese- und Schreibvorgänge in globale Anwendungen auszeichnet.

Globale Tabellen replizieren Ihre DynamoDB-Tabellendaten automatisch kontenübergreifend AWS-Regionen und optional AWS kontenübergreifend, ohne dass Sie Ihre eigene Replikationslösung erstellen und verwalten müssen. Globale Tabellen eignen sich ideal für Anwendungen, die in mehreren Regionen bereitgestellt werden und Geschäftskontinuität sowie eine hohe Verfügbarkeit erfordern. Jedes Replikat einer globalen Tabelle kann Lese- und Schreibvorgänge ausführen. Anwendungen können eine hohe Ausfallsicherheit mit niedrigen oder ganz ohne RPO (Recovery Point Objective) erreichen, weil der Datenverkehr in eine andere Region verlagert wird, sobald die Verarbeitung durch die Anwendung in einer Region unterbrochen wird. Globale Tabellen sind in allen Regionen verfügbar, in denen auch DynamoDB verfügbar ist.

## Konsistenzmodi
<a name="GlobalTables.consistency-modes"></a>

Sie können bei der Erstellung einer globalen Tabelle den Konsistenzmodus konfigurieren. Globale Tabellen unterstützen zwei Konsistenzmodi: Multi-Region Eventual Consistency (MREC) und Multi-Region Strong Consistency (MRSC).

Wenn Sie beim Erstellen einer globalen Tabelle keinen Konsistenzmodus angeben, wird für die globale Tabelle standardmäßig der MREC-Modus verwendet. Replikate, die mit unterschiedlichen Konsistenzmodi konfiguriert wurden, sind in einer globalen Tabelle nicht zulässig. Sie können den Konsistenzmodus einer globalen Tabelle nach der Erstellung nicht mehr ändern.

## Kontokonfigurationen
<a name="GlobalTables.account-configurations"></a>

DynamoDB unterstützt jetzt zwei globale Tabellenmodelle, die jeweils für unterschiedliche Architekturmuster konzipiert wurden:
+ **Globale Tabellen mit demselben Konto** — Alle Replikate werden in einem einzigen Konto erstellt und verwaltet. AWS 
+ **Globale Tabellen mit mehreren Konten** — Replikate werden für mehrere AWS Konten bereitgestellt und sind gleichzeitig Teil einer gemeinsamen Replikationsgruppe.

Sowohl Modelle mit demselben Konto als auch mit mehreren Konten unterstützen Schreibvorgänge in mehreren Regionen, asynchrone Replikation, last-writer-wins Konfliktlösung und dasselbe Abrechnungsmodell. Sie unterscheiden sich jedoch darin, wie Konten, Berechtigungen, Verschlüsselung und Tabellen-Governance verwaltet werden.

Für MRSC konfigurierte globale Tabellen unterstützen nur Konfigurationen mit demselben Konto.

Sie können eine globale Tabelle mit der Management Console konfigurieren. AWS Globale Tabellen verwenden vorhandene DynamoDB APIs zum Lesen und Schreiben von Daten in Ihre Tabellen, sodass keine Anwendungsänderungen erforderlich sind. Sie zahlen ohne Vorauszahlungen oder Verpflichtungen nur für bereitgestellte oder verwendete Ressourcen.


| **Eigenschaften** | **Globale Tabellen für dasselbe Konto** | **Globale Tabellen mit mehreren Konten** | 
| --- | --- | --- | 
| Primärer Anwendungsfall | Resilienz in mehreren Regionen für Anwendungen innerhalb eines einzigen Kontos AWS  | Replikation für mehrere Regionen und Konten für Anwendungen, die unterschiedlichen Teams, unterschiedlichen Geschäftseinheiten oder starken Sicherheitsgrenzen zwischen Konten gehören | 
| Kontomodell | Alle Repliken wurden in einem AWS Konto erstellt und verwaltet | Replikate, die für mehrere AWS Konten innerhalb derselben Bereitstellung erstellt wurden | 
| Besitz von Ressourcen | Ein einzelnes Konto besitzt die Tabelle und alle Replikate | Jedes Konto besitzt sein lokales Replikat; die Replikationsgruppe umfasst mehrere Konten | 
| Unterstützte Version | Version 2019.11.21 (aktuell) und Version 2017.11.29 (Legacy) | Version der globalen Tabellen 2019.11.21 (Aktuell) | 
| Betrieb der Kontrollebene | Erstellen, ändern und löschen Sie Replikate über das Konto des Tabellenbesitzers | Operationen auf verteilter Steuerungsebene: Konten treten der Replikationsgruppe bei oder verlassen sie | 
| Operationen auf Datenebene | DynamoDB-Standardendpunkte pro Region | Zugriff auf Datenebene pro Konto/Region; Routing über Replikationsgruppe | 
| Sicherheitsgrenze | Eine einzige IAM- und KMS-Grenze | Separate IAM-, KMS-, Fakturierungs- und CloudTrail Verwaltungsfunktionen für jedes Konto | 
| Beste Passform | Organizations mit zentralisiertem Besitz von Tabellen | Organizations mit Verbundteams, Verwaltungsgrenzen oder Konfigurationen mit mehreren Konten | 

**Topics**
+ [Konsistenzmodi](#GlobalTables.consistency-modes)
+ [Kontokonfigurationen](#GlobalTables.account-configurations)
+ [Kernkonzepte globaler Tabellen](globaltables-CoreConcepts.md)
+ [DynamoDB-Tabelle für dasselbe Konto](globaltables-SameAccount.md)
+ [DynamoDB-Tabellen für mehrere Konten](globaltables-MultiAccount.md)
+ [Grundlegendes zur Amazon DynamoDB-Fakturierung für globale Tabellen](global-tables-billing.md)
+ [Versionen von globalen DynamoDB-Tabellen](V2globaltables_versions.md)
+ [Bewährte Methoden für globale Tabellen](globaltables-bestpractices.md)

# Kernkonzepte globaler Tabellen
<a name="globaltables-CoreConcepts"></a>

In den folgenden Abschnitten werden die Konzepte und das Verhalten globaler Tabellen in Amazon DynamoDB beschrieben.

## Konzepte
<a name="globaltables-CoreConcepts.KeyConcepts"></a>

*Globale Tabellen* sind eine DynamoDB-Funktion, die Tabellendaten regionsübergreifend repliziert. AWS 

Eine *Replikattabelle* (oder kurz ein Replikat) ist eine einzelne DynamoDB-Tabelle, die als Teil einer globalen Tabelle fungiert. Eine globale Tabelle besteht aus zwei oder mehr Replikattabellen in verschiedenen Regionen. AWS Jede globale Tabelle kann nur über eine Replikattabelle je AWS -Region verfügen. Alle Replikate in einer globalen Tabelle verwenden denselben Tabellennamen, dasselbe Primärschlüsselschema und dieselben Elementdaten.

Wenn eine Anwendung Daten in eine Replikattabelle in einer Region schreibt, verteilt DynamoDB den Schreibvorgang automatisch auf die anderen Replikattabellen in der globalen Tabelle. Weitere Informationen zu den ersten Schritten mit globalen Tabellen finden Sie unter [Tutorials: Erstellen von globalen Tabellen](V2globaltables.tutorial.md) oder[Tutorials: Globale Tabellen mit mehreren Konten erstellen](V2globaltables_MA.tutorial.md).

## Versionen
<a name="globaltables-CoreConcepts.Versions"></a>

Es gibt zwei Versionen von globalen DynamoDB-Tabellen: [Version 2019.11.21 (Aktuell)](GlobalTables.md) und [Version 2017.11.29 (Legacy) der globalen Tabellen](globaltables.V1.md). Sie sollten nach Möglichkeit Global Tables Version 2019.11.21 (Aktuell) verwenden. Die Informationen in diesem Abschnitt der Dokumentation gelten für die Version 2019.11.21 (Aktuell). Weitere Informationen finden Sie unter Ermitteln der Version einer globalen Tabelle. [Ermitteln der Version einer globalen Tabelle](V2globaltables_versions.md#globaltables.DetermineVersion)

## Verfügbarkeit
<a name="globaltables-CoreConcepts.availability"></a>

Globale Tabellen tragen zur Verbesserung der Geschäftskontinuität bei, da sie die Implementierung einer hoch verfügbaren Architektur für mehrere Regionen erleichtern. Wenn eine Arbeitslast in einer einzelnen AWS Region beeinträchtigt wird, können Sie den Anwendungsdatenverkehr in eine andere Region verlagern und Lese- und Schreibvorgänge in einer anderen Replikattabelle in derselben globalen Tabelle durchführen.

Jede Replikattabelle in einer globalen Tabelle bietet dieselbe Stabilität und Verfügbarkeit wie eine DynamoDB-Tabelle mit einer Region. Globale Tabellen bieten ein [Service Level Agreement (SLA)](https://aws.amazon.com//dynamodb/sla/) mit einer Verfügbarkeit von 99,999 %, im Gegensatz zur Verfügbarkeit von 99,99 % bei Tabellen mit einer einzelnen Region.

## Testen mit Fehlerinjektionen
<a name="fault-injection-testing"></a>

Sowohl die globalen MREC- als auch die MRSC-Tabellen sind in den [AWSAWS Fault Injection Service](https://docs.aws.amazon.com/resilience-hub/latest/userguide/testing.html) (FIS) integriert, einen vollständig verwalteten Dienst zur Durchführung kontrollierter Fehlerinjektionsexperimente zur Verbesserung der Ausfallsicherheit einer Anwendung. Mit AWS FIS können Sie:
+ Erstellen Sie Versuchsvorlagen, die spezifische Fehlerszenarien definieren.
+ Injizieren Sie Fehler, um die Ausfallsicherheit von Anwendungen zu überprüfen, indem Sie die Regionsisolierung simulieren (d. h. die Replikation zu und von einem ausgewählten Replikat unterbrechen), um die Fehlerbehandlung, Wiederherstellungsmechanismen und das Verhalten bei Störungen in einer Region zu testen. AWS 

In einer globalen Tabelle mit Replikaten in USA Ost (Nord-Virginia), USA Ost (Ohio) und USA West (Oregon) können Sie beispielsweise ein Experiment in USA Ost (Ohio) durchführen, um die dortige Regionsisolierung zu testen, während USA Ost (Nord-Virginia) und USA West (Oregon) ihren normalen Betrieb fortsetzen. Diese kontrollierten Tests helfen Ihnen dabei, potenzielle Probleme zu identifizieren und zu lösen, bevor sie sich auf den Produktions-Workload auswirken. 

Eine vollständige Liste der von *AWS FIS unterstützten Aktionen und [regionsübergreifender Konnektivität zum Anhalten der DynamoDB-Replikation zwischen Regionen](https://docs.aws.amazon.com/fis/latest/userguide/cross-region-scenario.html) finden Sie unter [Aktionsziele](https://docs.aws.amazon.com/fis/latest/userguide/action-sequence.html#action-targets) im AWS FIS-Benutzerhandbuch*.

*Informationen zu globalen Tabellenaktionen von Amazon DynamoDB, die in AWS FIS verfügbar sind, finden Sie unter [DynamoDB Global Tables Actions Reference](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#dynamodb-actions-reference) im FIS-Benutzerhandbuch.AWS *

Informationen zu den ersten Schritten mit der Durchführung von Fault-Injection-Experimenten finden Sie unter [Planung Ihrer AWS FIS-Experimente im FIS-Benutzerhandbuch](https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html). AWS 

**Anmerkung**  
Bei AWS FIS Experimenten in MRSC sind eventuell konsistente Lesevorgänge zulässig, Aktualisierungen der Tabelleneinstellungen — wie z. B. das Ändern des Abrechnungsmodus oder die Konfiguration des Tabellendurchsatzes — sind jedoch nicht zulässig, ähnlich wie bei MREC. Weitere Informationen [`FaultInjectionServiceInducedErrors`](metrics-dimensions.md#FaultInjectionServiceInducedErrors)zum Fehlercode finden Sie in der CloudWatch Metrik.

## Time to Live (TTL)
<a name="global-tables-ttl"></a>

In globalen Tabellen mit MREC-Konfiguration kann die Konfiguration von [Time To Live](TTL.md) (TTL) gelöscht werden. Die TTL-Einstellungen werden automatisch für alle Replikate einer globalen Tabelle synchronisiert. Wenn TTL ein Element aus einem Replikat in einer Region löscht, wird der Löschvorgang auf alle anderen Replikate in der globalen Tabelle repliziert. TTL verbraucht keine Schreibkapazität; das Löschen von TTL wird Ihnen in der Region, in der der Löschvorgang stattgefunden hat, nicht in Rechnung gestellt. In allen anderen Regionen, deren globale Tabelle ein Replikat enthält, wird Ihnen jedoch der replizierte Löschvorgang in Rechnung gestellt.

Die Replikation eines TTL-Löschvorgangs verbraucht Schreibkapazität in den Replikaten, in die der Löschvorgang repliziert wird. Replikate, die für bereitgestellte Kapazität konfiguriert sind, können Anfragen drosseln, wenn die Kombination aus Schreibdurchsatz und TTL-Löschdurchsatz die bereitgestellte Schreibkapazität überschreitet.

Globale Tabellen mit MRSC-Konfiguration unterstützen die Konfiguration des TTL-Löschvorgangs nicht.

## Streams
<a name="global-tables-streams"></a>

Globale Tabellen mit MREC-Konfiguration replizieren Änderungen, indem sie diese aus einem [DynamoDB-Stream](Streams.md) in einer Replikattabelle auslesen und auf alle anderen Replikattabellen anwenden. Streams sind daher standardmäßig für alle Replikate in einer globalen MREC-Tabelle aktiviert und können in diesen Replikaten nicht deaktiviert werden. Der MREC-Replikationsprozess kann mehrere Änderungen in einem kurzen Zeitraum zu einem einzigen replizierten Schreibvorgang kombinieren, was dazu führt, dass der Stream jedes Replikats Datensätze enthält, die sich geringfügig unterscheiden. Streams-Datensätze auf MREC-Replikaten behalten die Reihenfolge für alle Änderungen am selben Objekt bei, aber die relative Reihenfolge der Änderungen an verschiedenen Elementen kann je nach Replikat variieren.

Wenn Sie eine Anwendung schreiben möchten, die Streams-Datensätze für Änderungen verarbeitet, die in einer bestimmten Region, aber nicht in anderen Regionen in einer globalen Tabelle vorgenommen wurden, können Sie jedem Element ein Attribut hinzufügen, das definiert, in welcher Region die Änderung für dieses Element stattgefunden hat. Sie können dieses Attribut verwenden, um Streams-Datensätze nach Änderungen zu filtern, die in anderen Regionen aufgetreten sind und hierzu auch Lambda-Ereignisfilter verwenden, um Lambda-Funktionen nur für Änderungen in einer bestimmten Region aufzurufen.

Globale Tabellen mit MRSC-Konfiguration verwenden keine DynamoDB Streams für die Replikation, sodass Streams in MRSC-Replikaten standardmäßig nicht aktiviert sind. Streams können in einem MRSC-Replikat aktiviert werden. Streams-Datensätze in MRSC-Replikaten sind für jedes Replikat identisch, auch in Bezug auf ihre Reihenfolge.

## Transaktionen
<a name="global-tables-transactions"></a>

In einer globalen Tabelle mit MREC-Konfiguration sind DynamoDB-Transaktionsoperationen ([https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) und [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)) nur innerhalb der Region, in der der Vorgang aufgerufen wurde, unteilbar. Schreibtransaktionen werden nicht als Einheit regionsübergreifend repliziert, was bedeutet, dass nur einige Schreibvorgänge in einer Transaktion zu einem bestimmten Zeitpunkt durch Lesevorgänge in anderen Replikaten zurückgegeben werden können.

Wenn Sie beispielsweise eine globale Tabelle mit Replikaten in den Regionen USA Ost (Ohio) und USA West (Oregon) nutzen und eine `TransactWriteItems`-Operation in der Region USA Ost (Ohio) durchführen, sind unter Umständen partiell durchgeführte Transaktionen in der Region USA West (Oregon) zu beobachten, während die Änderungen repliziert werden. Die Änderungen werden erst in die anderen Regionen repliziert, nachdem sie in der Quellregion in die Datenbank eingetragen wurden.

Globale Tabellen mit MRSC-Konfiguration unterstützen keine Transaktionsvorgänge und geben einen Fehler zurück, wenn solche Operationen in einem MRSC-Replikat aufgerufen werden.

## Lese- und Schreibdurchsatz
<a name="globaltables-CoreConcepts.Throughput"></a>

### Modus bereitgestellter Kapazität
<a name="gt_throughput.provisioned"></a>

Eine Replikation verbraucht Schreibkapazität. Replikate, die für bereitgestellte Kapazität konfiguriert sind, können Anfragen drosseln, wenn die Kombination aus Anwendungsschreibdurchsatz und Replikationsschreibdurchsatz die bereitgestellte Schreibkapazität überschreitet. Bei globalen Tabellen, die den Bereitstellungsmodus verwenden, werden die Auto Scaling-Einstellungen für Lese- und Schreibkapazitäten zwischen den Replikaten synchronisiert.

Sie können die Lesekapazitätseinstellungen für jedes Replikat in einer globalen Tabelle unabhängig konfigurieren, indem Sie den [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html)Parameter auf Replikatebene verwenden. Standardmäßig werden Änderungen an der bereitgestellten Lesekapazität auf alle Replikate in der globalen Tabelle angewendet. Beim Hinzufügen eines neuen Replikats zu einer globalen Tabelle wird die Lesekapazität der Quelltabelle oder des Replikats als Anfangswert verwendet, sofern nicht ausdrücklich eine Überschreibung auf Replikatebene angegeben ist.

### On-Demand-Modus
<a name="gt_throughput.on-demand"></a>

Bei globalen Tabellen, die für den On-Demand-Modus konfiguriert sind, wird die Schreibkapazität automatisch über alle Replikate hinweg synchronisiert. DynamoDB passt die Kapazität automatisch an den Datenverkehr an, und es müssen keine replikatspezifischen Lese- oder Schreibkapazitätseinstellungen verwaltet werden.

## Überwachen globaler Tabellen
<a name="monitoring-global-tables"></a>

In globalen Tabellen, die für Multi-Region Eventual Consistency (MREC) konfiguriert sind, wird die Metrik veröffentlicht. [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency) CloudWatch Diese Metrik misst die verstrichene Zeit zwischen dem Schreiben eines Elements in eine Replikattabelle und dem Erscheinen dieses Elements in einem anderen Replikat in der globalen Tabelle. `ReplicationLatency` wird in Millisekunden ausgedrückt und für jedes Paar aus Quell- und Zielregion ausgegeben. 

Typische `ReplicationLatency` Werte hängen von der Entfernung zwischen den ausgewählten AWS Regionen sowie von anderen Variablen wie Workload-Typ und Durchsatz ab. Beispiel: Ein Quellreplikat in der Region USA West (Nordkalifornien) (us-west-1) weist im Vergleich zur Region Afrika (Kapstadt) (af-south-1) einen niedrigeren Wert für `ReplicationLatency` auf als die Region USA West (Oregon) (us-west-2).

Ein erhöhter Wert für `ReplicationLatency` könnte darauf hinweisen, dass Updates von einem Replikat nicht in einem angemessenen Zeitraum an andere Replikattabellen verteilt werden. In diesem Fall können Sie die Lese- und Schreibaktivität Ihrer Anwendung vorübergehend in eine andere AWS Region umleiten.

Globale Tabellen mit MRSC-Konfiguration veröffentlichen keine `ReplicationLatency`-Metrik.

## Überlegungen zur Verwaltung globaler Tabellen
<a name="management-considerations"></a>

Sie können eine Tabelle, die zum Hinzufügen des neuen Replikats einer globalen Tabelle verwendet wurde, erst 24 Stunden nach der Erstellung des neuen Replikats löschen.

Wenn Sie eine AWS Region deaktivieren, die globale Tabellenreplikate enthält, werden diese Replikate 20 Stunden nach der Deaktivierung der Region dauerhaft in Tabellen mit nur einer Region konvertiert.

# DynamoDB-Tabelle für dasselbe Konto
<a name="globaltables-SameAccount"></a>

Globale Tabellen mit demselben Konto replizieren Ihre DynamoDB-Tabellendaten automatisch regionsübergreifend innerhalb AWS eines einzigen Kontos. AWS Globale Tabellen mit demselben Konto bieten das einfachste Modell für die Ausführung von Anwendungen mit mehreren Regionen, da alle Replikate dasselbe Kontogrenzen-, Eigentums- und Berechtigungsmodell verwenden. Wenn Sie die AWS Regionen für Ihre Replikattabellen auswählen, übernehmen globale Tabellen die gesamte Replikation automatisch. Globale Tabellen sind in allen Regionen verfügbar, in denen auch DynamoDB verfügbar ist.

Globale Tabellen mit demselben Konto bieten die folgenden Vorteile:
+ Automatisches Replizieren von DynamoDB-Tabellendaten in allen AWS Regionen Ihrer Wahl, um Daten näher an Ihren Benutzern zu finden
+ Höhere Anwendungsverfügbarkeit bei regionaler Isolierung oder Auslagerung von Daten
+ Verwenden Sie die integrierte Konfliktlösung, damit Sie sich auf die Geschäftslogik Ihrer Anwendung konzentrieren können
+ Wenn Sie eine globale Tabelle für dasselbe Konto erstellen, können Sie entweder oder wählen [Multi-Region Eventual Consistency (MREC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrec) [Multi-Region Strong Consistency (MRSC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrsc)

**Topics**
+ [So funktionieren globale DynamoDB-Tabellen](V2globaltables_HowItWorks.md)
+ [Tutorials: Erstellen von globalen Tabellen](V2globaltables.tutorial.md)
+ [Sicherheit von globalen DynamoDB-Tabellen](globaltables-security.md)

# So funktionieren globale DynamoDB-Tabellen
<a name="V2globaltables_HowItWorks"></a>

In den folgenden Abschnitten werden die Konzepte und das Verhalten globaler Tabellen in Amazon DynamoDB beschrieben.

## Konzepte
<a name="V2globaltables_HowItWorks.KeyConcepts"></a>

*Globale Tabellen* sind eine DynamoDB-Funktion, die Tabellendaten regionsübergreifend repliziert. AWS 

Eine *Replikattabelle* (oder kurz ein Replikat) ist eine einzelne DynamoDB-Tabelle, die als Teil einer globalen Tabelle fungiert. Eine globale Tabelle besteht aus zwei oder mehr Replikattabellen in verschiedenen Regionen. AWS Jede globale Tabelle kann nur über eine Replikattabelle je AWS -Region verfügen. Alle Replikate in einer globalen Tabelle verwenden denselben Tabellennamen, dasselbe Primärschlüsselschema und dieselben Elementdaten.

Wenn eine Anwendung Daten in eine Replikattabelle in einer Region schreibt, verteilt DynamoDB den Schreibvorgang automatisch auf die anderen Replikattabellen in der globalen Tabelle. Weitere Informationen über die ersten Schritte mit globalen Tabellen finden Sie unter [Tutorials: Erstellen von globalen Tabellen](V2globaltables.tutorial.md).

## Versionen
<a name="V2globaltables_HowItWorks.versions"></a>

Es gibt zwei Versionen von globalen DynamoDB-Tabellen: Version 2019.11.21 (Aktuell) und [Version 2017.11.29 (Legacy)](globaltables.V1.md). Sie sollten nach Möglichkeit die Version 2019.11.21 (Aktuell) verwenden. Die Informationen in diesem Abschnitt der Dokumentation gelten für die Version 2019.11.21 (Aktuell). Weitere Informationen finden Sie unter [Ermitteln der Version einer globalen Tabelle](V2globaltables_versions.md#globaltables.DetermineVersion).

## Verfügbarkeit
<a name="V2globaltables_HowItWorks.availability"></a>

Globale Tabellen tragen zur Verbesserung der Geschäftskontinuität bei, da sie die Implementierung einer hoch verfügbaren Architektur für mehrere Regionen erleichtern. Wenn eine Arbeitslast in einer einzelnen AWS Region beeinträchtigt wird, können Sie den Anwendungsdatenverkehr in eine andere Region verlagern und Lese- und Schreibvorgänge in einer anderen Replikattabelle in derselben globalen Tabelle durchführen.

Jede Replikattabelle in einer globalen Tabelle bietet dieselbe Stabilität und Verfügbarkeit wie eine DynamoDB-Tabelle mit einer Region. Globale Tabellen bieten ein [Service Level Agreement (SLA)](https://aws.amazon.com//dynamodb/sla/) mit einer Verfügbarkeit von 99,999 %, im Gegensatz zur Verfügbarkeit von 99,99 % bei Tabellen mit einer einzelnen Region.

## Konsistenzmodi
<a name="V2globaltables_HowItWorks.consistency-modes"></a>

Sie können bei der Erstellung einer globalen Tabelle den Konsistenzmodus konfigurieren. Globale Tabellen unterstützen zwei Konsistenzmodi: Multi-Region Eventual Consistency (MREC) und Multi-Region Strong Consistency (MRSC).

Wenn Sie beim Erstellen einer globalen Tabelle keinen Konsistenzmodus angeben, wird für die globale Tabelle standardmäßig der MREC-Modus verwendet. Replikate, die mit unterschiedlichen Konsistenzmodi konfiguriert wurden, sind in einer globalen Tabelle nicht zulässig. Sie können den Konsistenzmodus einer globalen Tabelle nach der Erstellung nicht mehr ändern.

### Multi-Region Eventual Consistency (MREC)
<a name="V2globaltables_HowItWorks.consistency-modes.mrec"></a>

Der Standardmodus für globale Tabellen ist der MREC-Modus (Multi-Region Eventual Consistency). Elementänderungen im Replikat einer globalen MREC-Tabelle werden asynchron für alle anderen Replikate repliziert, normalerweise innerhalb von maximal einer Sekunde. In dem unwahrscheinlichen Fall, dass ein Replikat in einer globalen MREC-Tabelle isoliert ist oder beeinträchtigt wird, werden alle Daten, die noch nicht in andere Regionen repliziert wurden, repliziert, sobald das Replikat fehlerfrei ist.

Wenn dasselbe Element in mehreren Regionen gleichzeitig geändert wird, löst DynamoDB den Konflikt, indem die Änderung mit dem neuesten internen Zeitstempel pro Element verwendet wird; diese Konfliktlösungsmethode wird als „Last Writer Wins“ bezeichnet. Letztendlich stimmt ein Element in allen Replikaten mit der Version überein, die beim letzten Schreibvorgang erstellt wurde.

[Strikt konsistente Lesevorgänge](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html#DDB-GetItem-request-ConsistentRead) geben die jeweils aktuelle Version eines Elements zurück, wenn dieses zuletzt in der Region aktualisiert wurde, in der der Lesevorgang stattgefunden hat. Hierbei können jedoch veraltete Daten zurückgegeben werden, wenn das Element zuletzt in einer anderen Region aktualisiert wurde. Bei bedingten Schreibvorgängen wird der Bedingungsausdruck mit der Version des Elements in der Region verglichen.

Sie erstellen eine globale MREC-Tabelle, indem Sie einer vorhandenen DynamoDB-Tabelle ein Replikat hinzufügen. Das Hinzufügen eines Replikats hat keine Auswirkungen auf die Leistung vorhandener DynamoDB-Tabellen mit einer einzigen Region oder von Replikaten globaler Tabellen. Sie können einer globalen MREC-Tabelle Replikate hinzufügen, um die Anzahl der Regionen zu erhöhen, in denen Daten repliziert werden, oder Replikate aus einer globalen MREC-Tabelle entfernen, wenn sie nicht mehr benötigt werden. Eine globale MREC-Tabelle kann ein Replikat in jeder Region haben, in der DynamoDB verfügbar ist, und sie kann so viele Replikate enthalten, wie es Regionen in der [AWS -Partition](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/partitions.html) gibt.

### Multi-Region Strong Consistency (MRSC)
<a name="V2globaltables_HowItWorks.consistency-modes.mrsc"></a>

Sie können bei der Erstellung einer globalen Tabelle den MRSC-Modus (Multi-Region Strong Consistency) konfigurieren. Elementänderungen im Replikat einer globalen MRSC-Tabelle werden synchron in mindestens eine andere Region repliziert, bevor der Schreibvorgang eine erfolgreiche Antwort zurückgibt. Strikt konsistente Lesevorgänge für ein beliebiges MRSC-Replikat geben immer die neueste Version eines Elements zurück. Bei bedingten Schreibvorgängen wird immer der Bedingungsausdruck mit der aktuellen Version des Elements verglichen.

Eine globale MRSC-Tabelle muss in genau drei Regionen bereitgestellt werden. Sie können eine globale MRSC-Tabelle mit drei Replikaten oder zwei Replikaten und einem Witness konfigurieren. Ein Zeuge ist eine Komponente einer globalen MRSC-Tabelle, die in globale Tabellenreplikate geschriebene Daten enthält und eine optionale Alternative zu einem vollständigen Replikat darstellt und gleichzeitig die Verfügbarkeitsarchitektur von MRSC unterstützt. Sie können für einen Witness keine Lese- oder Schreibvorgänge ausführen. Ein Witness befindet sich in einer anderen Region als die beiden Replikate. Wenn Sie eine globale MRSC-Tabelle erstellen, wählen Sie bei ihrer Erstellung die Regionen sowohl für die Bereitstellung der Replikate als auch für den Witness aus. Sie können anhand der Ausgabe der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)-API bestimmen, ob und in welcher Region für eine globale MRSC-Tabelle ein Witness konfiguriert ist. Der Zeuge gehört DynamoDB und wird von DynamoDB verwaltet, und der Zeuge wird nicht in Ihrem AWS Konto in der Region angezeigt, in der er konfiguriert ist.

Die globalen MRSC-Tabellen sind in den folgenden Regionsgruppen verfügbar: US-Regionengruppe (USA Ost Nord-Virginia, USA Ost-Ohio, USA West Oregon), EU-Regionengruppe (Europa Irland, Europa London, Europa Paris, Europa Frankfurt) und AP-Regionengruppe (Asien-Pazifik Tokio, Asien-Pazifik Seoul und Asien-Pazifik Osaka). Globale MRSC-Tabellen dürfen sich nicht über verschiedene Region-Sets erstrecken (z. B. darf eine globale MRSC-Tabelle nicht gleichzeitig Replikate aus US- und EU-Regionen enthalten).

Sie erstellen eine globale MRSC-Tabelle, indem Sie einer vorhandenen DynamoDB-Tabelle, die keine Daten enthält, ein Replikat und einen Witness oder zwei Replikate hinzufügen. Wenn Sie eine bestehende Tabelle mit einer einzigen Region in eine globale MRSC-Tabelle konvertieren, müssen Sie sicherstellen, dass die Tabelle leer ist. Die Konvertierung einer Tabelle mit nur einer Region in eine globale MRSC-Tabelle mit vorhandenen Elementen wird nicht unterstützt. Stellen Sie sicher, dass während des Konvertierungsvorgangs keine Daten in die Tabelle geschrieben werden. Sie können einer vorhandenen globalen MRSC-Tabelle keine zusätzlichen Replikate hinzufügen. Ein einzelnes Replikat oder ein Witness kann nicht aus einer globalen MRSC-Tabelle gelöscht werden. Sie können zwei Replikate oder ein Replikat und einen Witness aus einer globalen MRSC-Tabelle löschen und das verbleibende Replikat in eine DynamoDB-Tabelle mit einer einzigen Region umwandeln.

Bei einem Schreibvorgang tritt der Fehler `ReplicatedWriteConflictException` auf, wenn versucht wird, ein Element zu ändern, das bereits in einer anderen Region geändert wird. Schreibvorgänge, die mit dem fehlschlagen, `ReplicatedWriteConflictException` können wiederholt werden und sind erfolgreich, wenn das Element in einer anderen Region nicht mehr geändert wird.

Für globale MRSC-Tabellen gelten die folgenden Überlegungen:
+ Die Funktion „Time to Live“ (TTL) wird von globalen MRSC-Tabellen nicht unterstützt.
+ Lokale sekundäre Indizes (LSIs) werden für globale MRSC-Tabellen nicht unterstützt.
+ CloudWatch Contributor Insights-Informationen werden nur für die Region gemeldet, in der ein Vorgang stattgefunden hat.

## Auswählen eines Konsistenzmodus
<a name="V2globaltables_HowItWorks.choosing-consistency-mode"></a>

Das Hauptkriterium für die Auswahl eines Konsistenzmodus für mehrere Regionen ist, ob die Anwendung Schreibvorgängen mit geringer Latenz und strikt konsistente Lesevorgänge oder der globalen strikten Konsistenz Priorität einräumt.

Globale MREC-Tabellen weisen im Vergleich zu globalen MRSC-Tabellen Schreib- und strikt konsistente Lesevorgänge mit geringen Latenzen auf. Globale MREC-Tabellen haben ein Recovery Point Objective (RPO), das der Replikationsverzögerung zwischen Replikaten entspricht, die je nach Replikatregion in der Regel einige Sekunden beträgt.

In folgenden Fällen sollten Sie den MREC-Modus verwenden:
+ Ihre Anwendung kann veraltete Daten tolerieren, die von strikt konsistenten Lesevorgängen zurückgegeben werden, wenn diese Daten in einer anderen Region aktualisiert wurden.
+ Schreib- und strikt konsistente Lesevorgänge mit geringer Latenz haben Vorrang vor der Konsistenz von multiregionalen Lesevorgängen.
+ Gemäß Ihrer Strategie für Hochverfügbarkeit für mehrere Regionen ist ein RPO über null zulässig.

Globale MRSC-Tabellen weisen im Vergleich zu globalen MREC-Tabellen Schreib- und strikt konsistente Lesevorgänge mit höheren Latenzen auf. Globale MRSC-Tabellen unterstützen einen Recovery Point Objective (RPO) von null.

In folgenden Fällen sollten Sie den MRSC-Modus verwenden:
+ Sie benötigen strikt konsistente Lesevorgänge über mehrere Regionen hinweg.
+ Die globale Konsistenz von Lesevorgängen hat Vorrang gegenüber Schreibvorgängen mit geringer Latenz.
+ Gemäß Ihrer Strategie für Hochverfügbarkeit für mehrere Regionen ist ein RPO von null erforderlich.

## Überwachen globaler Tabellen
<a name="monitoring-global-tables"></a>

In globalen Tabellen, die für Multi-Region Eventual Consistency (MREC) konfiguriert sind, wird die Metrik veröffentlicht. [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency) CloudWatch Diese Metrik misst die verstrichene Zeit zwischen dem Schreiben eines Elements in eine Replikattabelle und dem Erscheinen dieses Elements in einem anderen Replikat in der globalen Tabelle. `ReplicationLatency` wird in Millisekunden ausgedrückt und für jedes Paar aus Quell- und Zielregion ausgegeben. 

Typische `ReplicationLatency` Werte hängen von der Entfernung zwischen den ausgewählten AWS Regionen sowie von anderen Variablen wie Workload-Typ und Durchsatz ab. Beispiel: Ein Quellreplikat in der Region USA West (Nordkalifornien) (us-west-1) weist im Vergleich zur Region Afrika (Kapstadt) (af-south-1) einen niedrigeren Wert für `ReplicationLatency` auf als die Region USA West (Oregon) (us-west-2).

Ein erhöhter Wert für `ReplicationLatency` könnte darauf hinweisen, dass Updates von einem Replikat nicht in einem angemessenen Zeitraum an andere Replikattabellen verteilt werden. In diesem Fall können Sie die Lese- und Schreibaktivität Ihrer Anwendung vorübergehend in eine andere AWS Region umleiten.

Globale Tabellen mit MRSC-Konfiguration veröffentlichen keine `ReplicationLatency`-Metrik.

## Testen mit Fehlerinjektionen
<a name="fault-injection-testing"></a>

Sowohl die globalen MREC- als auch die MRSC-Tabellen sind in den [AWSAWS Fault Injection Service](https://docs.aws.amazon.com/resilience-hub/latest/userguide/testing.html) (FIS) integriert, einen vollständig verwalteten Dienst zur Durchführung kontrollierter Fehlerinjektionsexperimente zur Verbesserung der Ausfallsicherheit einer Anwendung. Mit AWS FIS können Sie:
+ Erstellen Sie Versuchsvorlagen, die spezifische Fehlerszenarien definieren.
+ Injizieren Sie Fehler, um die Ausfallsicherheit von Anwendungen zu überprüfen, indem Sie die Regionsisolierung simulieren (d. h. die Replikation zu und von einem ausgewählten Replikat unterbrechen), um die Fehlerbehandlung, Wiederherstellungsmechanismen und das Verhalten bei Störungen in einer Region zu testen. AWS 

In einer globalen Tabelle mit Replikaten in USA Ost (Nord-Virginia), USA Ost (Ohio) und USA West (Oregon) können Sie beispielsweise ein Experiment in USA Ost (Ohio) durchführen, um die dortige Regionsisolierung zu testen, während USA Ost (Nord-Virginia) und USA West (Oregon) ihren normalen Betrieb fortsetzen. Diese kontrollierten Tests helfen Ihnen dabei, potenzielle Probleme zu identifizieren und zu lösen, bevor sie sich auf den Produktions-Workload auswirken. 

Eine vollständige Liste der von *AWS FIS unterstützten Aktionen und [regionsübergreifender Konnektivität zum Anhalten der DynamoDB-Replikation zwischen Regionen](https://docs.aws.amazon.com/fis/latest/userguide/cross-region-scenario.html) finden Sie unter [Aktionsziele](https://docs.aws.amazon.com/fis/latest/userguide/action-sequence.html#action-targets) im AWS FIS-Benutzerhandbuch*.

*Informationen zu globalen Tabellenaktionen von Amazon DynamoDB, die in AWS FIS verfügbar sind, finden Sie unter [DynamoDB Global Tables Actions Reference](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#dynamodb-actions-reference) im FIS-Benutzerhandbuch.AWS *

Informationen zu den ersten Schritten mit der Durchführung von Fault-Injection-Experimenten finden Sie unter [Planung Ihrer AWS FIS-Experimente im FIS-Benutzerhandbuch](https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html). AWS 

**Anmerkung**  
Bei AWS FIS Experimenten in MRSC sind eventuell konsistente Lesevorgänge zulässig, Aktualisierungen der Tabelleneinstellungen — wie z. B. das Ändern des Abrechnungsmodus oder die Konfiguration des Tabellendurchsatzes — sind jedoch nicht zulässig, ähnlich wie bei MREC. Weitere Informationen [`FaultInjectionServiceInducedErrors`](metrics-dimensions.md#FaultInjectionServiceInducedErrors)zum Fehlercode finden Sie in der CloudWatch Metrik.

## Time to Live (TTL)
<a name="global-tables-ttl"></a>

In globalen Tabellen mit MREC-Konfiguration kann die Konfiguration von [Time To Live](TTL.md) (TTL) gelöscht werden. Die TTL-Einstellungen werden automatisch für alle Replikate einer globalen Tabelle synchronisiert. Wenn TTL ein Element aus einem Replikat in einer Region löscht, wird der Löschvorgang auf alle anderen Replikate in der globalen Tabelle repliziert. TTL verbraucht keine Schreibkapazität; das Löschen von TTL wird Ihnen in der Region, in der der Löschvorgang stattgefunden hat, nicht in Rechnung gestellt. In allen anderen Regionen, deren globale Tabelle ein Replikat enthält, wird Ihnen jedoch der replizierte Löschvorgang in Rechnung gestellt.

Die Replikation eines TTL-Löschvorgangs verbraucht Schreibkapazität in den Replikaten, in die der Löschvorgang repliziert wird. Replikate, die für bereitgestellte Kapazität konfiguriert sind, können Anfragen drosseln, wenn die Kombination aus Schreibdurchsatz und TTL-Löschdurchsatz die bereitgestellte Schreibkapazität überschreitet.

Globale Tabellen mit MRSC-Konfiguration unterstützen die Konfiguration des TTL-Löschvorgangs nicht.

## Streams
<a name="global-tables-streams"></a>

Globale Tabellen mit MREC-Konfiguration replizieren Änderungen, indem sie diese aus einem [DynamoDB-Stream](Streams.md) in einer Replikattabelle auslesen und auf alle anderen Replikattabellen anwenden. Streams sind daher standardmäßig für alle Replikate in einer globalen MREC-Tabelle aktiviert und können in diesen Replikaten nicht deaktiviert werden. Der MREC-Replikationsprozess kann mehrere Änderungen in einem kurzen Zeitraum zu einem einzigen replizierten Schreibvorgang kombinieren, was dazu führt, dass der Stream jedes Replikats Datensätze enthält, die sich geringfügig unterscheiden. Streams-Datensätze in MREC-Replikaten werden immer elementweise sortiert, wobei die Reihenfolge zwischen den Elementen sich von Replikat zu Replikat unterscheiden kann.

Globale Tabellen mit MRSC-Konfiguration verwenden keine DynamoDB Streams für die Replikation, sodass Streams in MRSC-Replikaten standardmäßig nicht aktiviert sind. Streams können in einem MRSC-Replikat aktiviert werden. Streams-Datensätze in MRSC-Replikaten sind für jedes Replikat identisch, auch in Bezug auf ihre Reihenfolge.

Wenn Sie eine Anwendung schreiben möchten, die Streams-Datensätze für Änderungen verarbeitet, die in einer bestimmten Region, aber nicht in anderen Regionen in einer globalen Tabelle vorgenommen wurden, können Sie jedem Element ein Attribut hinzufügen, das definiert, in welcher Region die Änderung für dieses Element stattgefunden hat. Sie können dieses Attribut verwenden, um Streams-Datensätze nach Änderungen zu filtern, die in anderen Regionen aufgetreten sind und hierzu auch Lambda-Ereignisfilter verwenden, um Lambda-Funktionen nur für Änderungen in einer bestimmten Region aufzurufen.

## Transaktionen
<a name="global-tables-transactions"></a>

In einer globalen Tabelle mit MREC-Konfiguration sind DynamoDB-Transaktionsoperationen ([https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) und [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)) nur innerhalb der Region, in der der Vorgang aufgerufen wurde, unteilbar. Schreibtransaktionen werden nicht als Einheit regionsübergreifend repliziert, was bedeutet, dass nur einige Schreibvorgänge in einer Transaktion zu einem bestimmten Zeitpunkt durch Lesevorgänge in anderen Replikaten zurückgegeben werden können.

Wenn Sie beispielsweise eine globale Tabelle mit Replikaten in den Regionen USA Ost (Ohio) und USA West (Oregon) nutzen und eine `TransactWriteItems`-Operation in der Region USA Ost (Ohio) durchführen, sind unter Umständen partiell durchgeführte Transaktionen in der Region USA West (Oregon) zu beobachten, während die Änderungen repliziert werden. Die Änderungen werden erst in die anderen Regionen repliziert, nachdem sie in der Quellregion in die Datenbank eingetragen wurden.

Globale Tabellen mit MRSC-Konfiguration unterstützen keine Transaktionsvorgänge und geben einen Fehler zurück, wenn solche Operationen in einem MRSC-Replikat aufgerufen werden.

## Lese- und Schreibdurchsatz
<a name="V2globaltables_HowItWorks.Throughput"></a>

### Modus bereitgestellter Kapazität
<a name="gt_throughput.provisioned"></a>

Eine Replikation verbraucht Schreibkapazität. Replikate, die für bereitgestellte Kapazität konfiguriert sind, können Anfragen drosseln, wenn die Kombination aus Anwendungsschreibdurchsatz und Replikationsschreibdurchsatz die bereitgestellte Schreibkapazität übersteigt. Bei globalen Tabellen, die den Bereitstellungsmodus verwenden, werden die Auto Scaling-Einstellungen für Lese- und Schreibkapazitäten zwischen den Replikaten synchronisiert.

Sie können die Lesekapazitätseinstellungen für jedes Replikat in einer globalen Tabelle unabhängig konfigurieren, indem Sie den [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html)Parameter auf Replikatebene verwenden. Standardmäßig werden Änderungen an der bereitgestellten Lesekapazität auf alle Replikate in der globalen Tabelle angewendet. Beim Hinzufügen eines neuen Replikats zu einer globalen Tabelle wird die Lesekapazität der Quelltabelle oder des Replikats als Anfangswert verwendet, sofern nicht ausdrücklich eine Überschreibung auf Replikatebene angegeben ist.

### On-Demand-Modus
<a name="gt_throughput.on-demand"></a>

Bei globalen Tabellen, die für den On-Demand-Modus konfiguriert sind, wird die Schreibkapazität automatisch über alle Replikate hinweg synchronisiert. DynamoDB passt die Kapazität automatisch an den Datenverkehr an, und es müssen keine replikatspezifischen Lese- oder Schreibkapazitätseinstellungen verwaltet werden.

## Synchronisierung von Einstellungen
<a name="V2globaltables_HowItWorks.setting-synchronization"></a>

Einstellungen in globalen DynamoDB-Tabellen sind Konfigurationsparameter, mit denen verschiedene Aspekte des Tabellenverhaltens und der Replikation gesteuert werden können. Diese Einstellungen werden über die DynamoDB-Steuerebene verwaltet APIs und können beim Erstellen oder Ändern globaler Tabellen konfiguriert werden. In globale Tabellen werden bestimmte Einstellungen für alle Replikate automatisch synchronisiert, um die Konsistenz zu wahren und gleichzeitig Flexibilität für regionsspezifische Optimierungen zu ermöglichen. Wenn Sie wissen, welche Einstellungen synchronisiert werden und wie sich diese verhalten, können Sie Ihre globale Tabelle effizient konfigurieren. Je nach Art ihrer replikatsübergreifenden Synchronisation lassen sich diese Einstellungen in drei Hauptkategorien unterteilen.

Die folgenden Einstellungen werden immer zwischen Replikaten in einer globalen Tabelle synchronisiert:
+ Kapazitätsmodus (bereitgestellte oder On-Demand-Kapazität)
+ Bereitgestellte Schreibkapazität der Tabelle
+ Schreib-Auto-Scaling der Tabelle
+ Attributdefinition des Schlüsselschemas
+ Definition des globalen sekundären Index (GSI)
+ Bereitgestellte Schreibkapazität des GSI
+ Schreib-Auto-Scaling des GSI
+ Typ der serverseitigen Verschlüsselung (Server-Side Encryption, SSE)
+ Streams-Definition im MREC-Modus
+ Time to Live (TTL)
+ Warmdurchsatz
+ Maximaler On-Demand-Schreibdurchsatz

Die folgenden Einstellungen werden zwischen Replikaten synchronisiert, können jedoch für ein Replikat außer Kraft gesetzt werden:
+ Von der Tabelle bereitgestellte Lesekapazität
+ Auto-Scaling für Tabellenlesevorgänge
+ Vom GSI bereitgestellte Lesekapazität
+ Auto-Scaling für GSI-Lesevorgänge
+ Tabellenklasse
+ Maximaler On-Demand-Lesedurchsatz

**Anmerkung**  
Überschreibbare Werte werden geändert, wenn die Einstellung in einem anderen Replikat geändert wird. Sie haben zum Beispiel eine globale MREC-Tabelle mit Replikaten in USA Ost (Nord-Virginia) und USA West (Oregon). Für das Replikat „USA Ost“ (Nord-Virginia) wurde ein Lesedurchsatz von 200 bereitgestellt. RCUs Für das Replikat in der Region USA West (Oregon) wurde der bereitgestellte Lesedurchsatz auf 100 festgelegt. RCUs Wenn Sie die Einstellung für den bereitgestellten Lesedurchsatz auf dem Replikat USA Ost (Nord-Virginia) von 200 RCUs auf 300 aktualisieren RCUs, wird der neue Wert für den bereitgestellten Lesedurchsatz auch auf das Replikat in USA West (Oregon) angewendet. Dadurch wird die Einstellung für den bereitgestellten Lesedurchsatz für das Replikat USA West (Oregon) vom überschriebenen Wert 100 auf den neuen Wert 300 geändert. RCUs RCUs

Die folgenden Einstellungen werden niemals zwischen Replikaten in einer globalen Tabelle synchronisiert:
+ Löschschutz
+ Point-in-time Wiederherstellung
+ Tags (Markierungen)
+ Aktivierung von Table CloudWatch Contributor Insights
+ Aktivierung von GSI Contributor Insights CloudWatch 
+ Definition der Kinesis-Datenströme
+ Ressourcenrichtlinien
+ Streams-Definition im MREC-Modus

Alle anderen Einstellungen werden nicht zwischen Replikaten synchronisiert.

## DynamoDB Accelerator (DAX)
<a name="V2globaltables_HowItWorks.dax"></a>

Bei Schreibvorgängen in Replikate von globalen Tabellen wird DynamoDB unter Umgehung von DynamoDB Accelerator (DAX) direkt aktualisiert. In der Folge kann es zu veralteten DAX-Caches kommen, da der DAX-Cache nicht durch die Schreibvorgänge aktualisiert wird. DAX-Caches, die für Replikate von globalen Tabellen konfiguriert sind, werden erst bei Ablauf der TTL des Cache aktualisiert.

## Überlegungen zur Verwaltung globaler Tabellen
<a name="management-considerations"></a>

Sie können eine Tabelle, die zum Hinzufügen des neuen Replikats einer globalen Tabelle verwendet wurde, erst 24 Stunden nach der Erstellung des neuen Replikats löschen.

Wenn Sie eine AWS Region deaktivieren, die globale Tabellenreplikate enthält, werden diese Replikate 20 Stunden nach der Deaktivierung der Region dauerhaft in Tabellen mit nur einer Region konvertiert.

# Tutorials: Erstellen von globalen Tabellen
<a name="V2globaltables.tutorial"></a>

Dieser Abschnitt enthält step-by-step Anweisungen zum Erstellen globaler DynamoDB-Tabellen, die für Ihren bevorzugten Konsistenzmodus konfiguriert sind. Wählen Sie je nach Anforderungen der Anwendung entweder den Modus „Multi-Region Eventual Consistency (MREC)“ oder „Multi-Region Strong Consistency (MRSC)“ aus.

Globale MREC-Tabellen bieten eine geringere Schreiblatenz und sorgen letztendlich für Konsistenz über alle AWS-Regionen hinweg. Globale MRSC-Tabellen bieten strikt konsistente Lesevorgänge in allen Regionen und ermöglichen etwas höhere Schreiblatenzen als MREC-Tabellen. Wählen Sie den Konsistenzmodus, der den Anforderungen Ihrer Anwendung an Datenkonsistenz, Latenz und Verfügbarkeit am ehesten entspricht.

**Topics**
+ [Erstellen einer globalen Tabelle, die für den MREC-Modus konfiguriert ist](#V2creategt_mrec)
+ [Erstellen einer globalen Tabelle, die für den MRSC-Modus konfiguriert ist](#create-gt-mrsc)

## Erstellen einer globalen Tabelle, die für den MREC-Modus konfiguriert ist
<a name="V2creategt_mrec"></a>

In diesem Abschnitt erfahren Sie, wie Sie eine globale Tabelle im MREC-Modus (Multi-Region Eventual Consistency) erstellen. MREC ist der Standard-Konsistenzmodus für globale Tabellen und ermöglicht Schreibvorgänge mit geringer Latenz und asynchroner Replikation über alle AWS-Regionen hinweg. Änderungen, die in einer Region an einem Element vorgenommen werden, werden in der Regel innerhalb einer Sekunde auf alle anderen Regionen repliziert. Dadurch eignet sich der MREC-Modus ideal für Anwendungen, die einer geringen Schreiblatenz Priorität einräumen und tolerieren können, dass aus verschiedenen Regionen kurzzeitig Datenversionen mit geringen Unterschieden zurückgegeben werden.

Sie können globale MREC-Tabellen mit Replikaten in jeder AWS Region erstellen, in der DynamoDB verfügbar ist, und jederzeit Replikate hinzufügen oder entfernen. In den folgenden Beispielen wird gezeigt, wie eine globale DynamoDB-Tabelle mit Replikaten in mehreren Regionen erstellt wird.

### Erstellen einer globalen Tabelle im MREC-Modus mit der DynamoDB-Konsole
<a name="mrec-console"></a>

Gehen Sie wie folgt vor, um eine globale Tabelle mit der AWS-Managementkonsole zu erstellen. Im folgenden Beispiel wird eine globale Tabelle mit Replikattabellen in den USA und Europa erstellt.

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie für dieses Beispiel in der Regionsauswahl in der Navigationsleiste die Region **USA Ost (Ohio)** aus.

1. Klicken Sie im Navigationsbereich auf der linken Seite der Konsole auf **Tabellen**.

1. Wählen Sie **Tabelle erstellen** aus.

1. Gehen Sie auf der Seite **Tabelle erstellen** wie folgt vor:

   1. Geben Sie unter **Tabellenname** **Music** ein.

   1. Geben Sie unter **Partitionsschlüssel** den Wert **Artist** ein.

   1. Geben Sie unter **(Sortierschlüssel)** den Wert **SongTitle** ein.

   1. Behalten Sie die übrigen Standardeinstellungen bei und wählen Sie **Tabelle erstellen** aus.

      Diese neue Tabelle dient als erste Replikattabelle in einer neuen globalen Tabelle. Sie stellt den Prototyp für andere Replikattabellen dar, die Sie später hinzufügen.

1. Gehen Sie folgendermaßen vor, wenn die Tabelle aktiv wird:

   1. Wählen Sie in der Tabellenliste die Tabelle **Musik** aus.

   1. Wählen Sie die Registerkarte **Globale Tabellen** aus.

   1. Wählen Sie die Option **Replikat erstellen** aus.

1. Wählen Sie in der Dropdown-Liste **Verfügbare Replikationsregionen** den Eintrag **USA West (Oregon) us-west-2** aus.

   Die Konsole stellt sicher, dass die ausgewählte Region keine Tabelle mit demselben Namen enthält. Wenn eine Tabelle mit demselben Namen vorhanden ist, müssen Sie die vorhandene Tabelle löschen, bevor Sie eine neue Replikattabelle in der betreffenden Region erstellen können.

1. Wählen Sie die Option **Replikat erstellen** aus. Dies startet den Prozess der Erstellung von Tabellen in der Region „USA West (Oregon) us-west-2“.

   Die Registerkarte **Globale Tabelle** für die Tabelle **Music** (und für alle anderen Replikattabellen) zeigt, dass die Tabelle in mehreren Regionen repliziert wurde.

1. Fügen Sie eine weitere Region hinzu, indem Sie die vorherigen Schritte wiederholen, aber als Region **Europa (Frankfurt) eu-central-1** auswählen.

1. So testen Sie die Replikation:

   1. Stellen Sie sicher, dass Sie die AWS-Managementkonsole Region USA Ost (Ohio) verwenden.

   1. Wählen Sie **Tabellenelemente erkunden** aus.

   1. Wählen Sie **Element erstellen** aus.

   1. Geben Sie **item\$11** für **Künstler** und **Song Value 1** für ein **SongTitle**.

   1. Wählen Sie **Element erstellen** aus.

1. Überprüfen Sie die Replikation, indem Sie zu den anderen Regionen wechseln:

   1. Wählen Sie in der Regionsauswahl in der rechten oberen Ecke **Europa (Frankfurt)** aus.

   1. Vergewissern Sie sich, dass die Tabelle **Music** das von Ihnen erstellte Objekt enthält.

   1. Wiederholen Sie die Überprüfung für **USA West (Oregon)**.

### Erstellen einer globalen MREC-Tabelle mit AWS CLI oder Java
<a name="mrec-cli-java"></a>

------
#### [ CLI ]

Das folgende Codebeispiel zeigt, wie globale DynamoDB-Tabellen mit letztendlicher multiregionaler Konsistenz (Multi-Region Eventual Consistency, MREC) verwaltet werden.
+ Erstellen Sie eine Tabelle mit multiregionaler Replikation (MREC).
+ Fügen Sie Elemente in eine Replikattabelle ein und rufen Sie sie ab.
+ Entfernen Sie Replikate one-by-one.
+ Führen Sie eine Bereinigung durch Löschen der Tabelle aus.

**AWS CLI mit Bash-Skript**  
Erstellen Sie eine Tabelle mit multiregionaler Replikation.  

```
# Step 1: Create a new table (MusicTable) in US East (Ohio), with DynamoDB Streams enabled (NEW_AND_OLD_IMAGES)
aws dynamodb create-table \
    --table-name MusicTable \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
    --region us-east-2

# Step 2: Create an identical MusicTable table in US East (N. Virginia)
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Create": {
        "RegionName": "us-east-1"
      }
    }
  ]
}' \
--region us-east-2

# Step 3: Create a table in Europe (Ireland)
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Create": {
        "RegionName": "eu-west-1"
      }
    }
  ]
}' \
--region us-east-2
```
Beschreiben Sie die multiregionale Tabelle.  

```
# Step 4: View the list of replicas created using describe-table
aws dynamodb describe-table \
    --table-name MusicTable \
    --region us-east-2 \
    --query 'Table.{TableName:TableName,TableStatus:TableStatus,MultiRegionConsistency:MultiRegionConsistency,Replicas:Replicas[*].{Region:RegionName,Status:ReplicaStatus}}'
```
Fügen Sie Elemente in eine Replikattabelle ein.  

```
# Step 5: To verify that replication is working, add a new item to the Music table in US East (Ohio)
aws dynamodb put-item \
    --table-name MusicTable \
    --item '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-2
```
Rufen Sie Elemente aus Replikattabellen ab.  

```
# Step 6: Wait for a few seconds, and then check to see whether the item has been 
# successfully replicated to US East (N. Virginia) and Europe (Ireland)
aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-1

aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region eu-west-1
```
Entfernen Sie Replikate.  

```
# Step 7: Delete the replica table in Europe (Ireland) Region
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Delete": {
        "RegionName": "eu-west-1"
      }
    }
  ]
}' \
--region us-east-2

# Delete the replica table in US East (N. Virginia) Region
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Delete": {
        "RegionName": "us-east-1"
      }
    }
  ]
}' \
--region us-east-2
```
Führen Sie eine Bereinigung durch Löschen der Tabelle aus.  

```
# Clean up: Delete the primary table
aws dynamodb delete-table --table-name MusicTable --region us-east-2

echo "Global table demonstration complete."
```
+ Weitere API-Informationen finden Sie in den folgenden Themen der *AWS CLI -Befehlsreferenz*.
  + [CreateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/PutItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateTable)

------
#### [ Java ]

Im folgenden Codebeispiel wird gezeigt, wie globale DynamoDB-Tabellen mit Replikaten in mehreren Regionen erstellt und verwaltet werden.
+ Erstellen Sie eine Tabelle mit einem globalen sekundären Index und DynamoDB Streams.
+ Fügen Sie Replikate in verschiedenen Regionen hinzu, um eine globale Tabelle zu erstellen.
+ Entfernen Sie Replikate aus einer globalen Tabelle.
+ Fügen Sie Testelemente hinzu, um die regionsübergreifende Replikation zu überprüfen.
+ Beschreiben Sie die globale Tabellenkonfiguration und den Replikatstatus.

**SDK für Java 2.x**  
Erstellen Sie eine Tabelle mit Global Secondary Index und DynamoDB Streams mithilfe von. AWS SDK for Java 2.x  

```
    public static CreateTableResponse createTableWithGSI(
        final DynamoDbClient dynamoDbClient, final String tableName, final String indexName) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (indexName == null || indexName.trim().isEmpty()) {
            throw new IllegalArgumentException("Index name cannot be null or empty");
        }

        try {
            LOGGER.info("Creating table: " + tableName + " with GSI: " + indexName);

            CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .tableName(tableName)
                .attributeDefinitions(
                    AttributeDefinition.builder()
                        .attributeName("Artist")
                        .attributeType(ScalarAttributeType.S)
                        .build(),
                    AttributeDefinition.builder()
                        .attributeName("SongTitle")
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(
                    KeySchemaElement.builder()
                        .attributeName("Artist")
                        .keyType(KeyType.HASH)
                        .build(),
                    KeySchemaElement.builder()
                        .attributeName("SongTitle")
                        .keyType(KeyType.RANGE)
                        .build())
                .billingMode(BillingMode.PAY_PER_REQUEST)
                .globalSecondaryIndexes(GlobalSecondaryIndex.builder()
                    .indexName(indexName)
                    .keySchema(KeySchemaElement.builder()
                        .attributeName("SongTitle")
                        .keyType(KeyType.HASH)
                        .build())
                    .projection(
                        Projection.builder().projectionType(ProjectionType.ALL).build())
                    .build())
                .streamSpecification(StreamSpecification.builder()
                    .streamEnabled(true)
                    .streamViewType(StreamViewType.NEW_AND_OLD_IMAGES)
                    .build())
                .build();

            CreateTableResponse response = dynamoDbClient.createTable(createTableRequest);
            LOGGER.info("Table creation initiated. Status: "
                + response.tableDescription().tableStatus());

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to create table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Warten Sie, bis eine Tabelle aktiv wird mit. AWS SDK for Java 2.x  

```
    public static void waitForTableActive(final DynamoDbClient dynamoDbClient, final String tableName) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }

        try {
            LOGGER.info("Waiting for table to become active: " + tableName);

            try (DynamoDbWaiter waiter =
                DynamoDbWaiter.builder().client(dynamoDbClient).build()) {
                DescribeTableRequest request =
                    DescribeTableRequest.builder().tableName(tableName).build();

                waiter.waitUntilTableExists(request);
                LOGGER.info("Table is now active: " + tableName);
            }

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to wait for table to become active: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Fügen Sie ein Replikat hinzu, um eine globale Tabelle zu erstellen oder zu erweitern mit AWS SDK for Java 2.x.  

```
    public static UpdateTableResponse addReplica(
        final DynamoDbClient dynamoDbClient,
        final String tableName,
        final Region replicaRegion,
        final String indexName,
        final Long readCapacity) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (replicaRegion == null) {
            throw new IllegalArgumentException("Replica region cannot be null");
        }
        if (indexName == null || indexName.trim().isEmpty()) {
            throw new IllegalArgumentException("Index name cannot be null or empty");
        }
        if (readCapacity == null || readCapacity <= 0) {
            throw new IllegalArgumentException("Read capacity must be a positive number");
        }

        try {
            LOGGER.info("Adding replica in region: " + replicaRegion.id() + " for table: " + tableName);

            // Create a ReplicationGroupUpdate for adding a replica
            ReplicationGroupUpdate replicationGroupUpdate = ReplicationGroupUpdate.builder()
                .create(builder -> builder.regionName(replicaRegion.id())
                    .globalSecondaryIndexes(ReplicaGlobalSecondaryIndex.builder()
                        .indexName(indexName)
                        .provisionedThroughputOverride(ProvisionedThroughputOverride.builder()
                            .readCapacityUnits(readCapacity)
                            .build())
                        .build())
                    .build())
                .build();

            UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .tableName(tableName)
                .replicaUpdates(replicationGroupUpdate)
                .build();

            UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest);
            LOGGER.info("Replica addition initiated in region: " + replicaRegion.id());

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add replica in region: " + replicaRegion.id() + " - " + e.getMessage());
            throw e;
        }
    }
```
Entfernen Sie ein Replikat aus einer globalen Tabelle mit. AWS SDK for Java 2.x  

```
    public static UpdateTableResponse removeReplica(
        final DynamoDbClient dynamoDbClient, final String tableName, final Region replicaRegion) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (replicaRegion == null) {
            throw new IllegalArgumentException("Replica region cannot be null");
        }

        try {
            LOGGER.info("Removing replica in region: " + replicaRegion.id() + " for table: " + tableName);

            // Create a ReplicationGroupUpdate for removing a replica
            ReplicationGroupUpdate replicationGroupUpdate = ReplicationGroupUpdate.builder()
                .delete(builder -> builder.regionName(replicaRegion.id()).build())
                .build();

            UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .tableName(tableName)
                .replicaUpdates(replicationGroupUpdate)
                .build();

            UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest);
            LOGGER.info("Replica removal initiated in region: " + replicaRegion.id());

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to remove replica in region: " + replicaRegion.id() + " - " + e.getMessage());
            throw e;
        }
    }
```
Fügen Sie Testelemente hinzu, um die Replikation mithilfe von AWS SDK for Java 2.x zu überprüfen.  

```
    public static PutItemResponse putTestItem(
        final DynamoDbClient dynamoDbClient, final String tableName, final String artist, final String songTitle) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (artist == null || artist.trim().isEmpty()) {
            throw new IllegalArgumentException("Artist cannot be null or empty");
        }
        if (songTitle == null || songTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("Song title cannot be null or empty");
        }

        try {
            LOGGER.info("Adding test item to table: " + tableName);

            Map<String, software.amazon.awssdk.services.dynamodb.model.AttributeValue> item = new HashMap<>();
            item.put(
                "Artist",
                software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder()
                    .s(artist)
                    .build());
            item.put(
                "SongTitle",
                software.amazon.awssdk.services.dynamodb.model.AttributeValue.builder()
                    .s(songTitle)
                    .build());

            PutItemRequest putItemRequest =
                PutItemRequest.builder().tableName(tableName).item(item).build();

            PutItemResponse response = dynamoDbClient.putItem(putItemRequest);
            LOGGER.info("Test item added successfully");

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add test item to table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Beschreiben Sie die globale Tabellenkonfiguration und die Verwendung von AWS SDK for Java 2.x Replikaten.  

```
    public static DescribeTableResponse describeTable(final DynamoDbClient dynamoDbClient, final String tableName) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }

        try {
            LOGGER.info("Describing table: " + tableName);

            DescribeTableRequest request =
                DescribeTableRequest.builder().tableName(tableName).build();

            DescribeTableResponse response = dynamoDbClient.describeTable(request);

            LOGGER.info("Table status: " + response.table().tableStatus());
            if (response.table().replicas() != null
                && !response.table().replicas().isEmpty()) {
                LOGGER.info("Number of replicas: " + response.table().replicas().size());
                response.table()
                    .replicas()
                    .forEach(replica -> LOGGER.info(
                        "Replica region: " + replica.regionName() + ", Status: " + replica.replicaStatus()));
            }

            return response;

        } catch (ResourceNotFoundException e) {
            LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage());
            throw e;
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Vollständiges Beispiel für globale Tabellenoperationen unter Verwendung von AWS SDK for Java 2.x.  

```
    public static void exampleUsage(final Region sourceRegion, final Region replicaRegion) {

        String tableName = "Music";
        String indexName = "SongTitleIndex";
        Long readCapacity = 15L;

        // Create DynamoDB client for the source region
        try (DynamoDbClient dynamoDbClient =
            DynamoDbClient.builder().region(sourceRegion).build()) {

            try {
                // Step 1: Create the initial table with GSI and streams
                LOGGER.info("Step 1: Creating table in source region: " + sourceRegion.id());
                createTableWithGSI(dynamoDbClient, tableName, indexName);

                // Step 2: Wait for table to become active
                LOGGER.info("Step 2: Waiting for table to become active");
                waitForTableActive(dynamoDbClient, tableName);

                // Step 3: Add replica in destination region
                LOGGER.info("Step 3: Adding replica in region: " + replicaRegion.id());
                addReplica(dynamoDbClient, tableName, replicaRegion, indexName, readCapacity);

                // Step 4: Wait a moment for replica creation to start
                Thread.sleep(5000);

                // Step 5: Describe table to view replica information
                LOGGER.info("Step 5: Describing table to view replicas");
                describeTable(dynamoDbClient, tableName);

                // Step 6: Add a test item to verify replication
                LOGGER.info("Step 6: Adding test item to verify replication");
                putTestItem(dynamoDbClient, tableName, "TestArtist", "TestSong");

                LOGGER.info("Global table setup completed successfully!");
                LOGGER.info("You can verify replication by checking the item in region: " + replicaRegion.id());

                // Step 7: Remove replica and clean up table
                LOGGER.info("Step 7: Removing replica from region: " + replicaRegion.id());
                removeReplica(dynamoDbClient, tableName, replicaRegion);
                DeleteTableResponse deleteTableResponse = dynamoDbClient.deleteTable(
                    DeleteTableRequest.builder().tableName(tableName).build());
                LOGGER.info("MREC global table demonstration completed successfully!");

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Thread was interrupted", e);
            } catch (DynamoDbException e) {
                LOGGER.severe("DynamoDB operation failed: " + e.getMessage());
                throw e;
            }
        }
    }
```
+ Weitere API-Informationen finden Sie in den folgenden Themen der *AWS SDK for Java 2.x -API-Referenz*.
  + [CreateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/CreateTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DescribeTable)
  + [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateTable)

------

## Erstellen einer globalen Tabelle, die für den MRSC-Modus konfiguriert ist
<a name="create-gt-mrsc"></a>

In diesem Abschnitt erfahren Sie, wie Sie eine globale Tabelle im MRSC-Modus (Multi-Region Strong Consistency) erstellen. Globale MRSC-Tabellen replizieren geänderte Elemente synchron über Regionen hinweg und stellen so sicher, dass durch strikt konsistente Lesevorgänge in jedem Replikat immer die aktuelle Version eines Elements zurückgegeben wird. Wenn Sie eine Tabelle mit einer einzigen Region in eine globale MRSC-Tabelle konvertieren, müssen Sie sicherstellen, dass die Tabelle leer ist. Die Konvertierung einer Tabelle mit nur einer Region in eine globale MRSC-Tabelle mit vorhandenen Elementen wird nicht unterstützt. Stellen Sie sicher, dass während des Konvertierungsvorgangs keine Daten in die Tabelle geschrieben werden.

Sie können eine globale MRSC-Tabelle mit drei Replikaten oder zwei Replikaten und einem Witness konfigurieren. Beim Erstellen einer globalen MRSC-Tabelle wählen Sie die Regionen aus, in denen Replikate und ein optionaler Witness bereitgestellt werden. Im folgenden Beispiel wird eine globale MRSC-Tabelle mit Replikaten in den Regionen USA Ost (Nord-Virginia) und USA Ost (Ohio) und einem Witness in der Region USA West (Oregon) erstellt.

**Anmerkung**  
Stellen Sie vor dem Erstellen einer globalen Tabelle sicher, dass die Service-Quota-Durchsatzgrenzwerte in allen Zielregionen einheitlich sind, da dies für die Erstellung einer globalen Tabelle erforderlich ist. Weitere Informationen zu den Grenzwerten für den Durchsatz für globale Tabellen finden Sie unter [Globale Tabellenkontingente](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ServiceQuotas.html#gt-limits-throughput).

### Erstellen einer globalen Tabelle im MRSC-Modus mit der DynamoDB-Konsole
<a name="mrsc_console"></a>

Gehen Sie wie folgt vor, um eine globale Tabelle mit der AWS-Managementkonsole zu erstellen.

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie in der Navigationsleiste Regionsauswahl eine Region aus, in der globale Tabellen mit MRSC [unterstützt werden](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes), wie z. B. **us-east-2**.

1. Wählen Sie im Navigationsbereich **Tables** (Tabellen) aus.

1. Wählen Sie **Create table** (Tabelle erstellen) aus.

1. Gehen Sie auf der Seite **Tabelle erstellen** wie folgt vor:

   1. Geben Sie unter **Tabellenname** **Music** ein.

   1. Geben Sie unter **Partitionsschlüssel** den Wert **Artist** ein und behalten Sie die Standardeinstellung **Zeichenfolge** bei.

   1. Geben Sie unter **Sortierschlüssel** den Wert **SongTitle** ein und behalten Sie die Standardeinstellung **Zeichenfolge** bei.

   1. Behalten Sie die übrigen Standardeinstellungen bei und wählen Sie **Tabelle erstellen** aus.

      Diese neue Tabelle dient als erste Replikattabelle in einer neuen globalen Tabelle. Sie stellt den Prototyp für andere Replikattabellen dar, die Sie später hinzufügen.

1. Warten Sie, bis die Tabelle aktiv wird, und wählen Sie sie dann aus der Tabellenliste aus.

1. Wählen Sie die Registerkarte **Globale Tabellen** und anschließend **Replikat erstellen** aus.

1. Gehen Sie auf der Seite **Replikat erstellen** wie folgt vor:

   1. Wählen Sie unter **Multiregionale Konsistenz** die Option **Starke Konsistenz** aus.

   1. Wählen Sie unter **Replikationsregion 1** die Option **US East (N. Virginia) us-east-1** aus.

   1. Wählen Sie unter **Replikationsregion 2** die Option **US West (Oregon) us-west-2** aus.

   1. Aktivieren Sie Option **Als Witness konfigurieren** für die Region „USA West (Oregon)“.

   1. Wählen Sie die Option **Replikat erstellen** aus.

1. Warten Sie, bis der Vorgang zur Erstellung des Replikats und des Witness abgeschlossen ist. Der Replikatstatus lautet **Aktiv**, wenn die Tabelle einsatzbereit ist.

### Erstellen einer globalen MRSC-Tabelle mit oder Java AWS CLI
<a name="mrsc-cli-java"></a>

Bevor Sie beginnen, stellen Sie sicher, dass Ihr IAM-Prinzipal über die erforderlichen Berechtigungen verfügt, um eine globale MRSC-Tabelle mit einer Witness-Region zu erstellen.

Mit der folgenden IAM-Beispielrichtlinie können Sie eine DynamoDB-Tabelle (`MusicTable`) in der Region „USA Ost (Ohio)“ mit einem Replikat in der Region „USA Ost (Nord-Virginia)“ und einer Witness-Region in der Region „USA West (Oregon)“ erstellen:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:CreateTable",
                "dynamodb:CreateTableReplica",
                "dynamodb:CreateGlobalTableWitness",
                "dynamodb:DescribeTable",
                "dynamodb:UpdateTable",
                "dynamodb:DeleteTable",
                "dynamodb:DeleteTableReplica",
                "dynamodb:DeleteGlobalTableWitness",
                "dynamodb:Scan",
                "dynamodb:Query",
                "dynamodb:UpdateItem",
                "dynamodb:PutItem",
                "dynamodb:GetItem",
                "dynamodb:DeleteItem",
                "dynamodb:BatchWriteItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:us-east-1:123456789012:table/MusicTable",
                "arn:aws:dynamodb:us-east-2:123456789012:table/MusicTable",
                "arn:aws:dynamodb:us-west-2:123456789012:table/MusicTable"
            ]
        },
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "arn:aws:iam::*:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication",
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": "replication.dynamodb.amazonaws.com"
                }
            }
        }
    ]
}
```

------

In den folgenden Codebeispielen wird gezeigt, wie globale DynamoDB-Tabellen mit Multi-Region Strong Consistency (MRSC) erstellt und verwaltet werden.
+ Erstellen einer Tabelle mit multiregionaler starker Konsistenz
+ Überprüfen Sie die MRSC-Konfiguration und den Replikatstatus.
+ Testen Sie die starke Konsistenz in allen Regionen mit sofortigen Lesevorgängen.
+ Führen Sie bedingte Schreibvorgänge mit MRSC-Garantien durch.
+ Bereinigen Sie die globalen MRSC-Tabellenressourcen.

------
#### [ Bash ]

**AWS CLI mit Bash-Skript**  
Erstellen Sie eine Tabelle mit multiregionaler starker Konsistenz (Multiregion Strong Consistency, MRSC).  

```
# Step 1: Create a new table in us-east-2 (primary region for MRSC)
# Note: Table must be empty when enabling MRSC
aws dynamodb create-table \
    --table-name MusicTable \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --region us-east-2

# Wait for table to become active
aws dynamodb wait table-exists --table-name MusicTable --region us-east-2

# Step 2: Add replica and witness with Multi-Region Strong Consistency
# MRSC requires exactly three replicas in supported regions
aws dynamodb update-table \
    --table-name MusicTable \
    --replica-updates '[{"Create": {"RegionName": "us-east-1"}}]' \
    --global-table-witness-updates '[{"Create": {"RegionName": "us-west-2"}}]' \
    --multi-region-consistency STRONG \
    --region us-east-2
```
Überprüfen Sie die MRSC-Konfiguration und den Replikatstatus.  

```
# Verify the global table configuration and MRSC setting
aws dynamodb describe-table \
    --table-name MusicTable \
    --region us-east-2 \
    --query 'Table.{TableName:TableName,TableStatus:TableStatus,MultiRegionConsistency:MultiRegionConsistency,Replicas:Replicas[*],GlobalTableWitnesses:GlobalTableWitnesses[*].{Region:RegionName,Status:ReplicaStatus}}'
```
Testen Sie die starke Konsistenz mit sofortigen Lesevorgängen in allen Regionen.  

```
# Write an item to the primary region
aws dynamodb put-item \
    --table-name MusicTable \
    --item '{"Artist": {"S":"The Beatles"},"SongTitle": {"S":"Hey Jude"},"Album": {"S":"The Beatles 1967-1970"},"Year": {"N":"1968"}}' \
    --region us-east-2

# Read the item from replica region to verify strong consistency (cannot read or write to witness)
# No wait time needed - MRSC provides immediate consistency
echo "Reading from us-east-1 (immediate consistency):"
aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"The Beatles"},"SongTitle": {"S":"Hey Jude"}}' \
    --consistent-read \
    --region us-east-1
```
Führen Sie bedingte Schreibvorgänge mit MRSC-Garantien durch.  

```
# Perform a conditional update from a different region
# This demonstrates that conditions work consistently across all regions
aws dynamodb update-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"The Beatles"},"SongTitle": {"S":"Hey Jude"}}' \
    --update-expression "SET #rating = :rating" \
    --condition-expression "attribute_exists(Artist)" \
    --expression-attribute-names '{"#rating": "Rating"}' \
    --expression-attribute-values '{":rating": {"N":"5"}}' \
    --region us-east-1
```
Bereinigen Sie die globalen MRSC-Tabellenressourcen.  

```
# Remove replica tables (must be done before deleting the primary table)
aws dynamodb update-table \
    --table-name MusicTable \
    --replica-updates '[{"Delete": {"RegionName": "us-east-1"}}]' \
    --global-table-witness-updates '[{"Delete": {"RegionName": "us-west-2"}}]' \
    --region us-east-2

# Wait for replicas to be deleted
echo "Waiting for replicas to be deleted..."
sleep 30

# Delete the primary table
aws dynamodb delete-table \
    --table-name MusicTable \
    --region us-east-2
```
+ Weitere API-Informationen finden Sie in den folgenden Themen der *AWS CLI -Befehlsreferenz*.
  + [CreateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/PutItem)
  + [UpdateItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateTable)

------
#### [ Java ]

**SDK für Java 2.x**  
Erstellen Sie eine regionale Tabelle, die für die MRSC-Konvertierung bereit ist, mit. AWS SDK for Java 2.x  

```
    public static CreateTableResponse createRegionalTable(final DynamoDbClient dynamoDbClient, final String tableName) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }

        try {
            LOGGER.info("Creating regional table: " + tableName + " (must be empty for MRSC)");

            CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .tableName(tableName)
                .attributeDefinitions(
                    AttributeDefinition.builder()
                        .attributeName("Artist")
                        .attributeType(ScalarAttributeType.S)
                        .build(),
                    AttributeDefinition.builder()
                        .attributeName("SongTitle")
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(
                    KeySchemaElement.builder()
                        .attributeName("Artist")
                        .keyType(KeyType.HASH)
                        .build(),
                    KeySchemaElement.builder()
                        .attributeName("SongTitle")
                        .keyType(KeyType.RANGE)
                        .build())
                .billingMode(BillingMode.PAY_PER_REQUEST)
                .build();

            CreateTableResponse response = dynamoDbClient.createTable(createTableRequest);
            LOGGER.info("Regional table creation initiated. Status: "
                + response.tableDescription().tableStatus());

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to create regional table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to create regional table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Konvertiert eine regionale Tabelle in eine MRSC-Tabelle mit Replikaten und Zeugen unter Verwendung von. AWS SDK for Java 2.x  

```
    public static UpdateTableResponse convertToMRSCWithWitness(
        final DynamoDbClient dynamoDbClient,
        final String tableName,
        final Region replicaRegion,
        final Region witnessRegion) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (replicaRegion == null) {
            throw new IllegalArgumentException("Replica region cannot be null");
        }
        if (witnessRegion == null) {
            throw new IllegalArgumentException("Witness region cannot be null");
        }

        try {
            LOGGER.info("Converting table to MRSC with replica in " + replicaRegion.id() + " and witness in "
                + witnessRegion.id());

            // Create replica update using ReplicationGroupUpdate
            ReplicationGroupUpdate replicaUpdate = ReplicationGroupUpdate.builder()
                .create(CreateReplicationGroupMemberAction.builder()
                    .regionName(replicaRegion.id())
                    .build())
                .build();

            // Create witness update
            GlobalTableWitnessGroupUpdate witnessUpdate = GlobalTableWitnessGroupUpdate.builder()
                .create(CreateGlobalTableWitnessGroupMemberAction.builder()
                    .regionName(witnessRegion.id())
                    .build())
                .build();

            UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .tableName(tableName)
                .replicaUpdates(List.of(replicaUpdate))
                .globalTableWitnessUpdates(List.of(witnessUpdate))
                .multiRegionConsistency(MultiRegionConsistency.STRONG)
                .build();

            UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest);
            LOGGER.info("MRSC conversion initiated. Status: "
                + response.tableDescription().tableStatus());
            LOGGER.info("UpdateTableResponse full object: " + response);
            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to convert table to MRSC: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to convert table to MRSC: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Beschreiben Sie eine globale MRSC-Tabellenkonfiguration mit. AWS SDK for Java 2.x  

```
    public static DescribeTableResponse describeMRSCTable(final DynamoDbClient dynamoDbClient, final String tableName) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }

        try {
            LOGGER.info("Describing MRSC global table: " + tableName);

            DescribeTableRequest request =
                DescribeTableRequest.builder().tableName(tableName).build();

            DescribeTableResponse response = dynamoDbClient.describeTable(request);

            LOGGER.info("Table status: " + response.table().tableStatus());
            LOGGER.info("Multi-region consistency: " + response.table().multiRegionConsistency());

            if (response.table().replicas() != null
                && !response.table().replicas().isEmpty()) {
                LOGGER.info("Number of replicas: " + response.table().replicas().size());
                response.table()
                    .replicas()
                    .forEach(replica -> LOGGER.info(
                        "Replica region: " + replica.regionName() + ", Status: " + replica.replicaStatus()));
            }

            if (response.table().globalTableWitnesses() != null
                && !response.table().globalTableWitnesses().isEmpty()) {
                LOGGER.info("Number of witnesses: "
                    + response.table().globalTableWitnesses().size());
                response.table()
                    .globalTableWitnesses()
                    .forEach(witness -> LOGGER.info(
                        "Witness region: " + witness.regionName() + ", Status: " + witness.witnessStatus()));
            }

            return response;

        } catch (ResourceNotFoundException e) {
            LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Table not found: " + tableName)
                .cause(e)
                .build();
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to describe table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Fügen Sie mit AWS SDK for Java 2.x Testelemente hinzu, um die starke Konsistenz von MRSC zu überprüfen.  

```
    public static PutItemResponse putTestItem(
        final DynamoDbClient dynamoDbClient,
        final String tableName,
        final String artist,
        final String songTitle,
        final String album,
        final String year) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (artist == null || artist.trim().isEmpty()) {
            throw new IllegalArgumentException("Artist cannot be null or empty");
        }
        if (songTitle == null || songTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("Song title cannot be null or empty");
        }

        try {
            LOGGER.info("Adding test item to MRSC global table: " + tableName);

            Map<String, AttributeValue> item = new HashMap<>();
            item.put("Artist", AttributeValue.builder().s(artist).build());
            item.put("SongTitle", AttributeValue.builder().s(songTitle).build());

            if (album != null && !album.trim().isEmpty()) {
                item.put("Album", AttributeValue.builder().s(album).build());
            }
            if (year != null && !year.trim().isEmpty()) {
                item.put("Year", AttributeValue.builder().n(year).build());
            }

            PutItemRequest putItemRequest =
                PutItemRequest.builder().tableName(tableName).item(item).build();

            PutItemResponse response = dynamoDbClient.putItem(putItemRequest);
            LOGGER.info("Test item added successfully with strong consistency");

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add test item to table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to add test item to table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Lesen Sie Elemente mit konsistenten Lesevorgängen aus MRSC-Replikaten unter Verwendung von. AWS SDK for Java 2.x  

```
    public static GetItemResponse getItemWithConsistentRead(
        final DynamoDbClient dynamoDbClient, final String tableName, final String artist, final String songTitle) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (artist == null || artist.trim().isEmpty()) {
            throw new IllegalArgumentException("Artist cannot be null or empty");
        }
        if (songTitle == null || songTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("Song title cannot be null or empty");
        }

        try {
            LOGGER.info("Reading item from MRSC global table with consistent read: " + tableName);

            Map<String, AttributeValue> key = new HashMap<>();
            key.put("Artist", AttributeValue.builder().s(artist).build());
            key.put("SongTitle", AttributeValue.builder().s(songTitle).build());

            GetItemRequest getItemRequest = GetItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .consistentRead(true)
                .build();

            GetItemResponse response = dynamoDbClient.getItem(getItemRequest);

            if (response.hasItem()) {
                LOGGER.info("Item found with strong consistency - no wait time needed");
            } else {
                LOGGER.info("Item not found");
            }

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to read item from table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to read item from table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Führen Sie bedingte Aktualisierungen mit MRSC-Garantien durch, indem Sie. AWS SDK for Java 2.x  

```
    public static UpdateItemResponse performConditionalUpdate(
        final DynamoDbClient dynamoDbClient,
        final String tableName,
        final String artist,
        final String songTitle,
        final String rating) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (artist == null || artist.trim().isEmpty()) {
            throw new IllegalArgumentException("Artist cannot be null or empty");
        }
        if (songTitle == null || songTitle.trim().isEmpty()) {
            throw new IllegalArgumentException("Song title cannot be null or empty");
        }
        if (rating == null || rating.trim().isEmpty()) {
            throw new IllegalArgumentException("Rating cannot be null or empty");
        }

        try {
            LOGGER.info("Performing conditional update on MRSC global table: " + tableName);

            Map<String, AttributeValue> key = new HashMap<>();
            key.put("Artist", AttributeValue.builder().s(artist).build());
            key.put("SongTitle", AttributeValue.builder().s(songTitle).build());

            Map<String, String> expressionAttributeNames = new HashMap<>();
            expressionAttributeNames.put("#rating", "Rating");

            Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
            expressionAttributeValues.put(
                ":rating", AttributeValue.builder().n(rating).build());

            UpdateItemRequest updateItemRequest = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .updateExpression("SET #rating = :rating")
                .conditionExpression("attribute_exists(Artist)")
                .expressionAttributeNames(expressionAttributeNames)
                .expressionAttributeValues(expressionAttributeValues)
                .build();

            UpdateItemResponse response = dynamoDbClient.updateItem(updateItemRequest);
            LOGGER.info("Conditional update successful - demonstrates strong consistency");

            return response;

        } catch (ConditionalCheckFailedException e) {
            LOGGER.warning("Conditional check failed: " + e.getMessage());
            throw e;
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to perform conditional update: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to perform conditional update: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Warten Sie, bis MRSC-Repliken und Zeugen die Nutzung aktivieren. AWS SDK for Java 2.x  

```
    public static void waitForMRSCReplicasActive(
        final DynamoDbClient dynamoDbClient, final String tableName, final int maxWaitTimeSeconds)
        throws InterruptedException {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (maxWaitTimeSeconds <= 0) {
            throw new IllegalArgumentException("Max wait time must be positive");
        }

        try {
            LOGGER.info("Waiting for MRSC replicas and witnesses to become active: " + tableName);

            final long startTime = System.currentTimeMillis();
            final long maxWaitTimeMillis = maxWaitTimeSeconds * 1000L;
            int backoffSeconds = 5; // Start with 5 second intervals
            final int maxBackoffSeconds = 30; // Cap at 30 seconds

            while (System.currentTimeMillis() - startTime < maxWaitTimeMillis) {
                DescribeTableResponse response = describeMRSCTable(dynamoDbClient, tableName);

                boolean allActive = true;
                StringBuilder statusReport = new StringBuilder();

                if (response.table().multiRegionConsistency() == null
                    || !MultiRegionConsistency.STRONG
                        .toString()
                        .equals(response.table().multiRegionConsistency().toString())) {
                    allActive = false;
                    statusReport
                        .append("MultiRegionConsistency: ")
                        .append(response.table().multiRegionConsistency())
                        .append(" ");
                }
                if (response.table().replicas() == null
                    || response.table().replicas().isEmpty()) {
                    allActive = false;
                    statusReport.append("No replicas found. ");
                }
                if (response.table().globalTableWitnesses() == null
                    || response.table().globalTableWitnesses().isEmpty()) {
                    allActive = false;
                    statusReport.append("No witnesses found. ");
                }

                // Check table status
                if (!"ACTIVE".equals(response.table().tableStatus().toString())) {
                    allActive = false;
                    statusReport
                        .append("Table: ")
                        .append(response.table().tableStatus())
                        .append(" ");
                }

                // Check replica status
                if (response.table().replicas() != null) {
                    for (var replica : response.table().replicas()) {
                        if (!"ACTIVE".equals(replica.replicaStatus().toString())) {
                            allActive = false;
                            statusReport
                                .append("Replica(")
                                .append(replica.regionName())
                                .append("): ")
                                .append(replica.replicaStatus())
                                .append(" ");
                        }
                    }
                }

                // Check witness status
                if (response.table().globalTableWitnesses() != null) {
                    for (var witness : response.table().globalTableWitnesses()) {
                        if (!"ACTIVE".equals(witness.witnessStatus().toString())) {
                            allActive = false;
                            statusReport
                                .append("Witness(")
                                .append(witness.regionName())
                                .append("): ")
                                .append(witness.witnessStatus())
                                .append(" ");
                        }
                    }
                }

                if (allActive) {
                    LOGGER.info("All MRSC replicas and witnesses are now active: " + tableName);
                    return;
                }

                LOGGER.info("Waiting for MRSC components to become active. Status: " + statusReport.toString());
                LOGGER.info("Next check in " + backoffSeconds + " seconds...");

                tempWait(backoffSeconds);

                // Exponential backoff with cap
                backoffSeconds = Math.min(backoffSeconds * 2, maxBackoffSeconds);
            }

            throw DynamoDbException.builder()
                .message("Timeout waiting for MRSC replicas to become active after " + maxWaitTimeSeconds + " seconds")
                .build();

        } catch (DynamoDbException | InterruptedException e) {
            LOGGER.severe("Failed to wait for MRSC replicas to become active: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Bereinigen Sie MRSC-Replikate und Zeugen mithilfe von. AWS SDK for Java 2.x  

```
    public static UpdateTableResponse cleanupMRSCReplicas(
        final DynamoDbClient dynamoDbClient,
        final String tableName,
        final Region replicaRegion,
        final Region witnessRegion) {

        if (dynamoDbClient == null) {
            throw new IllegalArgumentException("DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (replicaRegion == null) {
            throw new IllegalArgumentException("Replica region cannot be null");
        }
        if (witnessRegion == null) {
            throw new IllegalArgumentException("Witness region cannot be null");
        }

        try {
            LOGGER.info("Cleaning up MRSC replicas and witnesses for table: " + tableName);

            // Remove replica using ReplicationGroupUpdate
            ReplicationGroupUpdate replicaUpdate = ReplicationGroupUpdate.builder()
                .delete(DeleteReplicationGroupMemberAction.builder()
                    .regionName(replicaRegion.id())
                    .build())
                .build();

            // Remove witness
            GlobalTableWitnessGroupUpdate witnessUpdate = GlobalTableWitnessGroupUpdate.builder()
                .delete(DeleteGlobalTableWitnessGroupMemberAction.builder()
                    .regionName(witnessRegion.id())
                    .build())
                .build();

            UpdateTableRequest updateTableRequest = UpdateTableRequest.builder()
                .tableName(tableName)
                .replicaUpdates(List.of(replicaUpdate))
                .globalTableWitnessUpdates(List.of(witnessUpdate))
                .build();

            UpdateTableResponse response = dynamoDbClient.updateTable(updateTableRequest);
            LOGGER.info("MRSC cleanup initiated - removing replica and witness. Response: " + response);

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to cleanup MRSC replicas: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to cleanup MRSC replicas: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Vollständige Demonstration des MRSC-Workflows mithilfe von. AWS SDK for Java 2.x  

```
    public static void demonstrateCompleteMRSCWorkflow(
        final DynamoDbClient primaryClient,
        final DynamoDbClient replicaClient,
        final String tableName,
        final Region replicaRegion,
        final Region witnessRegion)
        throws InterruptedException {

        if (primaryClient == null) {
            throw new IllegalArgumentException("Primary DynamoDB client cannot be null");
        }
        if (replicaClient == null) {
            throw new IllegalArgumentException("Replica DynamoDB client cannot be null");
        }
        if (tableName == null || tableName.trim().isEmpty()) {
            throw new IllegalArgumentException("Table name cannot be null or empty");
        }
        if (replicaRegion == null) {
            throw new IllegalArgumentException("Replica region cannot be null");
        }
        if (witnessRegion == null) {
            throw new IllegalArgumentException("Witness region cannot be null");
        }

        try {
            LOGGER.info("=== Starting Complete MRSC Workflow Demonstration ===");

            // Step 1: Create an empty single-Region table
            LOGGER.info("Step 1: Creating empty single-Region table");
            createRegionalTable(primaryClient, tableName);

            // Use the existing GlobalTableOperations method for basic table waiting
            LOGGER.info("Intermediate step: Waiting for table [" + tableName + "] to become active before continuing");
            GlobalTableOperations.waitForTableActive(primaryClient, tableName);

            // Step 2: Convert to MRSC with replica and witness
            LOGGER.info("Step 2: Converting to MRSC with replica and witness");
            convertToMRSCWithWitness(primaryClient, tableName, replicaRegion, witnessRegion);

            // Wait for MRSC conversion to complete using MRSC-specific waiter
            LOGGER.info("Waiting for MRSC conversion to complete...");
            waitForMRSCReplicasActive(primaryClient, tableName);

            LOGGER.info("Intermediate step: Waiting for table [" + tableName + "] to become active before continuing");
            GlobalTableOperations.waitForTableActive(primaryClient, tableName);

            // Step 3: Verify MRSC configuration
            LOGGER.info("Step 3: Verifying MRSC configuration");
            describeMRSCTable(primaryClient, tableName);

            // Step 4: Test strong consistency with data operations
            LOGGER.info("Step 4: Testing strong consistency with data operations");

            // Add test item to primary region
            putTestItem(primaryClient, tableName, "The Beatles", "Hey Jude", "The Beatles 1967-1970", "1968");

            // Immediately read from replica region (no wait needed with MRSC)
            LOGGER.info("Reading from replica region immediately (strong consistency):");
            GetItemResponse getResponse =
                getItemWithConsistentRead(replicaClient, tableName, "The Beatles", "Hey Jude");

            if (getResponse.hasItem()) {
                LOGGER.info("✓ Strong consistency verified - item immediately available in replica region");
            } else {
                LOGGER.warning("✗ Item not found in replica region");
            }

            // Test conditional update from replica region
            LOGGER.info("Testing conditional update from replica region:");
            performConditionalUpdate(replicaClient, tableName, "The Beatles", "Hey Jude", "5");
            LOGGER.info("✓ Conditional update successful - demonstrates strong consistency");

            // Step 5: Cleanup
            LOGGER.info("Step 5: Cleaning up resources");
            cleanupMRSCReplicas(primaryClient, tableName, replicaRegion, witnessRegion);

            // Wait for cleanup to complete using basic table waiter
            LOGGER.info("Waiting for replica cleanup to complete...");
            GlobalTableOperations.waitForTableActive(primaryClient, tableName);

            // "Halt" until replica/witness cleanup is complete
            DescribeTableResponse cleanupVerification = describeMRSCTable(primaryClient, tableName);
            int backoffSeconds = 5; // Start with 5 second intervals
            while (cleanupVerification.table().multiRegionConsistency() != null) {
                LOGGER.info("Waiting additional time (" + backoffSeconds + " seconds) for MRSC cleanup to complete...");
                tempWait(backoffSeconds);

                // Exponential backoff with cap
                backoffSeconds = Math.min(backoffSeconds * 2, 30);
                cleanupVerification = describeMRSCTable(primaryClient, tableName);
            }

            // Delete the primary table
            deleteTable(primaryClient, tableName);

            LOGGER.info("=== MRSC Workflow Demonstration Complete ===");
            LOGGER.info("");
            LOGGER.info("Key benefits of Multi-Region Strong Consistency (MRSC):");
            LOGGER.info("- Immediate consistency across all regions (no eventual consistency delays)");
            LOGGER.info("- Simplified application logic (no need to handle eventual consistency)");
            LOGGER.info("- Support for conditional writes and transactions across regions");
            LOGGER.info("- Consistent read operations from any region without waiting");

        } catch (DynamoDbException | InterruptedException e) {
            LOGGER.severe("MRSC workflow failed: " + e.getMessage());
            throw e;
        }
    }
```
+ Weitere API-Informationen finden Sie in den folgenden Themen der *AWS SDK for Java 2.x -API-Referenz*.
  + [CreateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)
  + [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateTable)

------

# Sicherheit von globalen DynamoDB-Tabellen
<a name="globaltables-security"></a>

Globale Tabellenreplikate sind DynamoDB-Tabellen. Sie verwenden also dieselben Methoden zur Steuerung des Zugriffs auf Replikate wie für Tabellen mit einer einzelnen Region, einschließlich AWS Identity and Access Management (IAM-) Identitätsrichtlinien und ressourcenbasierter Richtlinien.

In diesem Thema wird beschrieben, wie Sie globale DynamoDB-Tabellen mithilfe von IAM-Berechtigungen und AWS Key Management Service ()AWS KMS-Verschlüsselung sichern. Sie erfahren mehr über die serviceverknüpften Rollen (SLR), die regionsübergreifende Replikation und auto-scaling ermöglichen, über die IAM-Berechtigungen, die zum Erstellen, Aktualisieren und Löschen globaler Tabellen erforderlich sind, und über die Unterschiede zwischen Multi-Region Eventual Consistency (MREC) und Multi-Region Strong Consistency (MRSC) -Tabellen. Außerdem erfahren Sie mehr über Verschlüsselungsschlüssel, mit denen Sie die regionsübergreifende Replikation sicher verwalten können. AWS KMS 

## Mit Diensten verknüpfte Rollen für globale Tabellen
<a name="globaltables-slr"></a>

Globale DynamoDB-Tabellen basieren auf serviceverknüpften Rollen (SLRs), um regionsübergreifende Replikations- und Autoskalierungsfunktionen zu verwalten.

Sie müssen diese Rollen nur einmal pro Konto einrichten. AWS Nach der Erstellung dienen dieselben Rollen für alle globalen Tabellen in Ihrem Konto. Weitere Informationen zu serviceverknüpften Rollen finden Sie unter [Verwenden serviceverknüpfter Rollen](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) im *IAM-Benutzerhandbuch*.

### Mit dem Replikationsservice verknüpfte Rolle
<a name="globaltables-replication-slr"></a>

Amazon DynamoDB erstellt automatisch die `AWSServiceRoleForDynamoDBReplication` serviceverknüpfte Rolle (SLR), wenn Sie Ihre erste globale Tabelle erstellen. Diese Rolle verwaltet die regionsübergreifende Replikation für Sie.

Wenn Sie ressourcenbasierte Richtlinien auf Replikate anwenden, stellen Sie sicher, dass Sie dem SLR-Prinzipal keine der im SLR-Prinzipal definierten Berechtigungen verweigern, da dadurch die Replikation unterbrochen wird. `AWSServiceRoleForDynamoDBReplicationPolicy` Wenn Sie die erforderlichen SLR-Berechtigungen verweigern, wird die Replikation zu und von den betroffenen Replikaten beendet, und der Status der Replikattabelle ändert sich in `REPLICATION_NOT_AUTHORIZED`.
+ Bei globalen Multi-Region Eventual Consistency (MREC) -Tabellen gilt: Wenn ein Replikat länger als 20 Stunden im `REPLICATION_NOT_AUTHORIZED` Status verbleibt, wird das Replikat unwiderruflich in eine DynamoDB-Tabelle mit nur einer Region konvertiert.
+ Bei globalen Tabellen mit starker Konsistenz in mehreren Regionen (Multiregion Strong Consistency, MRSC) führt das Verweigern der erforderlichen Berechtigungen zu Schreib- und stark konsistenten Lesevorgängen. `AccessDeniedException` Bleibt ein Replikat länger als sieben Tage im `REPLICATION_NOT_AUTHORIZED` Status, kann nicht mehr auf das Replikat zugegriffen werden, und Schreib- und Strongly Consistent-Lesevorgänge schlagen weiterhin mit einem Fehler fehl. Einige Managementoperationen wie das Löschen von Replikaten werden erfolgreich abgeschlossen.

### Mit dem Auto Scaling Service verknüpfte Rolle
<a name="globaltables-autoscaling-slr"></a>

Bei der Konfiguration einer globalen Tabelle für den Modus mit bereitgestellter Kapazität muss Auto Scaling für die globale Tabelle konfiguriert werden. DynamoDB Auto Scaling verwendet den AWS Application Auto Scaling Scaling-Dienst, um die bereitgestellte Durchsatzkapazität auf Ihren globalen Tabellenreplikaten dynamisch anzupassen. Der Application Auto Scaling Scaling-Dienst erstellt eine serviceverknüpfte Rolle (SLR) mit dem Namen. [https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html](https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html) Diese serviceverknüpfte Rolle wird automatisch in Ihrem AWS Konto erstellt, wenn Sie Auto Scaling für eine DynamoDB-Tabelle zum ersten Mal konfigurieren. Es ermöglicht Application Auto Scaling, die bereitgestellte Tabellenkapazität zu verwalten und CloudWatch Alarme zu erstellen. 

 Achten Sie bei der Anwendung ressourcenbasierter Richtlinien auf Replikate darauf, dass Sie keine im SLR-Prinzipal für Application Auto Scaling definierten Berechtigungen verweigern, da dadurch die Auto Scaling-Funktionalität unterbrochen wird. [https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html)

### Beispiel für IAM-Richtlinien für serviceverknüpfte Rollen
<a name="globaltables-example-slr"></a>

Eine IAM-Richtlinie mit der folgenden Bedingung hat keine Auswirkungen auf die erforderlichen Berechtigungen für die DynamoDB-Replikations-SLR und AWS Auto Scaling SLR. Diese Bedingung kann zu ansonsten weitgehend restriktiven Richtlinien hinzugefügt werden, um zu verhindern, dass Replikation oder Auto Scaling unbeabsichtigt unterbrochen werden.

#### Ausgenommen der erforderlichen SLR-Berechtigungen aus den Verweigerungsrichtlinien
<a name="example-exclude-slr-policy"></a>

Das folgende Beispiel zeigt, wie servicebezogene Rollenprinzipale von Deny-Statements ausgeschlossen werden können:

```
"Condition": {
    "StringNotEquals": {
        "aws:PrincipalArn": [
            "arn:aws::iam::111122223333:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication",
            "arn:aws::iam::111122223333:role/aws-service-role/dynamodb.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_DynamoDBTable"
        ]
    }
}
```

## Wie globale Tabellen IAM verwenden AWS
<a name="globaltables-iam"></a>

In den folgenden Abschnitten werden die erforderlichen Berechtigungen für verschiedene globale Tabellenoperationen beschrieben und Richtlinienbeispiele bereitgestellt, die Ihnen bei der Konfiguration des entsprechenden Zugriffs für Ihre Benutzer und Anwendungen helfen sollen.

**Anmerkung**  
Alle beschriebenen Berechtigungen müssen auf die spezifische Tabellenressource ARN in den betroffenen Regionen angewendet werden. Die Tabellenressource ARN folgt dem Format`arn:aws:dynamodb:region:account-id:table/table-name`, in dem Sie Ihre tatsächlichen Werte für Region, Konto-ID und Tabellennamen angeben müssen.

**Topics**
+ [Globale Tabellen erstellen und Replikate hinzufügen](#globaltables-creation-iam)
+ [Aktualisieren von globalen Tabellen](#globaltables-update-iam)
+ [Löschen globaler Tabellen und Entfernen von Replikaten](#globaltables-delete-iam)

### Globale Tabellen erstellen und Replikate hinzufügen
<a name="globaltables-creation-iam"></a>

Globale DynamoDB-Tabellen unterstützen zwei Konsistenzmodi: Multi-Region Eventual Consistency (MREC) und Multi-Region Strong Consistency (MRSC). Globale MREC-Tabellen können mehrere Replikate in einer beliebigen Anzahl von Regionen enthalten und sorgen so für Konsistenz. Globale MRSC-Tabellen erfordern genau drei Regionen (drei Replikate oder zwei Replikate und ein Zeuge) und bieten eine hohe Konsistenz mit einem Nullpunktziel (RPO).

Die zum Erstellen globaler Tabellen erforderlichen Berechtigungen hängen davon ab, ob Sie eine globale Tabelle mit oder ohne Zeugen erstellen.

#### Berechtigungen für die Erstellung globaler Tabellen
<a name="globaltables-creation-iam-all-types"></a>

Die folgenden Berechtigungen sind sowohl für die anfängliche Erstellung globaler Tabellen als auch für das spätere Hinzufügen von Replikaten erforderlich. Diese Berechtigungen gelten sowohl für globale Tabellen mit Multi-Region Eventual Consistency (MREC) als auch für Multi-Region Strong Consistency (MRSC).
+ Globale Tabellen erfordern eine regionsübergreifende Replikation, die DynamoDB über die [`AWSServiceRoleForDynamoDBReplication`](#globaltables-replication-slr)serviceverknüpfte Rolle (SLR) verwaltet. Die folgende Berechtigung ermöglicht DynamoDB, diese Rolle automatisch zu erstellen, wenn Sie zum ersten Mal eine globale Tabelle erstellen:
  + `iam:CreateServiceLinkedRole`
+ Um mithilfe der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API eine globale Tabelle zu erstellen oder ein Replikat hinzuzufügen, benötigen Sie die folgende Berechtigung für die Quelltabellenressource:
  + `dynamodb:UpdateTable`
+ Sie benötigen die folgenden Berechtigungen für die Tabellenressource in den Regionen, damit die Replikate hinzugefügt werden können:
  + `dynamodb:CreateTable`
  + `dynamodb:CreateTableReplica`
  + `dynamodb:Query`
  + `dynamodb:Scan`
  + `dynamodb:UpdateItem`
  + `dynamodb:PutItem`
  + `dynamodb:GetItem`
  + `dynamodb:DeleteItem`
  + `dynamodb:BatchWriteItem`

#### Zusätzliche Berechtigungen für globale MRSC-Tabellen, die einen Zeugen verwenden
<a name="globaltables-creation-iam-witness"></a>

Wenn Sie eine globale MRSC-Tabelle (Multi-Region Strong Consistency) mit einer Zeugenregion erstellen, benötigen Sie die folgenden Berechtigungen für die Tabellenressource in allen beteiligten Regionen (einschließlich der Replikatregionen und der Zeugenregion):
+ `dynamodb:CreateGlobalTableWitness`

#### Beispiel für IAM-Richtlinien zum Erstellen globaler Tabellen
<a name="globaltables-creation-iam-example"></a>

##### Erstellung einer globalen MREC- oder MRSC-Tabelle für drei Regionen
<a name="globaltables-creation-iam-example-three-regions"></a>

Die folgende identitätsbasierte Richtlinie ermöglicht es Ihnen, eine globale MREC- oder MRSC-Tabelle mit dem Namen „users“ in drei Regionen zu erstellen, einschließlich der Erstellung der erforderlichen mit dem DynamoDB-Replikationsdienst verknüpften Rolle.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowCreatingUsersGlobalTable",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:CreateTableReplica",
        "dynamodb:UpdateTable",
        "dynamodb:Query",
        "dynamodb:Scan",
        "dynamodb:UpdateItem",
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:DeleteItem",
        "dynamodb:BatchWriteItem"
      ],
      "Resource": [
        "arn:aws:dynamodb:us-east-1:123456789012:table/users",
        "arn:aws:dynamodb:us-east-2:123456789012:table/users",
        "arn:aws:dynamodb:us-west-2:123456789012:table/users"
      ]
    },
    {
      "Sid": "AllowCreatingSLR",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole"
      ],
      "Resource": [
        "arn:aws:iam::123456789012:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication"
      ]
    }
  ]
}
```

------

##### Beschränken Sie die Erstellung globaler MREC- oder MRSC-Tabellen auf bestimmte Regionen
<a name="globaltables-creation-iam-example-restrict-regions"></a>

Die folgende identitätsbasierte Richtlinie ermöglicht es Ihnen, mithilfe des RequestedRegion Bedingungsschlüssels [aws:](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requestedregion) globale DynamoDB-Tabellen in bestimmten Regionen zu erstellen, einschließlich der Erstellung der erforderlichen mit dem DynamoDB-Replikationsdienst verknüpften Rolle.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowAddingReplicasToSourceTable",
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateTable"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": [
            "us-east-1"
          ]
        }
      }
    },
    {
      "Sid": "AllowCreatingReplicas",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:CreateTableReplica",
        "dynamodb:UpdateTable",
        "dynamodb:Query",
        "dynamodb:Scan",
        "dynamodb:UpdateItem",
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:DeleteItem",
        "dynamodb:BatchWriteItem"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": [
            "us-east-2",
            "us-west-2"
          ]
        }
      }
    },
    {
      "Sid": "AllowCreatingSLR",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole"
      ],
      "Resource": [
        "arn:aws:iam::123456789012:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication"
      ]
    }
  ]
}
```

------

##### Erstellen einer globalen MRSC-Tabelle mit Zeuge
<a name="globaltables-creation-iam-example-witness"></a>

Die folgende identitätsbasierte Richtlinie ermöglicht es Ihnen, eine globale DynamoDB-MRSC-Tabelle mit dem Namen „users“ mit Replikaten in us-east-1 und us-east-2 und einem Zeugen in us-west-2 zu erstellen, einschließlich der Erstellung der erforderlichen mit dem DynamoDB-Replikationsdienst verknüpften Rolle.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowCreatingUsersGlobalTableWithWitness",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:CreateTableReplica",
        "dynamodb:CreateGlobalTableWitness",
        "dynamodb:UpdateTable",
        "dynamodb:Query",
        "dynamodb:Scan",
        "dynamodb:UpdateItem",
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:DeleteItem",
        "dynamodb:BatchWriteItem"
      ],
      "Resource": [
        "arn:aws:dynamodb:us-east-1:123456789012:table/users",
        "arn:aws:dynamodb:us-east-2:123456789012:table/users"
      ]
    },
    {
      "Sid": "AllowCreatingSLR",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole"
      ],
      "Resource": [
        "arn:aws:iam::123456789012:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication"
      ]
    }
  ]
}
```

------

##### Beschränkung der Erstellung von MRSC-Zeugen auf bestimmte Regionen
<a name="globaltables-creation-iam-example-restrict-witness-regions"></a>

Diese identitätsbasierte Richtlinie ermöglicht es Ihnen, eine globale MRSC-Tabelle mit Replikaten zu erstellen, die auf bestimmte Regionen beschränkt sind, indem Sie den RequestedRegion Bedingungsschlüssel [aws:](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requestedregion) verwenden und uneingeschränkte Zeugenerstellung für alle Regionen verwenden, einschließlich der Erstellung der erforderlichen, mit dem DynamoDB-Replikationsdienst verknüpften Rolle.

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "AllowCreatingReplicas",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateTable",
        "dynamodb:CreateTableReplica",
        "dynamodb:UpdateTable",
        "dynamodb:Query",
        "dynamodb:Scan",
        "dynamodb:UpdateItem",
        "dynamodb:PutItem",
        "dynamodb:GetItem",
        "dynamodb:DeleteItem",
        "dynamodb:BatchWriteItem"
      ],
      "Resource": "*",
      "Condition": {
        "StringEquals": {
          "aws:RequestedRegion": [
            "us-east-1",
            "us-east-2"
          ]
        }
      }
    },
    {
      "Sid": "AllowCreatingWitness",
      "Effect": "Allow",
      "Action": [
        "dynamodb:CreateGlobalTableWitness"
      ],
      "Resource": "*"
    },
    {
      "Sid": "AllowCreatingSLR",
      "Effect": "Allow",
      "Action": [
        "iam:CreateServiceLinkedRole"
      ],
      "Resource": [
        "arn:aws:iam::123456789012:role/aws-service-role/replication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBReplication"
      ]
    }
  ]
}
```

------

### Aktualisieren von globalen Tabellen
<a name="globaltables-update-iam"></a>

Um die Replikateinstellungen für eine bestehende globale Tabelle mithilfe der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API zu ändern, benötigen Sie die folgende Berechtigung für die Tabellenressource in der Region, in der Sie den API-Aufruf tätigen:
+ `dynamodb:UpdateTable`

Sie können auch andere globale Tabellenkonfigurationen aktualisieren, z. B. Richtlinien für auto Skalierung und Time-to-Live-Einstellungen. Für diese zusätzlichen Aktualisierungsvorgänge sind die folgenden Berechtigungen erforderlich:
+ Um eine Replica-Auto-Scaling-Richtlinie mit der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTableReplicaAutoScaling.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTableReplicaAutoScaling.html)API zu aktualisieren, benötigen Sie die folgenden Berechtigungen für die Tabellenressource in allen Regionen, die Replikate enthalten:
  + `application-autoscaling:DeleteScalingPolicy`
  + `application-autoscaling:DeleteScheduledAction`
  + `application-autoscaling:DeregisterScalableTarget`
  + `application-autoscaling:DescribeScalableTargets`
  + `application-autoscaling:DescribeScalingActivities`
  + `application-autoscaling:DescribeScalingPolicies`
  + `application-autoscaling:DescribeScheduledActions`
  + `application-autoscaling:PutScalingPolicy`
  + `application-autoscaling:PutScheduledAction`
  + `application-autoscaling:RegisterScalableTarget`
+ Um die Time-to-Live-Einstellungen mit der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTimeToLive.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTimeToLive.html)API zu aktualisieren, benötigen Sie die folgenden Berechtigungen für die Tabellenressource in allen Regionen, die Replikate enthalten:
  + `dynamodb:UpdateTimeToLive`

  Beachten Sie, dass Time to Live (TTL) nur für globale Tabellen unterstützt wird, die mit Multi-Region Eventual Consistency (MREC) konfiguriert sind. Weitere Informationen zur Funktionsweise globaler Tabellen mit TTL finden Sie unter [So funktionieren globale DynamoDB-Tabellen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html).

### Löschen globaler Tabellen und Entfernen von Replikaten
<a name="globaltables-delete-iam"></a>

Um eine globale Tabelle zu löschen, müssen Sie alle Replikate entfernen. Die für diesen Vorgang erforderlichen Berechtigungen hängen davon ab, ob Sie eine globale Tabelle mit oder ohne Zeugenregion löschen.

#### Berechtigungen zum Löschen globaler Tabellen und zum Entfernen von Replikaten
<a name="globaltables-delete-iam-all-types"></a>

Die folgenden Berechtigungen sind sowohl für das Entfernen einzelner Replikate als auch für das vollständige Löschen globaler Tabellen erforderlich. Durch das Löschen einer globalen Tabellenkonfiguration wird nur die Replikationsbeziehung zwischen Tabellen in verschiedenen Regionen entfernt. Die zugrunde liegende DynamoDB-Tabelle in der letzten verbleibenden Region wird nicht gelöscht. Die Tabelle in der letzten Region existiert weiterhin als standardmäßige DynamoDB-Tabelle mit denselben Daten und Einstellungen. Diese Berechtigungen gelten sowohl für globale Tabellen mit Multi-Region Eventual Consistency (MREC) als auch für Multi-Region Strong Consistency (MRSC). 
+ Um mithilfe der [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API Replikate aus einer globalen Tabelle zu entfernen, benötigen Sie die folgende Berechtigung für die Tabellenressource in der Region, von der aus Sie den API-Aufruf tätigen:
  + `dynamodb:UpdateTable`
+ Sie benötigen die folgenden Berechtigungen für die Tabellenressource in jeder Region, in der Sie ein Replikat entfernen:
  + `dynamodb:DeleteTable`
  + `dynamodb:DeleteTableReplica`

#### Zusätzliche Berechtigungen für globale MRSC-Tabellen, die einen Zeugen verwenden
<a name="globaltables-delete-iam-witness"></a>

Um eine globale MRSC-Tabelle (Multiregion Strong Consistency) mit einem Zeugen zu löschen, benötigen Sie in allen beteiligten Regionen (einschließlich der Replikatregionen und der Zeugenregion) die folgenden Berechtigungen für die Tabellenressource:
+ `dynamodb:DeleteGlobalTableWitness`

#### Beispiele für IAM-Richtlinien zum Löschen globaler Tabellenreplikate
<a name="globaltables-delete-iam-example"></a>

##### Löschen globaler Tabellenreplikate
<a name="globaltables-delete-replicas-iam-example"></a>

Diese identitätsbasierte Richtlinie ermöglicht es Ihnen, eine globale DynamoDB-Tabelle mit dem Namen „users“ und ihre Replikate in drei Regionen zu löschen:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateTable",
        "dynamodb:DeleteTable",
        "dynamodb:DeleteTableReplica"
      ],
      "Resource": [
        "arn:aws:dynamodb:us-east-1:123456789012:table/users",
        "arn:aws:dynamodb:us-east-2:123456789012:table/users",
        "arn:aws:dynamodb:us-west-2:123456789012:table/users"
      ]
    }
  ]
}
```

------

##### Löschen einer globalen MRSC-Tabelle mit einem Zeugen
<a name="globaltables-delete-witness-iam-example"></a>

Mit dieser identitätsbasierten Richtlinie können Sie das Replikat und den Zeugen einer globalen MRSC-Tabelle mit dem Namen „users“ löschen:

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "dynamodb:UpdateTable",
        "dynamodb:DeleteTable",
        "dynamodb:DeleteTableReplica",
        "dynamodb:DeleteGlobalTableWitness"
      ],
      "Resource": [
        "arn:aws:dynamodb:us-east-1:123456789012:table/users",
        "arn:aws:dynamodb:us-east-2:123456789012:table/users"
      ]
    }
  ]
}
```

------

## Wie verwenden globale Tabellen AWS KMS
<a name="globaltables-kms"></a>

Wie alle DynamoDB-Tabellen verschlüsseln Replikate Daten im Ruhezustand immer mit Verschlüsselungsschlüsseln, die im AWS Key Management Service () gespeichert sind.AWS KMS

Alle Replikate in einer globalen Tabelle müssen mit demselben Typ von KMS-Schlüssel (AWS -eigener Schlüssel, von AWS verwalteter Schlüssel oder kundenseitig verwalteter Schlüssel) konfiguriert werden.

**Wichtig**  
DynamoDB benötigt Zugriff auf den Verschlüsselungsschlüssel des Replikats, um ein Replikat zu löschen. Wenn Sie einen kundenseitig verwalteten Schlüssel, der zur Verschlüsselung eines Replikats verwendet wird, deaktivieren oder löschen möchten, weil Sie das Replikat löschen, sollten Sie zuerst das Replikat löschen, warten, bis sich der Tabellenstatus in einem der verbleibenden Replikate in `ACTIVE` ändert, und dann den Schlüssel deaktivieren oder löschen.

Wenn Sie bei einer globalen MREC-Tabelle den Zugriff von DynamoDB auf einen kundenseitig verwalteten Schlüssel, der zur Verschlüsselung eines Replikats verwendet wird, deaktivieren oder entziehen, wird die Replikation zum und vom Replikat beendet und der Replikatstatus ändert sich in `INACCESSIBLE_ENCRYPTION_CREDENTIALS`. Wenn ein Replikat in einer globalen MREC-Tabelle länger als 20 Stunden im Status `INACCESSIBLE_ENCRYPTION_CREDENTIALS` verbleibt, wird das Replikat unwiderruflich in eine DynamoDB-Tabelle mit einer einzelnen Region konvertiert.

Wenn Sie bei einer globalen MRSC-Tabelle den Zugriff von DynamoDB auf einen kundenseitig verwalteten Schlüssel, der zur Verschlüsselung eines Replikats verwendet wird, deaktivieren oder entziehen, wird die Replikation zum und vom Replikat beendet, bei dem Versuch, strikt konsistente Lesevorgänge in das Replikat zu schreiben, tritt ein Fehler auf, und der Replikatstatus ändert sich in `INACCESSIBLE_ENCRYPTION_CREDENTIALS`. Wenn ein Replikat in einer globalen MRSC-Tabelle länger als sieben Tage im `INACCESSIBLE_ENCRYPTION_CREDENTIALS` Status verbleibt, wird das Replikat je nach den widerrufenen Berechtigungen archiviert oder es kann dauerhaft nicht mehr darauf zugegriffen werden.

# DynamoDB-Tabellen für mehrere Konten
<a name="globaltables-MultiAccount"></a>

Globale Tabellen mit mehreren Konten replizieren Ihre DynamoDB-Tabellendaten automatisch über mehrere AWS Regionen und mehrere AWS Konten hinweg, um die Ausfallsicherheit zu verbessern, Workloads auf Kontoebene zu isolieren und unterschiedliche Sicherheits- und Governance-Kontrollen anzuwenden. Jede Replikattabelle befindet sich in einem eigenen AWS Konto, wodurch eine Fehlerisolierung sowohl auf Regions- als auch auf Kontoebene ermöglicht wird. Sie können Replikate auch an Ihre AWS Organisationsstruktur anpassen. Globale Tabellen mit mehreren Konten bieten zusätzliche Isolations-, Verwaltungs- und Sicherheitsvorteile im Vergleich zu globalen Tabellen mit demselben Konto.

Globale Tabellen mit mehreren Konten bieten die folgenden Vorteile:
+ Automatisches Replizieren von DynamoDB-Tabellendaten für Konten und Regionen Ihrer AWS Wahl
+ Verbessern Sie Sicherheit und Governance, indem Sie Daten kontenübergreifend mit unterschiedlichen Richtlinien, Richtlinien und Compliance-Grenzen replizieren
+ Verbessern Sie die betriebliche Stabilität und die Fehlerisolierung auf Kontoebene, indem Sie Replikate auf separaten Konten platzieren AWS 
+ Richten Sie die Workloads nach Geschäftseinheit oder Eigentümer aus, wenn Sie eine Strategie für mehrere Konten verwenden
+ Vereinfachen Sie die Kostenzuweisung, indem Sie jedes Replikat seinem jeweiligen Konto in Rechnung stellen AWS 

Weitere Informationen finden Sie unter [Vorteile der Verwendung mehrerer AWS Konten](https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/benefits-of-using-multiple-aws-accounts.html). Wenn für Ihre Workloads keine Replikation mehrerer Konten erforderlich ist oder Sie eine einfachere Replikatverwaltung mit lokalen Überschreibungen wünschen, können Sie weiterhin globale Tabellen mit demselben Konto verwenden.

Sie können globale Tabellen mit mehreren Konten konfigurieren. [Multi-Region Eventual Consistency (MREC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrec) Für konfigurierte globale Tabellen unterstützen das Modell mit mehreren Konten [Multi-Region Strong Consistency (MRSC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrsc) nicht.

**Topics**
+ [So funktionieren globale DynamoDB-Tabellen](V2globaltables_MA_HowItWorks.md)
+ [Tutorials: Globale Tabellen mit mehreren Konten erstellen](V2globaltables_MA.tutorial.md)
+ [Sicherheit von globalen DynamoDB-Tabellen](globaltables_MA_security.md)

# So funktionieren globale DynamoDB-Tabellen
<a name="V2globaltables_MA_HowItWorks"></a>

Globale Tabellen mit mehreren Konten erweitern die vollständig verwalteten, serverlosen, regionsübergreifenden und multiaktiven Funktionen von DynamoDB auf mehrere Konten. AWS Globale Tabellen mit mehreren Konten replizieren Daten über AWS Regionen und Konten hinweg und bieten dieselbe aktive/aktive Funktionalität wie globale Tabellen mit demselben Konto. Wenn Sie in ein Replikat schreiben, repliziert DynamoDB die Daten auf alle anderen Replikate.

Zu den wichtigsten Unterschieden zu globalen Tabellen mit demselben Konto gehören:
+ Die Replikation mehrerer Konten wird für globale Tabellen mit Multi-Region Eventual Consistency (MREC) unterstützt.
+ Sie können Replikate nur hinzufügen, indem Sie mit einer Tabelle mit einer einzigen Region beginnen. Die Konvertierung einer vorhandenen globalen Tabelle mit demselben Konto in eine Konfiguration mit mehreren Konten wird nicht unterstützt. Um zu migrieren, müssen Sie vorhandene Replikate löschen, um zu einer Tabelle mit nur einer Region zurückzukehren, bevor Sie eine neue globale Tabelle mit mehreren Konten erstellen.
+ Jedes Replikat muss sich in einem separaten Konto befinden. AWS *Für eine globale Tabelle mit mehreren Konten und *N* Replikaten benötigen Sie N Konten.*
+ Globale Tabellen mit mehreren Konten verwenden standardmäßig einheitliche Tabelleneinstellungen für alle Replikate. Alle Replikate verwenden automatisch dieselbe Konfiguration (wie Durchsatzmodus und TTL), und im Gegensatz zu globalen Tabellen mit demselben Konto können diese Einstellungen nicht pro Replikat außer Kraft gesetzt werden.
+ Kunden müssen in ihren Ressourcenrichtlinien Replikationsberechtigungen für den DynamoDB-Dienstprinzipal für globale Tabellen bereitstellen.

Globale Tabellen mit mehreren Konten verwenden dieselbe zugrunde liegende Replikationstechnologie wie globale Tabellen mit demselben Konto. Tabelleneinstellungen werden automatisch auf alle regionalen Replikate repliziert, und Kunden können die Einstellungen nicht für jedes Replikat überschreiben oder anpassen. Dies gewährleistet eine konsistente Konfiguration und ein vorhersehbares Verhalten für mehrere AWS Konten, die an derselben globalen Tabelle teilnehmen.

Einstellungen in globalen DynamoDB-Tabellen definieren, wie sich eine Tabelle verhält und wie Daten regionsübergreifend repliziert werden. Diese Einstellungen werden während der Tabellenerstellung oder APIs beim Hinzufügen eines neuen regionalen Replikats über die DynamoDB-Steuerebene konfiguriert.

Bei der Erstellung einer globalen Tabelle mit mehreren Konten müssen Kunden `GlobalTableSettingsReplicationMode = ENABLED` für jedes regionale Replikat Einstellungen vornehmen. Dadurch wird sichergestellt, dass in einer Region vorgenommene Konfigurationsänderungen automatisch auf alle anderen Regionen übertragen werden, die Teil der globalen Tabelle sind.

Sie können die Replikation der Einstellungen nach der Tabellenerstellung aktivieren. Dies unterstützt das Szenario, in dem eine Tabelle ursprünglich als regionale Tabelle erstellt und später zu einer globalen Tabelle mit mehreren Konten aktualisiert wurde.

**Synchronisierte Einstellungen**

Die folgenden Tabelleneinstellungen werden immer für alle Replikate in einer globalen Tabelle mit mehreren Konten synchronisiert:

**Anmerkung**  
Im Gegensatz zu globalen Tabellen mit demselben Konto lassen globale Tabellen mit mehreren Konten keine regionsspezifischen Überschreibungen für diese Einstellungen zu. Die einzige Ausnahme besteht darin, dass Überschreibungen für Richtlinien zur auto-scaling von Lesevorgängen (Tabellen und GSIs) zulässig sind, da es sich um separate externe Ressourcen handelt.
+ Kapazitätsmodus (bereitgestellte oder On-Demand-Kapazität)
+ Von der Tabelle bereitgestellte Lese- und Schreibkapazität
+ auto Skalierung beim Lesen und Schreiben von Tabellen
+ Definition des lokalen sekundären Index (LSI)
+ Definition des globalen sekundären Index (GSI)
+ Von GSI bereitgestellte Lese- und Schreibkapazität
+ GSI Auto Scaling mit Lese- und Schreibzugriff
+ Streams-Definition im MREC-Modus
+ Time to Live (TTL)
+ Warmdurchsatz
+ Maximaler Lese- und Schreibdurchsatz auf Abruf

**Nicht synchronisierte Einstellungen**

Die folgenden Einstellungen werden nicht zwischen Replikaten synchronisiert und müssen für jede Replikattabelle in jeder Region unabhängig konfiguriert werden.
+ Tabellenklasse
+ Typ der serverseitigen Verschlüsselung (Server-Side Encryption, SSE)
+ Point-in-time Wiederherstellung
+ KMS-Schlüssel-ID für serverseitige Verschlüsselung (SSE)
+ Löschschutz
+ Kinesis Data Streams (KDSD)
+ Tags (Markierungen)
+ Ressourcenrichtlinie
+ Tabelle Cloudwatch-Contributor Insights (CCI)
+ Einblicke in GSI Cloudwatch Contributor (CCI)

## Überwachen
<a name="V2globaltables_MA_HowItWorks.monitoring"></a>

In globalen Tabellen, die für Multi-Region Eventual Consistency (MREC) konfiguriert sind, wird die Metrik veröffentlicht. [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency) CloudWatch Diese Metrik misst die verstrichene Zeit zwischen dem Schreiben eines Elements in eine Replikattabelle und dem Erscheinen dieses Elements in einem anderen Replikat in der globalen Tabelle. `ReplicationLatency` wird in Millisekunden ausgedrückt und für jedes Paar aus Quell- und Zielregion ausgegeben.

Typische `ReplicationLatency` Werte hängen von der Entfernung zwischen den ausgewählten AWS Regionen sowie von anderen Variablen wie Workload-Typ und Durchsatz ab. Beispiel: Ein Quellreplikat in der Region USA West (Nordkalifornien) (us-west-1) weist im Vergleich zur Region Afrika (Kapstadt) (af-south-1) einen niedrigeren Wert für `ReplicationLatency` auf als die Region USA West (Oregon) (us-west-2).

Ein erhöhter Wert für `ReplicationLatency` könnte darauf hinweisen, dass Updates von einem Replikat nicht in einem angemessenen Zeitraum an andere Replikattabellen verteilt werden. In diesem Fall können Sie die Lese- und Schreibaktivität Ihrer Anwendung vorübergehend in eine andere AWS Region umleiten.

**Behandlung von Problemen mit der Replikationslatenz in globalen Tabellen mit mehreren Konten**

Wenn aufgrund von vom Kunden verursachten Problemen mit einer Replikattabelle `ReplicationLatency` mehr als 3 Stunden vergangen sind, sendet DynamoDB eine Benachrichtigung, in der der Kunde aufgefordert wird, das zugrunde liegende Problem zu beheben. Zu den häufigsten kundenbedingten Problemen, die eine Replikation verhindern können, gehören:
+ Entfernen der erforderlichen Berechtigungen aus der Ressourcenrichtlinie der Replikattabelle
+ Abmeldung von einer AWS Region, in der ein Replikat der globalen Tabelle mit mehreren Konten gehostet wird
+ Verweigerung der zum Entschlüsseln von Daten erforderlichen AWS KMS-Schlüsselberechtigungen für die Tabelle

DynamoDB sendet innerhalb von 3 Stunden bei erhöhter Replikationslatenz eine erste Benachrichtigung, gefolgt von einer zweiten Benachrichtigung nach 20 Stunden, falls das Problem weiterhin besteht. Wenn das Problem nicht innerhalb des erforderlichen Zeitfensters behoben wird, trennt DynamoDB das Replikat automatisch von der globalen Tabelle. Das betroffene Replikat wird dann in eine regionale Tabelle konvertiert.

# Tutorials: Globale Tabellen mit mehreren Konten erstellen
<a name="V2globaltables_MA.tutorial"></a>

Dieser Abschnitt enthält step-by-step Anweisungen zum Erstellen globaler DynamoDB-Tabellen, die sich über mehrere AWS Konten erstrecken.

## Erstellen Sie mit der DynamoDB-Konsole eine globale Tabelle mit mehreren Konten
<a name="create-ma-gt-console"></a>

Gehen Sie wie folgt vor, um eine globale Tabelle mit mehreren Konten mithilfe von zu erstellen. AWS-Managementkonsole Im folgenden Beispiel wird eine globale Tabelle mit Replikattabellen in den Vereinigte Staaten erstellt.

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)für das erste Konto (sagen wir*111122223333*).

1. Wählen Sie für dieses Beispiel in der Regionsauswahl in der Navigationsleiste die Region **USA Ost (Ohio)** aus.

1. Klicken Sie im Navigationsbereich auf der linken Seite der Konsole auf **Tabellen**.

1. Wählen Sie **Tabelle erstellen** aus.

1. Gehen Sie auf der Seite **Tabelle erstellen** wie folgt vor:

   1. Geben Sie unter **Tabellenname** **MusicTable** ein.

   1. Geben Sie unter **Partitionsschlüssel** den Wert **Artist** ein.

   1. Geben Sie unter **(Sortierschlüssel)** den Wert **SongTitle** ein.

   1. Behalten Sie die übrigen Standardeinstellungen bei und wählen Sie **Tabelle erstellen** aus.

1. Fügen Sie der Tabelle die folgende Ressourcenrichtlinie hinzu

------
#### [ JSON ]

****  

   ```
   {
   "Version":"2012-10-17",		 	 	 
   "Statement": [
       {
           "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
           "Effect": "Allow",
           "Action": [
               "dynamodb:ReadDataForReplication",
               "dynamodb:WriteDataForReplication",
               "dynamodb:ReplicateSettings"
           ],
           "Resource": "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable",
           "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
           "Condition": {
               "StringEquals": {
                   "aws:SourceAccount": ["444455556666","111122223333"],
                   "aws:SourceArn": [
                       "arn:aws:dynamodb:us-east-1:444455556666:table/MusicTable",
                       "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable"
                   ]
               }
           }
       },
       {
           "Sid": "AllowTrustedAccountsToJoinThisGlobalTable",
           "Effect": "Allow",
           "Action": [
               "dynamodb:AssociateTableReplica"
           ],
           "Resource": "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable",
           "Principal": {"AWS": ["444455556666"]}
       }
   ]
   }
   ```

------

1. Diese neue Tabelle dient als erste Replikattabelle in einer neuen globalen Tabelle. Sie stellt den Prototyp für andere Replikattabellen dar, die Sie später hinzufügen.

1. Warten Sie, bis die Tabelle **aktiv** wird. Navigieren Sie für die neu erstellte Tabelle auf der Registerkarte **Globale Tabellen** zu **Einstellungen > Replikation** und klicken Sie auf **Aktivieren**.

1. Melden Sie sich von diesem Konto ab (*111122223333*hier).

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)für das zweite Konto (z. B.). *444455556666*

1. Wählen Sie für dieses Beispiel in der Navigationsleiste in der Regionsauswahl die Option **US East (Nord-Virginia)** aus.

1. Die Konsole stellt sicher, dass die ausgewählte Region keine Tabelle mit demselben Namen enthält. Wenn eine Tabelle mit demselben Namen vorhanden ist, müssen Sie die vorhandene Tabelle löschen, bevor Sie eine neue Replikattabelle in der betreffenden Region erstellen können.

1. Wählen Sie in der Dropdownliste neben **Tabelle erstellen** die Option **Aus einem anderen Konto erstellen**

1. Gehen Sie auf der Seite **Tabelle aus einem anderen Konto erstellen** wie folgt vor:

   1. Fügen Sie **arn:aws:dynamodb:us-east-2:*111122223333*:table/MusicTable** als Tabelle arn für die Quelltabelle hinzu.

   1. Fügen Sie in der **Replikattabelle ARNs** erneut **arn:aws:dynamodb:us-east-2:*111122223333*:table/MusicTable** den ARN der Quelltabelle hinzu. Wenn bereits mehrere Replikate als Teil einer globalen Tabelle mit mehreren Konten vorhanden sind, müssen Sie jedes vorhandene Replikat dem ReplicaTable ARN hinzufügen.

   1. **Behalten Sie die anderen Standardeinstellungen bei und wählen Sie Submit.**

1. Auf der Registerkarte „**Globale Tabellen**“ für die Tabelle „Musik“ (und für alle anderen Replikattabellen) wird angezeigt, dass die Tabelle in mehreren Regionen repliziert wurde.

1. So testen Sie die Replikation:

   1. Sie können jede Region, in der ein Replikat vorhanden ist, für diese Tabelle verwenden

   1. Wählen Sie **Tabellenelemente erkunden** aus.

   1. Wählen Sie **Element erstellen** aus.

   1. Geben Sie **item\$11** für **Künstler** und **Song Value 1** für ein **SongTitle**.

   1. Wählen Sie **Element erstellen** aus.

   1. Überprüfen Sie die Replikation, indem Sie zu den anderen Regionen wechseln:

   1. Vergewissern Sie sich, dass die Tabelle Music das von Ihnen erstellte Objekt enthält.

## Erstellen Sie eine globale Tabelle mit mehreren Konten mithilfe der AWS CLI
<a name="ma-gt-cli"></a>

Die folgenden Beispiele zeigen, wie Sie mit dem eine globale Tabelle mit mehreren Konten erstellen. AWS CLI Diese Beispiele veranschaulichen den vollständigen Arbeitsablauf für die Einrichtung der kontenübergreifenden Replikation.

------
#### [ CLI ]

Verwenden Sie die folgenden AWS CLI Befehle, um eine globale Tabelle mit mehreren Konten und kontenübergreifender Replikation zu erstellen.

```
# STEP 1: Setting resource policy for the table in account 111122223333

cat > /tmp/source-resource-policy.json << 'EOF'
{
    "Version": "2012-10-17", 		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": ["444455556666","111122223333"],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:us-east-1:444455556666:table/MusicTable",
                        "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable"
                    ]
                }
            }
        },
        {
            "Sid": "AllowTrustedAccountsToJoinThisGlobalTable",
            "Effect": "Allow",
            "Action": [
                "dynamodb:AssociateTableReplica"
            ],
            "Resource": "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable",
            "Principal": {"AWS": ["444455556666"]}
        }
    ]
}
EOF

# Step 2: Create a new table (MusicTable) in US East (Ohio), 
#   with DynamoDB Streams enabled (NEW_AND_OLD_IMAGES),
#   and Settings Replication ENABLED on the account 111122223333

aws dynamodb create-table \
    --table-name MusicTable \
    --attribute-definitions \
        AttributeName=Artist,AttributeType=S \
        AttributeName=SongTitle,AttributeType=S \
    --key-schema \
        AttributeName=Artist,KeyType=HASH \
        AttributeName=SongTitle,KeyType=RANGE \
    --billing-mode PAY_PER_REQUEST \
    --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES \
    --global-table-settings-replication-mode ENABLED \
    --resource-policy file:///tmp/source-resource-policy.json \
    --region us-east-2 


# Step 3: Creating replica table in account 444455556666

# Resource policy for account 444455556666
cat > /tmp/dest-resource-policy.json << 'EOF'
{
    "Version": "2012-10-17", 		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:us-east-1:444455556666:table/MusicTable",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": ["444455556666","111122223333"],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:us-east-1:444455556666:table/MusicTable",
                        "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable"
                    ]
                }
            }
        }
    ]
}
EOF

# Execute the replica table creation
aws dynamodb create-table \
    --table-name MusicTable \
    --global-table-source-arn "arn:aws:dynamodb:us-east-2:111122223333:table/MusicTable" \
    --resource-policy file:///tmp/dest-resource-policy.json \
    --global-table-settings-replication-mode ENABLED \
    --region us-east-1

# Step 4: View the list of replicas created using describe-table
aws dynamodb describe-table \
    --table-name MusicTable \
    --region us-east-2 \
    --query 'Table.{TableName:TableName,TableStatus:TableStatus,MultiRegionConsistency:MultiRegionConsistency,Replicas:Replicas[*].{Region:RegionName,Status:ReplicaStatus}}'

# Step 5: To verify that replication is working, add a new item to the Music table in US East (Ohio)
aws dynamodb put-item \
    --table-name MusicTable \
    --item '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-2

# Step 6: Wait for a few seconds, and then check to see whether the item has been 
# successfully replicated to US East (N. Virginia) and Europe (Ireland)
aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-1

aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-2

# Step 7: Delete the replica table in US East (N. Virginia) Region
aws dynamodb delete-table \
    --table-name MusicTable \
    --region us-east-1

# Clean up: Delete the primary table
aws dynamodb delete-table \
    --table-name MusicTable \
    --region us-east-2
```

------

# Sicherheit von globalen DynamoDB-Tabellen
<a name="globaltables_MA_security"></a>

Globale Tabellenreplikate sind DynamoDB-Tabellen. Sie verwenden also dieselben Methoden zur Steuerung des Zugriffs auf Replikate wie für Tabellen mit einer einzelnen Region, einschließlich AWS Identity and Access Management (IAM-) Identitätsrichtlinien und ressourcenbasierter Richtlinien. In diesem Thema wird beschrieben, wie Sie globale DynamoDB-Tabellen mit mehreren Konten mithilfe von IAM-Berechtigungen und AWS Key Management Service () -Verschlüsselung sichern.AWS KMS Sie erfahren mehr über die ressourcenbasierten Richtlinien und serviceverknüpften Rollen (SLR), die eine regionsübergreifende kontenübergreifende Replikation und auto-scaling ermöglichen, sowie über die IAM-Berechtigungen, die zum Erstellen, Aktualisieren und Löschen globaler Tabellen für MREC-Tabellen (Multi-Region Eventual Consistency) erforderlich sind. Außerdem erfahren Sie mehr über Verschlüsselungsschlüssel, mit denen Sie die regionsübergreifende Replikation sicher verwalten können. AWS KMS 

Es enthält detaillierte Informationen zu den ressourcenbasierten Richtlinien und Berechtigungen, die für die Einrichtung der konto- und regionsübergreifenden Tabellenreplikation erforderlich sind. Das Verständnis dieses Sicherheitsmodells ist für Kunden, die sichere, kontoübergreifende Datenreplikationslösungen implementieren müssen, von entscheidender Bedeutung.

## Serviceprinzipalautorisierung für die Replikation
<a name="globaltables_MA_service_principal"></a>

Die globalen Tabellen von DynamoDB mit mehreren Konten verwenden einen eigenen Autorisierungsansatz, da die Replikation über Kontogrenzen hinweg durchgeführt wird. Dies erfolgt mithilfe des Replikationsdienstprinzipals von DynamoDB:. `replication.dynamodb.amazonaws.com` Jedes teilnehmende Konto muss diesen Prinzipal in der Ressourcenrichtlinie der Replikattabelle explizit zulassen und ihm damit Berechtigungen geben, die durch Quellkontextbedingungen für Schlüssel wie`aws:SourceAccount`, `aws:SourceArn` usw. auf bestimmte Replikate beschränkt werden können. Weitere Informationen finden Sie unter [AWS globale Bedingungsschlüssel](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html). Die Berechtigungen sind bidirektional, was bedeutet, dass sich alle Replikate gegenseitig ausdrücklich Berechtigungen gewähren müssen, bevor die Replikation für ein bestimmtes Replikatpaar eingerichtet werden kann.

Die folgenden Dienstprinzipalberechtigungen sind für die kontenübergreifende Replikation unerlässlich:
+ `dynamodb:ReadDataForReplication`gewährt die Möglichkeit, Daten für Replikationszwecke zu lesen. Mit dieser Berechtigung können Änderungen an einem Replikat gelesen und an andere Replikate weitergegeben werden.
+ `dynamodb:WriteDataForReplication`ermöglicht das Schreiben replizierter Daten in Zieltabellen. Mit dieser Berechtigung können Änderungen zwischen allen Replikaten in der globalen Tabelle synchronisiert werden.
+ `dynamodb:ReplicateSettings`ermöglicht die Synchronisation von Tabelleneinstellungen zwischen Replikaten und sorgt so für eine konsistente Konfiguration in allen beteiligten Tabellen.

Jedes Replikat muss allen anderen Replikaten und sich selbst die oben genannten Berechtigungen gewähren — d. h. die Quellkontextbedingungen müssen den gesamten Satz von Replikaten umfassen, aus dem die globale Tabelle besteht. Diese Berechtigungen werden für jedes neue Replikat überprüft, wenn es zu einer globalen Tabelle mit mehreren Konten hinzugefügt wird. Dadurch wird überprüft, ob Replikationsvorgänge nur vom autorisierten DynamoDB-Dienst und nur zwischen den vorgesehenen Tabellen ausgeführt werden.

## Mit Diensten verknüpfte Rollen für globale Tabellen mit mehreren Konten
<a name="globaltables_MA_service_linked_roles"></a>

DynamoDB-Tabellen mit mehreren Konten replizieren Einstellungen über alle Replikate hinweg, sodass jedes Replikat identisch eingerichtet wird, einen konsistenten Durchsatz aufweist und ein nahtloses Failover-Erlebnis bietet. Die Replikation von Einstellungen wird über die `ReplicateSettings` Berechtigungen des Dienstprinzipals gesteuert, aber wir verlassen uns auch auf dienstverknüpfte Rollen (SLRs), um bestimmte kontenübergreifende Funktionen für die regionsübergreifende Replikation und auto-scaling zu verwalten. Diese Rollen werden nur einmal pro Konto eingerichtet. AWS Nach der Erstellung dienen dieselben Rollen für alle globalen Tabellen in Ihrem Konto. Weitere Informationen zu serviceverknüpften Rollen finden Sie unter [Verwenden von serviceverknüpften Rollen](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create-service-linked-role.html) im IAM-Benutzerhandbuch.

### Mit dem Dienst verknüpfte Rolle für die Verwaltung von Einstellungen
<a name="globaltables_MA_settings_management_slr"></a>

Amazon DynamoDB erstellt automatisch die AWSService RoleForDynamo DBGlobal TableSettingsManagement serviceverknüpfte Rolle (SLR), wenn Sie Ihr erstes globales Tabellenreplikat mit mehreren Konten im Konto erstellen. Diese Rolle verwaltet die kontoübergreifende regionsübergreifende Replikation von Einstellungen für Sie.

Wenn Sie ressourcenbasierte Richtlinien auf Replikate anwenden, stellen Sie sicher, dass Sie keine der im SLR-Prinzipal definierten Berechtigungen verweigern, da dies die Einstellungsverwaltung beeinträchtigen und die Replikation beeinträchtigen könnte, wenn der Durchsatz zwischen den Replikaten nicht übereinstimmt oder. `AWSServiceRoleForDynamoDBGlobalTableSettingsManagement` GSIs Wenn Sie die erforderlichen SLR-Berechtigungen verweigern, wird die Replikation zu und von den betroffenen Replikaten möglicherweise beendet, und der Status der Replikattabelle ändert sich auf. `REPLICATION_NOT_AUTHORIZED` Wenn bei globalen Tabellen mit mehreren Konten ein Replikat länger als 20 Stunden im `REPLICATION_NOT_AUTHORIZED` Status verbleibt, wird das Replikat unwiderruflich in eine DynamoDB-Tabelle mit einer einzigen Region konvertiert. Die Spiegelreflexkamera hat die folgenden Berechtigungen:
+ `application-autoscaling:DeleteScalingPolicy`
+ `application-autoscaling:DescribeScalableTargets`
+ `application-autoscaling:DescribeScalingPolicies`
+ `application-autoscaling:DeregisterScalableTarget`
+ `application-autoscaling:PutScalingPolicy`
+ `application-autoscaling:RegisterScalableTarget`

### Mit dem Auto Scaling Service verknüpfte Rolle
<a name="globaltables_MA_autoscaling_slr"></a>

Bei der Konfiguration einer globalen Tabelle für den Modus mit bereitgestellter Kapazität muss Auto Scaling für die globale Tabelle konfiguriert werden. DynamoDB Auto Scaling verwendet den AWS Application Auto Scaling Scaling-Dienst, um die bereitgestellte Durchsatzkapazität auf Ihren globalen Tabellenreplikaten dynamisch anzupassen. Der Application Auto Scaling Scaling-Dienst erstellt eine serviceverknüpfte Rolle (SLR) mit dem Namen. [AWSServiceRoleForApplicationAutoScaling\$1DynamoDBTable](https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html) Diese serviceverknüpfte Rolle wird automatisch in Ihrem AWS Konto erstellt, wenn Sie Auto Scaling für eine DynamoDB-Tabelle zum ersten Mal konfigurieren. Es ermöglicht Application Auto Scaling, die bereitgestellte Tabellenkapazität zu verwalten und CloudWatch Alarme zu erstellen.

Wenn Sie ressourcenbasierte Richtlinien auf Replikate anwenden, stellen Sie sicher, dass Sie dem Application Auto Scaling SLR-Prinzipal keine in der [AWSApplicationAutoscalingDynamoDBTableRichtlinie](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html) definierten Berechtigungen verweigern, da dadurch die Auto-Scaling-Funktionalität unterbrochen wird.

## AWS Wie globale Tabellen IAM verwenden
<a name="globaltables_MA_iam"></a>

In den folgenden Abschnitten werden die erforderlichen Berechtigungen für verschiedene globale Tabellenoperationen beschrieben und Richtlinienbeispiele bereitgestellt, die Ihnen bei der Konfiguration des entsprechenden Zugriffs für Ihre Benutzer und Anwendungen helfen sollen.

**Anmerkung**  
Alle beschriebenen Berechtigungen müssen auf die spezifische Tabellenressource ARN in den betroffenen Regionen angewendet werden. Die Tabellenressource ARN folgt dem Format`arn:aws:dynamodb:region:account-id:table/table-name`, in dem Sie Ihre tatsächlichen Werte für Region, Konto-ID und Tabellennamen angeben müssen.

Die folgenden step-by-step Themen behandeln wir in den folgenden Abschnitten:
+ Globale Tabellen mit mehreren Konten erstellen und Replikate hinzufügen
+ Aktualisierung einer globalen Tabelle mit mehreren Konten
+ Löschen globaler Tabellen und Entfernen von Replikaten

### Globale Tabellen erstellen und Replikate hinzufügen
<a name="globaltables_MA_creating"></a>

#### Berechtigungen für die Erstellung globaler Tabellen
<a name="globaltables_MA_creating_permissions"></a>

Wenn ein neues Replikat zu einer regionalen Tabelle hinzugefügt wird, um eine globale Tabelle mit mehreren Konten zu bilden, oder zu einer vorhandenen globalen Tabelle mit mehreren Konten, muss der IAM-Prinzipal, der die Aktion ausführt, von allen vorhandenen Mitgliedern autorisiert werden. Alle vorhandenen Mitglieder müssen in ihrer Tabellenrichtlinie die folgenden Berechtigungen erteilen, damit das Replikat erfolgreich hinzugefügt werden kann:
+ `dynamodb:AssociateTableReplica`- Mit dieser Berechtigung können Tabellen zu einer globalen Tabellenkonfiguration zusammengefügt werden. Dies ist die grundlegende Berechtigung, die den anfänglichen Aufbau der Replikationsbeziehung ermöglicht.

Durch diese präzise Steuerung können nur autorisierte Konten an der globalen Tabelleneinrichtung teilnehmen.

#### Beispiel für IAM-Richtlinien zum Erstellen globaler Tabellen
<a name="globaltables_MA_creating_examples"></a>

##### Beispiel für IAM-Richtlinien für ein Setup mit zwei Replikaten
<a name="globaltables_MA_2replica_example"></a>

Die Einrichtung globaler Tabellen mit mehreren Konten folgt einem bestimmten Autorisierungsablauf, der eine sichere Replikation gewährleistet. Lassen Sie uns anhand eines praktischen Szenarios untersuchen, wie dies in der Praxis funktioniert, in dem ein Kunde eine globale Tabelle mit zwei Replikaten einrichten möchte. Das erste Replikat (ReplicA) befindet sich in Konto A in der Region ap-east-1, während sich das zweite Replikat (ReplicAB) in Konto B in der Region eu-south-1 befindet.
+ Im Quellkonto (Konto A) beginnt der Prozess mit der Erstellung der primären Replikattabelle. Der Kontoadministrator muss dieser Tabelle eine ressourcenbasierte Richtlinie beifügen, die dem Zielkonto (Konto B) ausdrücklich die erforderlichen Berechtigungen erteilt, um die Zuordnung durchzuführen. Diese Richtlinie autorisiert auch den DynamoDB-Replikationsdienst, wichtige Replikationsaktionen durchzuführen.
+ Das Zielkonto (Konto B) folgt einem ähnlichen Prozess, indem es beim Erstellen des Replikats eine entsprechende ressourcenbasierte Richtlinie anhängt und auf den ARN der Quelltabelle verweist, der zur Erstellung des Replikats verwendet werden soll. Diese Richtlinie spiegelt die von Konto A erteilten Berechtigungen wider und schafft so eine vertrauenswürdige bidirektionale Beziehung. Bevor die Replikation eingerichtet wird, validiert DynamoDB diese kontoübergreifenden Berechtigungen, um sicherzustellen, dass die richtige Autorisierung vorhanden ist.

So richten Sie dieses Setup ein:
+ Der Administrator von Konto A muss zuerst die ressourcenbasierte Richtlinie an ReplicAA anhängen. Diese Richtlinie gewährt Konto B und dem DynamoDB-Replikationsdienst ausdrücklich die erforderlichen Berechtigungen.
+ In ähnlicher Weise muss der Administrator von Konto B im Aufruf create table Replica B, das auf Replikat A als Quelltabelle verweist, eine entsprechende Richtlinie an Replicab anhängen, wobei die Kontoreferenzen umgekehrt werden, um Konto A die entsprechenden Berechtigungen zu gewähren.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [ "111122223333", "444455556666" ],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                        "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB"
                    ]
                }
            }
        },
        {
            "Sid": "AllowTrustedAccountsToJoinThisGlobalTable",
            "Effect": "Allow",
            "Action": [
                "dynamodb:AssociateTableReplica"
            ],
            "Resource": "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
            "Principal": {"AWS": ["444455556666"]}
        }
    ]
}
```

------

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [ "111122223333", "444455556666" ],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                        "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB"
                    ]
                }
            }
        }
    ]
}
```

------

##### Beispiel für IAM-Richtlinien für ein Setup mit drei Replikaten
<a name="globaltables_MA_3replica_example"></a>

In diesem Setup haben wir jeweils 3 Replikate ReplicA, Replicab und ReplicaC in Konto A, Konto B und Konto C. Replikat A ist das erste Replikat, das als regionale Tabelle beginnt und der dann Replicab und ReplicaC hinzugefügt werden.
+ Der Administrator von Konto A muss zuerst ReplicA die ressourcenbasierte Richtlinie zuordnen, sodass die Replikation mit allen Mitgliedern möglich ist und den IAM-Prinzipalen von Konto B und Konto C das Hinzufügen von Replikaten ermöglicht wird.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [ "111122223333", "444455556666", "123456789012" ],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                        "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB",
                        "arn:aws:dynamodb:us-east-1:123456789012:table/ReplicaC"
                    ]
                }
            }
        },
        {
            "Sid": "AllowTrustedAccountsToJoinThisGlobalTable",
            "Effect": "Allow",
            "Action": [
                "dynamodb:AssociateTableReplica"
            ],
            "Resource": "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
            "Principal": { "AWS": [ "444455556666", "123456789012" ] }
        }
    ]
}
```

------
+ Der Administrator von Konto B muss ein Replikat (Replikat B) hinzufügen, das auf Replica A als Quelle verweist. Für Replikat B gilt die folgende Richtlinie, die die Replikation zwischen allen Mitgliedern ermöglicht und es Konto C ermöglicht, ein Replikat hinzuzufügen:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [ "111122223333", "444455556666", "123456789012" ],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                        "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB",
                        "arn:aws:dynamodb:us-east-1:123456789012:table/ReplicaC"
                    ]
                }
            }
        },
        {
            "Sid": "AllowTrustedAccountsToJoinThisGlobalTable",
            "Effect": "Allow",
            "Action": [
                "dynamodb:AssociateTableReplica"
            ],
            "Resource": "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB",
            "Principal": { "AWS": [ "123456789012" ] }
        }
    ]
}
```

------
+ Schließlich erstellt der Administrator von Konto C ein Replikat mit der folgenden Richtlinie, die Replikationsberechtigungen zwischen allen Mitgliedern gewährt. Die Richtlinie erlaubt nicht, dass weitere Replikate hinzugefügt werden.

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "DynamoDBActionsNeededForSteadyStateReplication",
            "Effect": "Allow",
            "Action": [
                "dynamodb:ReadDataForReplication",
                "dynamodb:WriteDataForReplication",
                "dynamodb:ReplicateSettings"
            ],
            "Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/ReplicaC",
            "Principal": {"Service": ["replication.dynamodb.amazonaws.com"]},
            "Condition": {
                "StringEquals": {
                    "aws:SourceAccount": [ "111122223333", "444455556666" ],
                    "aws:SourceArn": [
                        "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                        "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB"
                    ]
                }
            }
        }
    ]
}
```

------

### Aktualisierung einer globalen Tabelle mit mehreren Konten
<a name="globaltables_MA_updating"></a>

Um die Replikateinstellungen für eine bestehende globale Tabelle mithilfe der UpdateTable API zu ändern, benötigen Sie die folgende Berechtigung für die Tabellenressource in der Region, in der Sie den API-Aufruf tätigen: `dynamodb:UpdateTable`

Sie können auch andere globale Tabellenkonfigurationen aktualisieren, z. B. Richtlinien für auto Skalierung und Time-to-Live-Einstellungen. Für diese zusätzlichen Aktualisierungsvorgänge sind die folgenden Berechtigungen erforderlich:

Um die Time-to-Live-Einstellungen mit der `UpdateTimeToLive` API zu aktualisieren, benötigen Sie die folgenden Berechtigungen für die Tabellenressource in allen Regionen, die Replikate enthalten: `dynamodb:UpdateTimeToLive`

Um eine Replica-Auto-Scaling-Richtlinie mit der `UpdateTableReplicaAutoScaling` API zu aktualisieren, benötigen Sie die folgenden Berechtigungen für die Tabellenressource in allen Regionen, die Replikate enthalten:
+ `application-autoscaling:DeleteScalingPolicy`
+ `application-autoscaling:DeleteScheduledAction`
+ `application-autoscaling:DeregisterScalableTarget`
+ `application-autoscaling:DescribeScalableTargets`
+ `application-autoscaling:DescribeScalingActivities`
+ `application-autoscaling:DescribeScalingPolicies`
+ `application-autoscaling:DescribeScheduledActions`
+ `application-autoscaling:PutScalingPolicy`
+ `application-autoscaling:PutScheduledAction`
+ `application-autoscaling:RegisterScalableTarget`

**Anmerkung**  
Sie müssen `dynamodb:ReplicateSettings` Berechtigungen für alle Replikatregionen und Konten bereitstellen, damit die Aktualisierungstabelle erfolgreich aktualisiert werden kann. Wenn ein Replikat nicht berechtigt ist, Einstellungen auf ein beliebiges Replikat in der globalen Tabelle mit `AccessDeniedException` mehreren Konten zu replizieren, schlagen alle Aktualisierungsvorgänge für alle Replikate fehl, bis die Berechtigungen repariert sind.

### Löschen globaler Tabellen und Entfernen von Replikaten
<a name="globaltables_MA_deleting"></a>

Um eine globale Tabelle zu löschen, müssen Sie alle Replikate entfernen. Im Gegensatz zu Global Table mit demselben Konto können Sie diese Option nicht verwenden, `UpdateTable` um eine Replikattabelle in einer entfernten Region zu löschen. Jedes Replikat muss über die `DeleteTable` API aus dem Konto gelöscht werden, das es steuert.

#### Berechtigungen zum Löschen globaler Tabellen und zum Entfernen von Replikaten
<a name="globaltables_MA_deleting_permissions"></a>

Die folgenden Berechtigungen sind sowohl für das Entfernen einzelner Replikate als auch für das vollständige Löschen globaler Tabellen erforderlich. Durch das Löschen einer globalen Tabellenkonfiguration wird nur die Replikationsbeziehung zwischen Tabellen in verschiedenen Regionen entfernt. Die zugrunde liegende DynamoDB-Tabelle in der letzten verbleibenden Region wird nicht gelöscht. Die Tabelle in der letzten Region existiert weiterhin als standardmäßige DynamoDB-Tabelle mit denselben Daten und Einstellungen.

Sie benötigen die folgenden Berechtigungen für die Tabellenressource in jeder Region, in der Sie ein Replikat entfernen:
+ `dynamodb:DeleteTable`
+ `dynamodb:DeleteTableReplica`

## Wie verwenden globale Tabellen AWS KMS
<a name="globaltables_MA_kms"></a>

Wie alle DynamoDB-Tabellen verschlüsseln globale Tabellenreplikate Daten im Ruhezustand immer mit Verschlüsselungsschlüsseln, die im AWS Key Management Service () gespeichert sind.AWS KMS

**Anmerkung**  
Im Gegensatz zu globalen Tabellen mit demselben Konto können verschiedene Replikate in einer globalen Tabelle mit mehreren Konten mit unterschiedlichen Schlüsseltypen konfiguriert werden (AWS eigener Schlüssel oder vom Kunden AWS KMS verwalteter Schlüssel). Globale Tabellen mit mehreren Konten unterstützen keine verwalteten Schlüssel. AWS 

Globale Tabellen mit mehreren Konten, die verwendet werden, CMKs erfordern, dass die Schlüsselrichtlinie jedes Replikats dem DynamoDB-Replikationsdienstprinzipal (`replication.dynamodb.amazonaws.com`) Berechtigungen für den Zugriff auf den Schlüssel für die Replikation und die Einstellungsverwaltung erteilt. Die folgenden Berechtigungen sind erforderlich:
+ `kms:Decrypt`
+ `kms:ReEncrypt*`
+ `kms:GenerateDataKey*`
+ `kms:DescribeKey`

**Wichtig **

DynamoDB benötigt Zugriff auf den Verschlüsselungsschlüssel des Replikats, um ein Replikat zu löschen. Wenn Sie einen vom Kunden verwalteten Schlüssel, der zur Verschlüsselung eines Replikats verwendet wird, deaktivieren oder löschen möchten, weil Sie das Replikat löschen, sollten Sie zuerst das Replikat löschen, warten, bis die Tabelle aus der Replikationsgruppe entfernt wurde, indem Sie describe in einem der anderen Replikate aufrufen, und dann den Schlüssel deaktivieren oder löschen.

Wenn Sie den Zugriff von DynamoDB auf einen vom Kunden verwalteten Schlüssel, der zur Verschlüsselung eines Replikats verwendet wird, deaktivieren oder entziehen, wird die Replikation zum und vom Replikat beendet und der Replikatstatus wird auf geändert`INACCESSIBLE_ENCRYPTION_CREDENTIALS`. Wenn ein Replikat länger als 20 Stunden im `INACCESSIBLE_ENCRYPTION_CREDENTIALS` Status verbleibt, wird das Replikat irreversibel in eine DynamoDB-Tabelle mit einer einzigen Region konvertiert.

### Beispiel für eine Richtlinie AWS KMS
<a name="globaltables_MA_kms_example"></a>

Die AWS KMS Richtlinie ermöglicht DynamoDB den Zugriff auf beide AWS KMS Schlüssel für die Replikation zwischen den Replikaten A und B. Die AWS KMS Schlüssel, die dem DynamoDB-Replikat in jedem Konto zugeordnet sind, müssen mit der folgenden Richtlinie aktualisiert werden:

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": { "Service": "replication.dynamodb.amazonaws.com" },
        "Action": [
            "kms:Decrypt",
            "kms:ReEncrypt*",
            "kms:GenerateDataKey*",
            "kms:DescribeKey"
        ],
        "Resource": "*",
        "Condition": {
            "StringEquals": {
                "aws:SourceAccount": [ "111122223333", "444455556666" ],
                "aws:SourceArn": [
                    "arn:aws:dynamodb:ap-east-1:111122223333:table/ReplicaA",
                    "arn:aws:dynamodb:eu-south-1:444455556666:table/ReplicaB"
                ]
            }
        }
      }
   ]
 }
```

------

# Grundlegendes zur Amazon DynamoDB-Fakturierung für globale Tabellen
<a name="global-tables-billing"></a>

In diesem Leitfaden wird die Funktionsweise der DynamoDB-Fakturierung für globale Tabellen beschrieben und es werden die Komponenten ermittelt, die zu den Kosten globaler Tabellen beitragen, und anhand eines Beispiels veranschaulicht. 

[Globale Amazon-DynamoDB-Tabellen](GlobalTables.md) sind eine vollständig verwaltete, serverlose, multiregionale und multiaktive Datenbank. Globale Tabellen sind auf eine [Verfügbarkeit von 99,999 %](https://aws.amazon.com/dynamodb/sla/) ausgelegt und sorgen so für stabilere Anwendungen und eine höhere Geschäftskontinuität. Globale Tabellen replizieren Ihre DynamoDB-Tabellen automatisch in den AWS Regionen Ihrer Wahl, sodass Sie eine schnelle, lokale Lese- und Schreibleistung erzielen können. 

## Funktionsweise
<a name="global-tables-billing-how-it-works"></a>

Das Fakturierungsmodell für globale Tabellen unterscheidet sich von dem für DynamoDB-Tabellen mit einer Region. Schreibvorgänge in DynamoDB-Tabellen mit einer Region werden in den folgenden Einheiten abgerechnet:
+ Write Request Units (WRUs) für den On-Demand-Kapazitätsmodus, bei dem für jeden Schreibvorgang bis zu 1 KB eine WRU berechnet wird
+ Schreibkapazitätseinheiten (WCUs) für den Bereitstellungsmodus, bei dem eine WCU einen Schreibvorgang pro Sekunde für bis zu 1 KB ermöglicht

Wenn Sie eine globale Tabelle durch Hinzufügen einer Replikattabelle zu einer vorhandenen Tabelle mit einer Region erstellen, wird die Tabelle mit einer Region in eine Replikattabelle umgewandelt. Das bedeutet, dass sich auch die Einheiten für die Abrechnung von Schreibvorgängen in die Tabelle ändern. Schreibvorgänge in Replikattabellen mit einer Region werden in den folgenden Einheiten abgerechnet: 
+ Replicated Write Request Units (rWRUs) für den On-Demand-Kapazitätsmodus, bei dem für jeden Schreibvorgang bis zu 1 KB eine RWRU pro Replikattabelle berechnet wird
+ Replizierte Schreibkapazitätseinheiten (rWCUs) für den Bereitstellungskapazitätsmodus, bei dem eine WCU pro Replikattabelle einen Schreibvorgang pro Sekunde für bis zu 1 KB ermöglicht

Aktualisierungen globaler sekundärer Indizes (GSIs) werden mit denselben Einheiten abgerechnet wie DynamoDB-Tabellen mit einer Region, auch wenn es sich bei der Basistabelle für die GSI um eine Replikattabelle handelt. Aktualisierungsvorgänge für GSIs werden anhand der folgenden Einheiten abgerechnet:
+ Write Request Units (WRUs) für den On-Demand-Kapazitätsmodus, bei dem für jeden Schreibvorgang bis zu 1 KB eine WRU berechnet wird
+ Schreibkapazitätseinheiten (WCUs) für den Bereitstellungsmodus, bei dem eine WCU einen Schreibvorgang pro Sekunde für bis zu 1 KB ermöglicht

Für replizierte Schreibeinheiten (r WCUs und rWRUs) gilt der gleiche Preis wie für Schreibeinheiten mit einer Region (und). WCUs WRUs Für globale Tabellen fallen Gebühren für multiregionale Datenübertragungen an, da Daten regionsübergreifend repliziert werden. Gebühren für replizierte Schreibvorgänge (rWCU oder rWRU) fallen in jeder Region an, deren globale Tabelle eine Replikattabelle enthält.

Für Lesevorgänge aus Tabellen mit nur einer Region und aus Replikattabellen werden die folgenden Einheiten verwendet:
+ Read Request Units (RRUs) für den On-Demand-Kapazitätsmodus, bei dem für jeden stark konsistenten Lesevorgang bis zu 4 KB eine RRU berechnet wird
+ Lesekapazitätseinheiten (RCUs) für bereitgestellte Tabellen, bei denen eine RCU einen stark konsistenten Lesevorgang pro Sekunde für bis zu 4 KB ermöglicht

## Konsistenzmodi und Fakturierung
<a name="global-tables-billing-consistency-modes"></a>

Die replizierten Schreibeinheiten (r WCUs und rWRUs), die zur Abrechnung von Schreibvorgängen verwendet werden, sind sowohl für die Modi Multi-Region Strong Consistency (MRSC) als auch für Multi-Region Eventual Consistency (MREC) identisch. Für globale Tabellen, die den MRSC-Modus (Multi-Region Strong Consistency) verwenden und mit einem Zeugen konfiguriert sind, fallen keine Kosten für replizierte Schreibeinheiten (r WCUs und rWRUs), Speicherkosten oder Datenübertragungskosten für die Replikation zum Zeugen an.

## Beispiel für die Fakturierung von DynamoDB-Tabellen
<a name="global-tables-billing-example"></a>

Im Folgenden sehen Sie ein Beispielszenario über mehrere Tage, das die Abrechnung von Schreibanforderungen in globalen Tabellen in der Praxis darstellt. (Beachten Sie, dass hier nur Schreibanforderungen berücksichtigt werden und keine Gebühren für die Tabellenwiederherstellung und die regionsübergreifende Datenübertragung, die im vorliegenden Beispiel zusätzlich anfallen würden):

**Tag 1 – Tabelle mit einer Region:** Sie haben eine DynamoDB-On-Demand-Tabelle mit einer Region namens „Table\$1A“ in der Region „us-west-2“. Sie schreiben 100 Elemente mit 1 KB in Table\$1A. Für diese Schreibvorgänge mit nur einer Region wird eine Schreibanforderungseinheit (WRU) je 1 KB berechnet. Für Tag 1 fallen demnach folgende Gebühren an:
+ 100 WRUs in der Region US-West-2 für Schreibvorgänge in einer Region

**Die Gesamtzahl der am ersten Tag berechneten Anforderungseinheiten: 100. WRUs**

**Tag 2 – Erstellen einer globalen Tabelle:** Sie erstellen eine globale Tabelle, indem Sie Table\$1A in der Region „us-east-2“ ein Replikat hinzufügen. Table\$1A ist jetzt eine globale Tabelle mit zwei Replikattabellen: eine in der Region „us-west-2“ und eine in der Region „us-east-2“. Sie schreiben 150 Elemente mit 1 KB in die Replikattabelle in der Region „us-west-2“. Für Tag 2 fallen demnach folgende Gebühren an:
+ 150 r WRUs in der Region US-West-2 für replizierte Schreibvorgänge
+ 150 r WRUs in der Region us-east-2 für replizierte Schreibvorgänge

**Gesamtzahl der am zweiten Tag berechneten Anforderungseinheiten: 300 r. WRUs**

**Tag 3 – Hinzufügen eines globalen sekundären Index:** Sie fügen der Replikattabelle in der Region „us-east-2“ einen globalen sekundären Index (GSI) hinzu, der alle Attribute aus der Basistabelle (Replikattabelle) projiziert. Die globale Tabelle erstellt automatisch den globalen Index für die Replikattabelle in der Region „us-west-2“ für Sie. Sie schreiben 200 Elemente mit 1 KB in die Replikattabelle in der Region „us-west-2“. Für Tag 3 fallen demnach folgende Gebühren an:
+ • 200 r WRUs in der Region US-West-2 für replizierte Schreibvorgänge
+ • 200 WRUs in der Region US-West-2 für GSI-Updates
+ • 200 r WRUs in der Region us-east-2 für replizierte Schreibvorgänge
+ • 200 WRUs in der Region US-East-2 für GSI-Updates

Gesamtzahl der am 3. Tag berechneten Schreibanforderungseinheiten: **400 WRUs und 400 r. WRUs**

Die gesamten Gebühren für Schreibeinheiten für alle drei Tage betragen 500 WRUs (100 WRU an Tag 1 \$1 400 WRUs an Tag 3) und 700 R WRUs (300 R WRUs an Tag 2 \$1 400 R WRUs an Tag 3).

Zusammenfassend lässt sich sagen, dass Schreibvorgänge in Replikattabellen in allen Regionen, die eine Replikattabelle enthalten, in replizierten Schreibeinheiten abgerechnet werden. Wenn Sie über globale Sekundärindizes verfügen, werden Ihnen Schreibeinheiten für Aktualisierungen GSIs in allen Regionen berechnet, die einen globalen Index enthalten (was in einer globalen Tabelle für alle Regionen steht, die eine Replikattabelle enthalten). 

# Versionen von globalen DynamoDB-Tabellen
<a name="V2globaltables_versions"></a>

Es gibt zwei Versionen von globalen DynamoDB-Tabellen: Version 2019.11.21 (Aktuell) und Version 2017.11.29 (Legacy). Wir empfehlen für globale Tabellen die Verwendung der Version 2019.11.21 (Aktuell), da sie einfacher zu verwenden ist, in mehr Regionen unterstützt wird und für die meisten Workloads kostengünstiger ist als Version 2017.11.29 (Legacy).

## Ermitteln der Version einer globalen Tabelle
<a name="globaltables.DetermineVersion"></a>

### Ermitteln der Version mit dem AWS CLI
<a name="globaltables.CLI"></a>

#### Identifizieren des Replikats einer globalen Tabelle der Version 2019.11.21 (Aktuell)
<a name="globaltables.CLI.current"></a>

Rufen Sie den Befehl `describe-table` auf, um festzustellen, ob es sich bei einer Tabelle um ein Replikat von Version 2019.11.21 (Aktuell) handelt. Wenn die Ausgabe das `GlobalTableVersion`-Attribut mit dem Wert „2019.11.21“ enthält, handelt es sich bei der Tabelle um das Replikat einer globalen Tabelle der Version 2019.11.21 (Aktuell).

Beispiel eines CLI-Befehls für `describe-table`:

```
aws dynamodb describe-table \
--table-name users \
--region us-east-2
```

Wenn die (verkürzte) Ausgabe das `GlobalTableVersion`-Attribut mit dem Wert „2019.11.21“ enthält, handelt es sich bei der Tabelle um das Replikat einer globalen Tabelle der Version 2019.11.21 (Aktuell).

```
{
    "Table": {
        "AttributeDefinitions": [
            {
                "AttributeName": "id",
                "AttributeType": "S"
            },
            {
                "AttributeName": "name",
                "AttributeType": "S"
            }
        ],
        "TableName": "users",
        ...
        "GlobalTableVersion": "2019.11.21",
        "Replicas": [
            {
                "RegionName": "us-west-2",
                "ReplicaStatus": "ACTIVE",
            }
        ],
        ...
    }
}
```

#### Identifizieren des Replikats einer globalen Tabelle der Version 2017.11.29 (Legacy)
<a name="globaltables.CLI.legacy"></a>

Die Version 2017.11.29 (Legacy) verwendet einen speziellen Befehlssatz für die Verwaltung der globalen Tabelle. Rufen Sie den Befehl `describe-global-table` auf, um festzustellen, ob es sich bei einer Tabelle um ein Replikat von Version 2017.11.29 (Legacy) handelt. Wenn Sie eine erfolgreiche Antwort erhalten, handelt es sich bei der globalen Tabelle um ein Replikat der Version 2017.11.29 (Legacy). Wenn der Befehl `describe-global-table` den Fehler `GlobalTableNotFoundException` zurückgibt, handelt es sich bei der Tabelle nicht um ein Replikat der Version 2017.11.29 (Legacy).

Beispiel eines CLI-Befehls für `describe-global-table`:

```
aws dynamodb describe-global-table \
--table-name users \
--region us-east-2
```

Wenn der Befehl eine erfolgreiche Antwort zurückgibt, handelt es sich bei der globalen Tabelle um ein Replikat der Version 2017.11.29 (Legacy).

```
{
    "GlobalTableDescription": {
        "ReplicationGroup": [
            {
                "RegionName": "us-west-2"
            },
            {
                "RegionName": "us-east-2"
            }
        ],
        "GlobalTableArn": "arn:aws:dynamodb::123456789012:global-table/users",
        "CreationDateTime": "2025-06-10T13:55:53.630000-04:00",
        "GlobalTableStatus": "ACTIVE",
        "GlobalTableName": "users"
    }
}
```

### Ermitteln der Version mithilfe der DynamoDB-Konsole
<a name="globaltables.console"></a>

Gehen Sie wie folgt vor, um die Version des Replikats einer globalen Tabelle zu ermitteln:

1. [Öffnen Sie die DynamoDB-Konsole zu Hausehttps://console.aws.amazon.com/dynamodb/.](https://console.aws.amazon.com/dynamodb/home)

1. Klicken Sie im Navigationsbereich auf der linken Seite der Konsole auf **Tabellen**.

1. Wählen Sie die globale Tabelle aus, deren Version Sie ermitteln möchten.

1. Wählen Sie die Registerkarte **Globale Tabellen** aus.

   Im Abschnitt *Zusammenfassung* wird die Version der verwendeten globalen Tabellen angezeigt.

## Unterschiede im Verhalten zwischen der Legacy- und der aktuellen Version
<a name="DiffLegacyVsCurrent"></a>

In der folgenden Liste werden die Verhaltensunterschiede zwischen der Legacy-Version und der aktuellen Version globaler Tabellen beschrieben.
+ Version 2019.11.21 (Aktuell) verbraucht im Vergleich zu Version 2017.11.29 (Legacy) bei mehreren Operationen in DynamoDB-Datenbanken weniger Schreibkapazität und ist daher für die meisten Kunden kostengünstiger. Die Unterschiede in Bezug auf DynamoDB-Operationen im Einzelnen:
  + Das Aufrufen [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)eines 1-KB-Elements in einer Region und das Replizieren in andere Regionen erfordert 2 r WRUs pro Region für 2017.11.29 (Legacy), aber nur 1 RWRU für 2019.11.21 (Aktuell).
  + [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)Zum Aufrufen eines 1-KB-Elements sind 2 r WRUs in der Quellregion und 1 RWRU pro Zielregion für 2017.11.29 (Legacy) erforderlich, aber nur 1 RWRU für Quell- und Zielregion für 2019.11.21 (Aktuell).
  + Der Aufruf [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html)für ein 1-KB-Element erfordert 1 RWRU in der Quellregion und 2 r WRUs pro Zielregion für 2017.11.29 (Legacy), aber nur 1 RWRU sowohl für die Quell- als auch für die Zielregion für 2019.11.21 (Aktuell).

  Die folgende Tabelle zeigt den rWRU-Verbrauch der Tabellen-Versionen 2017.11.29 (Legacy) und 2019.11.21 (Aktuell) für ein 1 KB großes Element in zwei Regionen.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/V2globaltables_versions.html)
+ Version 2017.11.29 (Legacy) ist nur in Version 11 verfügbar. AWS-Regionen Version 2019.11.21 (Aktuell) hingegen ist in allen AWS-Regionen verfügbar.
+ Sie erstellen globale Tabellen der Version 2017.11.29 (Legacy), indem Sie zuerst einen Satz leerer Regionaltabellen erstellen und dann die API aufrufen, um die [CreateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateGlobalTable.html)globale Tabelle zu bilden. Sie erstellen globale Tabellen der Version 2019.11.21 (aktuell), indem Sie die [UpdateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API aufrufen, um einer vorhandenen Regionaltabelle ein Replikat hinzuzufügen.
+ Version 2017.11.29 (Legacy) erfordert, dass Sie alle Replikate in der Tabelle leeren, bevor Sie einer neuen Region (auch während ihrer Erstellung) ein Replikat hinzufügen. Version 2019.11.21 (Aktuell) unterstützt Sie beim Hinzufügen und Entfernen von Replikaten zu Regionen in einer Tabelle, die bereits Daten enthält.
+ Version 2017.11.29 (Legacy) verwendet die folgenden speziellen Steuerungsebenen für die Verwaltung von Replikaten: APIs 
  + [CreateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateGlobalTable.html)
  + [DescribeGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeGlobalTable.html)
  + [DescribeGlobalTableSettings](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeGlobalTableSettings.html)
  + [ListGlobalTables](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListGlobalTables.html)
  + [UpdateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateGlobalTable.html)
  + [UpdateGlobalTableSettings](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateGlobalTableSettings.html)

  Version 2019.11.21 (Aktuell) verwendet das und zur Verwaltung von Replikaten. [DescribeTable[UpdateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html) APIs 
+ In Version 2017.11.29 (Legacy) werden zwei DynamoDB-Streams-Datensätze für jeden Schreibvorgang veröffentlicht. In Version 2019.11.21 (Aktuell) wird nur ein DynamoDB-Streams-Datensatz für jeden Schreibvorgang veröffentlicht.
+ In Version 2017.11.29 (Legacy) werden die Attribute `aws:rep:deleting`, `aws:rep:updateregion` und `aws:rep:updatetime` gefüllt und aktualisiert. In Version 2019.11.21 (Aktuell) werden dieser Attribute nicht gefüllt und aktualisiert.
+ In Version 2017.11.29 (Legacy) werden die [Verwenden von Time to Live (TTL) in DynamoDB](TTL.md)-Einstellungen nicht replikatsübergreifend synchronisiert. In Version 2019.11.21 (Aktuell) werden die TTL-Einstellungen replikatsübergreifend synchronisiert.
+ In Version 2017.11.29 (Legacy) werden TTL-Löschvorgänge nicht auf andere Replikate übertragen. In Version 2019.11.21 (Aktuell) werden TTL-Löschvorgänge auf alle Replikate übertragen.
+ In Version 2017.11.29 (Legacy) werden die [Auto-Scaling](AutoScaling.md)-Einstellungen nicht replikatsübergreifend synchronisiert. In Version 2019.11.21 (Aktuell) werden die Auto-Scaling-Einstellungen replikatsübergreifend aktualisiert.
+ In Version 2017.11.29 (Legacy) werden die Einstellungen für den [globalen sekundären Index (GSI)](GSI.md) nicht replikatsübergreifend synchronisiert. In Version 2019.11.21 (Aktuell) werden die GSI-Einstellungen replikatsübergreifend synchronisiert.
+ In Version 2017.11.29 (Legacy) werden die Einstellungen für die [Verschlüsselung im Ruhezustand](encryption.usagenotes.md) nicht replikatsübergreifend synchronisiert. In Version 2019.11.21 (Aktuell) werden die Einstellungen für die Verschlüsselung im Ruhezustand replikatsübergreifend synchronisiert.
+ In Version 2017.11.29 (Legacy) wird die `PendingReplicationCount`-Metrik veröffentlicht. In Version 2019.11.21 (Aktuell) wird diese Metrik nicht veröffentlicht.

## Aktualisieren auf die aktuelle Version
<a name="upgrading-to-current-version"></a>

### Erforderliche Berechtigungen für die Aktualisierung von globalen Tabellen
<a name="V2globaltables_versions.Notes-permissions"></a>

Für eine Aktualisierung auf die Version 2019.11.21 (Aktuell) aktualisieren müssen Sie in allen Regionen mit Replikaten über die Berechtigung `dynamodb:UpdateGlobalTableversion` verfügen. Diese Berechtigungen werden zusätzlich zu den Berechtigungen benötigt, die für den Zugriff auf die DynamoDB-Konsole und die Anzeige von Tabellen erforderlich sind.

Über die folgende IAM-Richtlinie werden Berechtigungen zum Aktualisieren einer globalen Tabelle auf Version 2019.11.21 (Aktuell) erteilt.

```
{
    "version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "dynamodb:UpdateGlobalTableversion",
            "Resource": "*"
        }
    ]
}
```

Über die folgende IAM-Richtlinie wird die Berechtigung erteilt, nur die globale Tabelle `Music` mit Replikaten in zwei Regionen auf die Version 2019.11.21 (Aktuell) zu aktualisieren.

```
{
    "version": "2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "dynamodb:UpdateGlobalTableversion",
            "Resource": [
                "arn:aws:dynamodb::123456789012:global-table/Music",
                "arn:aws:dynamodb:ap-southeast-1:123456789012:table/Music",
                "arn:aws:dynamodb:us-east-2:123456789012:table/Music"
            ]
        }
    ]
}
```

### Informationen Fakten zum Ablauf der Aktualisierung
<a name="V2GlobalTablesUpgradeExpectations"></a>
+ Während der Aktualisierung wird in allen Replikaten globaler Tabellen die Verarbeitung des Lese- und Schreibdatenverkehr fortgesetzt.
+ Die Aktualisierung dauert je nach Tabellengröße und Anzahl der Replikate zwischen einigen Minuten und mehreren Stunden.
+ Während des Upgrade-Vorgangs ändert sich der Wert von von [TableStatus](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TableDescription.html#DDB-Type-TableDescription-TableStatus)auf. `ACTIVE` `UPDATING` Sie können den Status der Tabelle anzeigen, indem Sie die [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)API aufrufen oder die **Tabellenansicht** in der DynamoDB-Konsole verwenden.
+ Die Einstellungen für die bereitgestellte Kapazität für eine globale Tabelle werden während der Aktualisierung vom Auto-Scaling-Prozess nicht angepasst. Es wird dringend empfohlen, während der Aktualisierung der Tabelle den Modus [On-Demand-Kapazität](capacity-mode.md#capacity-mode-on-demand) zu verwenden.
+ Wenn Sie sich bei der Aktualisierung für den Modus [bereitgestellter Kapazität](provisioned-capacity-mode.md) mit Auto Scaling entscheiden, müssen Sie in Ihren Richtlinien den minimalen Lese- und Schreibdurchsatz erhöhen, um dem erwarteten Anstieg des Datenverkehrs während der Dauer der Aktualisierung Rechnung zu tragen.
+ Es kann vorkommen, dass die Metrik `ReplicationLatency` vorübergehend Latenzspitzen meldet oder dass die Meldung von Metrikdaten während der Aktualisierung ganz ausbleibt. Weitere Informationen finden Sie unter [ReplicationLatency](metrics-dimensions.md#ReplicationLatency). 
+ Sobald der Aktualisierungsvorgang abgeschlossen ist, wird der Status der Tabelle zurück zu `ACTIVE`.

### Verhalten von DynamoDB Streams vor, während und nach der Aktualisierung
<a name="V2GlobalTablesUpgradeDDBStreamsBehavior"></a>

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/V2globaltables_versions.html)

### Aktualisieren auf Version 2019.11.21 (Aktuell)
<a name="V2globaltables_versions.upgrade"></a>

Führen Sie die folgenden Schritte aus, um Ihre Version für globale DynamoDB-Tabellen mithilfe der AWS-Managementkonsole zu aktualisieren.

**So aktualisieren globale Tabellen auf Version 2019.11.21 (Aktuell)**

1. [Öffnen Sie die DynamoDB-Konsole zu Hausehttps://console.aws.amazon.com/dynamodb/.](https://console.aws.amazon.com/dynamodb/home) 

1. Wählen Sie im Navigationsbereich auf der linken Seite der Konsole die Option **Tabellen** und dann die globale Tabelle aus, die Sie auf Version 2019.11.21 (Aktuell) aktualisieren möchten. 

1. Wählen Sie die Registerkarte **Globale Tabellen** aus.

1. Wählen Sie **Update version** (Version aktualisieren) aus.  
![\[Screenshot der Konsole mit der Schaltfläche „Update version“ (Version aktualisieren)\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GlobalTables-upgrade.png)

1. Lesen Sie sich die neuen Anforderungen durch und stimmen Sie ihnen zu, wählen Sie dann **Update version** Version aktualisieren.

1. Nach Abschluss des Aktualisierungsvorgangs wird die in der Konsole angezeigte Version für globale Tabellen in **2019.11.21** geändert.

# Bewährte Methoden für globale Tabellen
<a name="globaltables-bestpractices"></a>

In den folgenden Abschnitten werden bewährte Methoden für die Bereitstellung und Verwendung globaler Tabellen beschrieben.

## Version
<a name="globaltables-bestpractices-version"></a>

Es gibt zwei Versionen von globalen DynamoDB-Tabellen: Version 2019.11.21 (Aktuell) und [Version 2017.11.29 (Legacy)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V1.html). Sie sollten nach Möglichkeit die Version 2019.11.21 (Aktuell) verwenden. 

## Löschschutz
<a name="globaltables-bestpractices-deletionprotection"></a>

Sie sollten den Löschschutz für globale Tabellenreplikate aktivieren, die Sie vor versehentlichem Löschen schützen möchten. Sie müssen den Löschschutz für jedes Replikat aktivieren.

## Benutzen AWS CloudFormation
<a name="globaltables-bestpractices-cloudformation"></a>

CloudFormation unterstützt derzeit nicht die stapelübergreifende Koordination von Ressourcen wie globalen Tabellen. Wenn Sie jedes Replikat einer globalen Tabelle in einem separaten regionalen Stack definieren, treten Fehler auf, die auf festgestellte Abweichungen zwischen den Stacks bei der Durchführung von Replikataktualisierungen zurückzuführen sind. Um dieses Problem zu vermeiden, sollten Sie eine Region als Referenzregion für die Bereitstellung der globalen Tabellen auswählen und alle Replikate der globalen Tabelle im Stack dieser Region definieren.

**Wichtig**  
Sie können eine Ressource des Typs `AWS::DynamoDB::Table` nicht in eine Ressource des Typs `AWS::DynamoDB::GlobalTable` konvertieren, indem Sie den Typ in Ihrer Vorlage ändern. Der Versuch, eine Tabelle mit einer einzigen Region in eine globale Tabelle zu konvertieren, indem ihr CloudFormation Ressourcentyp geändert wird, kann dazu führen, dass Ihre DynamoDB-Tabelle gelöscht wird.

Stattdessen können Sie die `AWS::DynamoDB::GlobalTable`-Ressource verwenden, um eine neue Tabelle in einer einzelnen Region zu erstellen. Diese Tabelle wird wie jede andere Tabelle mit einer einzelnen Region bereitgestellt. Wenn Sie den Stack später aktualisieren, um einer Ressource weitere Regionen hinzuzufügen, werden der Tabelle Replikate hinzugefügt, und sie wird sicher in eine globale Tabelle konvertiert.

Wenn Sie bereits über eine `AWS::DynamoDB::Table`-Ressource verfügen, die Sie in eine `AWS::DynamoDB::GlobalTable`-Ressource konvertieren möchten, werden folgende Schritte zur Konvertierung des Ressourcentyps empfohlen:

1. Legen Sie die Richtlinie zum Löschen von `AWS::DynamoDB::Table` fest, die beibehalten werden soll.

1. Entfernen Sie die Tabelle aus der Stack-Definition.

1. Fügen Sie der Tabelle mit einer Region in der AWS Konsole Replikate hinzu und konvertieren Sie sie in eine globale Tabelle.

1. Importieren Sie die globale Tabelle als neue `AWS::DynamoDB::GlobalTable`-Ressource in den Stack.

## Backups und Wiederherstellung Point-in-Time
<a name="globaltables-bestpractices-backups"></a>

Die Aktivierung von Automated Backups and Point-in-Time Recovery (PITR) für ein Replikat in einer globalen Tabelle kann ausreichen, um Ihre Disaster Recovery-Ziele zu erreichen. Mit -Backup erstellte AWS Replikat-Backups können automatisch regionsübergreifend repliziert werden, um die Ausfallsicherheit zu erhöhen. Berücksichtigen Sie bei der Wahl der Backup- und PITR-Strategie die Ziele des Notfallwiederherstellungsplans vor dem Hintergrund der Hochverfügbarkeit in mehreren Regionen.

## Planen einer hohen Verfügbarkeit in mehreren Regionen
<a name="globaltables-bestpractices-multiregion"></a>

Vorgeschriebene Anleitungen zur Bereitstellung globaler Tabellen finden Sie unter [Best Practices for DynamoDB global table design](bp-global-table-design.md).

# Arbeiten mit Elementen und Attributen in DynamoDB
<a name="WorkingWithItems"></a>

In Amazon DynamoDB ist ein *Element* eine Sammlung von Attributen. Jedes Attribut verfügt über einen Namen und einen Wert. Ein Attributwert kann eine Skalarfunktion, eine Gruppe oder ein Dokumenttyp sein. Weitere Informationen finden Sie unter [Amazon DynamoDB: Funktionsweise](HowItWorks.md).

DynamoDB bietet vier Operationen für grundlegende CRUD-Funktionalität (erstellen/lesen/aktualisieren/löschen). Alle diese Operationen sind atomar.
+ `PutItem` – ein Element erstellen.
+ `GetItem` – ein Element lesen.
+ `UpdateItem` – ein Element aktualisieren.
+ `DeleteItem` – ein Element löschen.

Jede dieser Operationen erfordert, dass Sie den Primärschlüssel des Elements angeben, mit dem Sie arbeiten möchten. Um z. B. ein Element mit `GetItem` zu lesen, müssen Sie den Partitions- und den Sortierschlüssel (sofern zutreffend) für das Element angeben.

Zusätzlich zu den vier grundlegenden CRUD-Operationen bietet DynamoDB außerdem Folgendes:
+ `BatchGetItem` – Liest bis zu 100 Elemente aus einer oder mehreren Tabellen.
+ `BatchWriteItem` – erstellt oder löscht bis zu 25 Elemente in einer oder mehreren Tabellen.

Diese Stapeloperationen kombinieren mehrere CRUD-Operationen in einer einzigen Anforderung. Darüber hinaus können die Stapeloperationen Elemente parallel lesen und schreiben, um Antwortlatenzen zu minimieren.

In diesem Abschnitt wird beschrieben, wie Sie diese Operationen verwenden. Außerdem wird auf verwandte Themen, wie z. B. bedingte Updates und unteilbare Zähler, eingegangen. Dieser Abschnitt enthält auch Beispielcode, der die verwendet AWS SDKs. 

**Topics**
+ [Elementgrößen und -formate in DynamoDB](CapacityUnitCalculations.md)
+ [Lesen eines Elements](#WorkingWithItems.ReadingData)
+ [Schreiben eines Elements](#WorkingWithItems.WritingData)
+ [Rückgabewerte](#WorkingWithItems.ReturnValues)
+ [Batch-Vorgänge](#WorkingWithItems.BatchOperations)
+ [Unteilbare Zähler](#WorkingWithItems.AtomicCounters)
+ [Bedingte Schreibvorgänge](#WorkingWithItems.ConditionalUpdate)
+ [Verwenden von Ausdrücken in DynamoDB](Expressions.md)
+ [Verwenden von Time to Live (TTL) in DynamoDB](TTL.md)
+ [Abfragen von Tabellen in DynamoDB](Query.md)
+ [Scannen von Tabellen in DynamoDB](Scan.md)
+ [PartiQL – Eine SQL-kompatible Abfragesprache für Amazon DynamoDB](ql-reference.md)
+ [Arbeiten mit Elementen: Java](JavaDocumentAPIItemCRUD.md)
+ [Arbeiten mit Elementen: .NET](LowLevelDotNetItemCRUD.md)

# Elementgrößen und -formate in DynamoDB
<a name="CapacityUnitCalculations"></a>

DynamoDB-Tabellen sind schemalos, mit Ausnahme des Primärschlüssels, sodass alle Elemente in einer Tabelle verschiedene Attribute, Größen und Datentypen haben können.

Die Gesamtgröße eines Elements ist die Summe der Längenwerte seiner Attributnamen und Werte, zuzüglich eventuell zutreffender Overhead, wie nachfolgend beschrieben. Sie können die folgenden Richtlinien zum Schätzen von Attributgrößen verwenden:
+ Die Zeichenfolgen sind Unicode mit binärer UTF-8-Kodierung. Die Größe einer Zeichenkette ist *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 (Anzahl der UTF-8-kodierten Byte)*.
+ Zahlen sind variable Länge mit bis zu 38 signifikanten Ziffern. Nullen am Anfang und am Ende werden abgeschnitten. Die Größe einer Zahl ist ca. *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 (1 Byte pro zwei signifikanten Ziffern) \$1 (1 Byte)*.
+ Ein binärer Wert muss im Base64-Format kodiert werden, bevor er an DynamoDB gesendet werden kann, aber die reine Bytelänge des Werts wird für die Größenberechnung verwendet. Die Größe eines binären Attributs ist *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 (Anzahl der reinen Byte).*
+ Die Größe eines Null-Attributs oder eines Booleschen Attributs ist *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 (1 Byte)*.
+ Ein Attribut vom Typ `List` oder `Map` erfordert 3 Byte Overhead, unabhängig von dessen Inhalten. Die Größe einer `List` oder `Map` ist *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 Summe (Größe der verschachtelten Elemente) \$1 (3 Byte)*. Die Größe einer leeren `List` oder `Map` ist *(Anzahl der UTF-8-kodierten Byte des Attributnamens) \$1 (3 Byte)*.
+ Jedes `List`- oder `Map`-Element benötigt außerdem einen Overhead von 1 Byte.

**Anmerkung**  
Wir empfehlen, dass Sie eher kürzere Attributnamen als längere wählen. Dies hilft Ihnen, den benötigten Speicherplatz zu reduzieren, kann aber auch den RCU/WCUs Speicherverbrauch verringern.

Für Speicher-Abrechnungszwecke enthält jedes Element einen Speicherzuschlag pro Element, der von den Funktionen abhängt, die Sie aktiviert haben.
+ Alle Elemente in DynamoDB benötigen 100 Byte Speicheraufwand für die Indizierung.
+ Einige DynamoDB-Funktionen (globale Tabellen, Transaktionen, Änderungsdatenerfassung für Kinesis Data Streams mit DynamoDB) erfordern zusätzlichen Speicheraufwand, um vom System erstellte Attribute zu berücksichtigen, die sich aus der Aktivierung dieser Funktionen ergeben. Globale Tabellen erfordern beispielsweise zusätzliche 48 Byte Speicheraufwand.

## Lesen eines Elements
<a name="WorkingWithItems.ReadingData"></a>

Verwenden Sie zum Lesen eines Elements von einer DynamoDB-Tabelle die Operation `GetItem`. Sie müssen den Namen der Tabelle sowie den Primärschlüssel des gewünschten Elements angeben.

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie ein Element aus der `ProductCatalog` Tabelle gelesen wird.  

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}'
```

**Anmerkung**  
Mit `GetItem` müssen Sie den Primärschlüssel *vollständig* und nicht nur teilweise angeben. Wenn eine Tabelle über einen zusammengesetzten Primärschlüssel (Partitions- und Sortierschlüssel) verfügt, müssen Sie einen Wert für den Partitionsschlüssel und einen Wert für den Sortierschlüssel angeben.

Eine `GetItem`-Anforderung führt standardmäßig einen Eventually Consistent-Lesevorgang durch. Sie können den Parameter `ConsistentRead` verwenden, um stattdessen einen Strongly Consistent-Lesevorgang anzufordern. (Dadurch werden zusätzliche Lesekapazitätseinheiten verbraucht, es wird jedoch die meiste up-to-date Version des Elements zurückgegeben.)

`GetItem` gibt alle Attribute des Elements zurück. Sie können einen *Projektionsausdruck* verwenden, um nur einige der Attribute zurückzugeben. Weitere Informationen finden Sie unter [Verwenden von Projektionsausdrücken in DynamoDB](Expressions.ProjectionExpressions.md).

Um die Anzahl der von `GetItem` verbrauchten Lesekapazitätseinheiten zurückzugeben, legen Sie den Parameter `ReturnConsumedCapacity` auf `TOTAL` fest.

**Example**  
Das folgende Beispiel AWS Command Line Interface (AWS CLI) zeigt einige der optionalen `GetItem` Parameter.  

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --consistent-read \
    --projection-expression "Description, Price, RelatedItems" \
    --return-consumed-capacity TOTAL
```

## Schreiben eines Elements
<a name="WorkingWithItems.WritingData"></a>

Zum Erstellen, Aktualisieren oder Löschen eines Elements in einer DynamoDB-Tabelle verwenden Sie eine der folgenden Operationen:
+ `PutItem`
+ `UpdateItem`
+ `DeleteItem`

Für diese Operationen müssen Sie jeweils den Primärschlüssel vollständig und nicht nur teilweise angeben. Wenn eine Tabelle über einen zusammengesetzten Primärschlüssel (Partitions- und Sortierschlüssel) verfügt, müssen Sie einen Wert für den Partitionsschlüssel und einen Wert für den Sortierschlüssel angeben.

Um die Anzahl der von einer dieser Operationen verbrauchten Schreibkapazitätseinheiten zurückzugeben, legen Sie den Parameter `ReturnConsumedCapacity` auf einen der folgenden Werte fest: 
+ `TOTAL` – Gibt die Gesamtanzahl der verbrauchten Schreibkapazitätseinheiten zurück.
+ `INDEXES` – Gibt die Gesamtzahl der verbrauchten Schreibkapazitätseinheiten mit Zwischensummen für die Tabelle und alle sekundären Indizes zurück, die vom Vorgang betroffen waren.
+ `NONE` – Es werden keine Schreibkapazitätsdetails zurückgegeben. (Dies ist die Standardeinstellung.)

### PutItem
<a name="WorkingWithItems.WritingData.PutItem"></a>

`PutItem` erstellt ein neues Element. Wenn ein Element mit demselben Schlüssel bereits in der Tabelle vorhanden ist, wird es durch das neue Element ersetzt.

**Example**  
Schreiben Sie ein neues Element in die `Thread`-Tabelle. Der Primärschlüssel für die `Thread`-Tabelle besteht aus `ForumName` (Partitionsschlüssel) und `Subject` (Sortierschlüssel).  

```
aws dynamodb put-item \
    --table-name Thread \
    --item file://item.json
```
Die Argumente für `--item` werden in der Datei `item.json` gespeichert.  

```
{
    "ForumName": {"S": "Amazon DynamoDB"},
    "Subject": {"S": "New discussion thread"},
    "Message": {"S": "First post in this thread"},
    "LastPostedBy": {"S": "fred@example.com"},
    "LastPostDateTime": {"S": "201603190422"}
}
```

### UpdateItem
<a name="WorkingWithItems.WritingData.UpdateItem"></a>

Wenn kein Element mit dem angegebenen Schlüssel vorhanden ist, erstellt `UpdateItem` ein neues Element. Andernfalls werden die Attribute eines vorhandenen Elements geändert.

Sie verwenden einen *Aktualisierungsausdruck*, um die zu ändernden Attribute und deren neue Werte anzugeben. Weitere Informationen finden Sie unter [Verwenden von Aktualisierungsausdrücken in DynamoDB](Expressions.UpdateExpressions.md). 

Innerhalb des Aktualisierungsausdrucks verwenden Sie die Ausdrucksattributwerte als Platzhalter für die tatsächlichen Werte. Weitere Informationen finden Sie unter [Verwenden von Ausdrucksattributwerten in DynamoDB](Expressions.ExpressionAttributeValues.md).

**Example**  
Ändern Sie verschiedene Attribute im Element `Thread`. Der optionale Parameter `ReturnValues` zeigt das Element so an, wie es nach der Aktualisierung dargestellt wird. Weitere Informationen finden Sie unter [Rückgabewerte](#WorkingWithItems.ReturnValues).  

```
aws dynamodb update-item \
    --table-name Thread \
    --key file://key.json \
    --update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy = :lastpostedby" \
    --expression-attribute-values file://expression-attribute-values.json \
    --return-values ALL_NEW
```

Die Argumente für `--key` werden in der Datei `key.json` gespeichert.

```
{
    "ForumName": {"S": "Amazon DynamoDB"},
    "Subject": {"S": "New discussion thread"}
}
```

Die Argumente für `--expression-attribute-values` werden in der Datei `expression-attribute-values.json` gespeichert.

```
{
    ":zero": {"N":"0"},
    ":lastpostedby": {"S":"barney@example.com"}
}
```

### DeleteItem
<a name="WorkingWithItems.WritingData.DeleteItem"></a>

`DeleteItem` löscht das Element mit dem angegebenen Schlüssel.

**Example**  
Das folgende AWS CLI Beispiel zeigt, wie das `Thread` Element gelöscht wird.  

```
aws dynamodb delete-item \
    --table-name Thread \
    --key file://key.json
```

## Rückgabewerte
<a name="WorkingWithItems.ReturnValues"></a>

In einigen Fällen soll DynamoDB bestimmte Attributwerte so zurückgeben, wie sie vor oder nach der Änderung erschienen. Die Operationen `PutItem`, `UpdateItem` und `DeleteItem` verfügen über einen Parameter `ReturnValues`, mit dem Sie Attributwerte zurückgeben können, bevor oder nachdem diese geändert wurden.

Der Standardwert für `ReturnValues` ist `NONE`. Dies bedeutet, dass DynamoDB keine Informationen über Attribute zurückgibt, die geändert wurden. 

Nachfolgend sind die anderen gültigen Einstellungen für `ReturnValues` nach DynamoDB-API-Operation sortiert aufgeführt.

### PutItem
<a name="WorkingWithItems.ReturnValues.PutItem"></a>
+ `ReturnValues`: `ALL_OLD`
  + Wenn Sie ein vorhandenes Element überschreiben, gibt `ALL_OLD` das gesamte Element so zurück, wie es vor dem Überschreiben dargestellt wurde.
  + Wenn Sie ein nicht vorhandenes Element schreiben, hat `ALL_OLD` keine Auswirkung.

### UpdateItem
<a name="WorkingWithItems.ReturnValues.UpdateItem"></a>

Die häufigste Nutzung für `UpdateItem` ist das Aktualisieren eines vorhandenen Elements. `UpdateItem` führt eigentlich eine *upsert*-Operation aus. Dies bedeutet, dass das Element automatisch erstellt wird, wenn es noch nicht vorhanden ist.
+ `ReturnValues`: `ALL_OLD`
  + Wenn Sie ein vorhandenes Element aktualisieren, gibt `ALL_OLD` das gesamte Element so zurück, wie es vor dem Aktualisieren dargestellt wurde.
  + Wenn Sie ein nicht vorhandenes Element aktualisieren (Upsert-Operation), hat `ALL_OLD` keine Auswirkung.
+ `ReturnValues`: `ALL_NEW`
  + Wenn Sie ein vorhandenes Element aktualisieren, gibt `ALL_NEW` das gesamte Element so zurück, wie es nach dem Aktualisieren dargestellt wird.
  + Wenn Sie ein nicht vorhandenes Element aktualisieren (Upsert-Operation), gibt `ALL_NEW` das gesamte Element zurück.
+ `ReturnValues`: `UPDATED_OLD`
  + Wenn Sie ein vorhandenes Element aktualisieren, gibt `UPDATED_OLD` nur die aktualisierten Attribute so zurück, wie sie vor dem Aktualisieren dargestellt wurden.
  + Wenn Sie ein nicht vorhandenes Element aktualisieren (Upsert-Operation), hat `UPDATED_OLD` keine Auswirkung.
+ `ReturnValues`: `UPDATED_NEW`
  + Wenn Sie ein vorhandenes Element aktualisieren, gibt `UPDATED_NEW` nur die betroffenen Attribute so zurück, wie sie nach dem Aktualisieren dargestellt werden.
  + Wenn Sie ein nicht vorhandenes Element aktualisieren (Upsert-Operation), gibt `UPDATED_NEW` nur die aktualisierten Attribute so zurück, wie sie nach dem Aktualisieren dargestellt werden.

### DeleteItem
<a name="WorkingWithItems.ReturnValues.DeleteItem"></a>
+ `ReturnValues`: `ALL_OLD`
  + Wenn Sie ein vorhandenes Element löschen, gibt `ALL_OLD` das gesamte Element so zurück, wie es vor dem Löschen dargestellt wurde.
  + Wenn Sie ein nicht vorhandenes Element löschen, gibt `ALL_OLD` keine Daten zurück.

## Batch-Vorgänge
<a name="WorkingWithItems.BatchOperations"></a>

Für Anwendungen, die mehrere Elemente lesen oder schreiben müssen, stellt DynamoDB die Operationen `BatchGetItem` und `BatchWriteItem` bereit. Mithilfe dieser Operationen können Sie die Anzahl der Netzläufe von Ihrer Anwendung für DynamoDB reduzieren. Außerdem führt DynamoDB die einzelnen Lese- oder Schreibvorgänge parallel aus. Ihre Anwendungen profitieren von dieser Parallelität, ohne Gleichzeitigkeit oder Threads verwalten zu müssen.

Die Stapeloperationen sind im Wesentlichen Wrapper für mehrere Lese- oder Schreibanforderungen. Wenn eine `BatchGetItem`-Anforderung z. B. fünf Elemente enthält, führt DynamoDB fünf `GetItem`-Operationen in Ihrem Namen aus. Wenn eine `BatchWriteItem`-Anforderung zwei PUT-Anforderungen und vier DELETE-Anforderungen enthält, führt DynamoDB zwei `PutItem`- und vier `DeleteItem`-Anforderungen aus.

Im Allgemeinen treten bei einer Stapeloperation nur Fehler auf, wenn *alle* im Stapel enthaltenen Anforderungen fehlschlagen. Angenommen, Sie führen eine `BatchGetItem`-Operation aus, doch bei einer der `GetItem`-Einzelanforderungen des Stapels tritt ein Fehler auf. In diesem Fall gibt `BatchGetItem` die Schlüssel und Daten der fehlgeschlagenen `GetItem`-Anforderung zurück. Die anderen `GetItem`-Anforderungen des Stapels sind davon nicht betroffen.

### BatchGetItem
<a name="WorkingWithItems.BatchOperations.BatchGetItem"></a>

Eine einzelne `BatchGetItem`-Operation kann bis zu 10 individuelle `GetItem`-Anforderungen enthalten und bis zu 16 MB Daten abrufen. Darüber hinaus kann eine `BatchGetItem`-Operation Elemente aus mehreren Tabellen abrufen.

**Example**  
Rufen Sie zwei Elemente aus der `Thread`-Tabelle mit einem Projektionsausdruck ab, um nur einige der Attribute zurückzugeben.  

```
aws dynamodb batch-get-item \
    --request-items file://request-items.json
```
Die Argumente für `--request-items` werden in der Datei `request-items.json` gespeichert.  

```
{
    "Thread": {
        "Keys": [
            {
                "ForumName":{"S": "Amazon DynamoDB"},
                "Subject":{"S": "DynamoDB Thread 1"}
            },
            {
                "ForumName":{"S": "Amazon S3"},
                "Subject":{"S": "S3 Thread 1"}
            }
        ],
        "ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies"
    }
}
```

### BatchWriteItem
<a name="WorkingWithItems.BatchOperations.BatchWriteItem"></a>

Die `BatchWriteItem`-Operation kann bis zu 25 individuelle `PutItem` und `DeleteItem`-Anforderungen enthalten und bis zu 16 MB Daten schreiben. (Die maximale Größe eines einzelnen Elements beträgt 400 KB.) Darüber hinaus kann eine `BatchWriteItem`-Operation Elemente in mehreren Tabellen einfügen oder daraus löschen. 

**Anmerkung**  
`BatchWriteItem` unterstützt keine `UpdateItem`-Anforderungen.

**Example**  
Fügen Sie der `ProductCatalog`-Tabelle zwei Elemente hinzu.  

```
aws dynamodb batch-write-item \
    --request-items file://request-items.json
```
Die Argumente für `--request-items` werden in der Datei `request-items.json` gespeichert.  

```
{
    "ProductCatalog": [
        {
            "PutRequest": {
                "Item": {
                    "Id": { "N": "601" },
                    "Description": { "S": "Snowboard" },
                    "QuantityOnHand": { "N": "5" },
                    "Price": { "N": "100" }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "Id": { "N": "602" },
                    "Description": { "S": "Snow shovel" }
                }
            }
        }
    ]
}
```

## Unteilbare Zähler
<a name="WorkingWithItems.AtomicCounters"></a>

Mit der `UpdateItem`-Operation können Sie einen *unteilbaren Zähler* implementieren. Hierbei handelt es sich um ein numerisches Attribut, das erhöht wird, und zwar ohne Bedingung und ohne Konflikte mit anderen Schreibanforderungen. (Alle Schreibanforderungen werden in der Reihenfolge angewendet, in der sie empfangen wurden.) Mit einem unteilbaren Zähler sind die Updates nicht idempotent. Mit anderen Worten, der numerische Wert wird bei jedem Aufruf von `UpdateItem` erhöht oder verringert. Wenn der zur Aktualisierung des unteilbaren Zählers verwendete Inkrementwert positiv ist, kann dies zu einer Überzählung führen. Wenn der Inkrementwert negativ ist, kann dies zu einer Unterzählung führen.

Sie können einen unteilbaren Zähler verwenden, um die Anzahl der Besucher einer Website zu verfolgen. In diesem Fall erhöht Ihre Anwendung einen numerischen Wert, unabhängig vom aktuellen Wert. Wenn bei einer `UpdateItem`-Operation ein Fehler auftritt, kann die Anwendung die Operation einfach wiederholen. Das bringt zwar das Risiko mit sich, den Zähler zweimal zu aktualisieren, doch eine leichte Unter- oder Überzählung der Websitebesucher ist tolerierbar.

Ein unteilbarer Zähler ist nicht geeignet, wenn eine Überzählung oder Unterzählung nicht toleriert werden kann (z. B. in einer Bankanwendung). In diesem Fall ist es sicherer, ein bedingtes Update anstelle eines unteilbaren Zählers zu verwenden.

Weitere Informationen finden Sie unter [Vergrößern und Verkleinern numerischer Attribute](Expressions.UpdateExpressions.md#Expressions.UpdateExpressions.SET.IncrementAndDecrement).

**Example**  
Im folgenden AWS CLI Beispiel wird der Wert `Price` eines Produkts um 5 erhöht. In diesem Beispiel war bekannt, dass das Element existiert, bevor der Zähler aktualisiert wurde. Da `UpdateItem` nicht idempotent ist, steigt `Price` bei jedem Ausführen dieses Codes an.   

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id": { "N": "601" }}' \
    --update-expression "SET Price = Price + :incr" \
    --expression-attribute-values '{":incr":{"N":"5"}}' \
    --return-values UPDATED_NEW
```

## Bedingte Schreibvorgänge
<a name="WorkingWithItems.ConditionalUpdate"></a>

Standardmäßig sind die DynamoDB-Schreiboperationen (`PutItem`,`DeleteItem`) *bedingungslos*: Jede Operation überschreibt ein vorhandenes Element, das den angegebenen Primärschlüssel hat.

DynamoDB unterstützt optional bedingte Schreibvorgänge für diese Operationen. Ein bedingter Schreibvorgang wird nur dann erfolgreich ausgeführt, wenn die Elementattribute eine oder mehrere erwartete Bedingungen erfüllen. Andernfalls wird ein Fehler zurückgegeben.

Bedingte Schreibvorgänge vergleichen ihre Bedingungen mit der zuletzt aktualisierten Version des Elements. Beachten Sie, dass der bedingte Schreibvorgang kein vorheriges Element findet, wenn das Element zuvor noch nicht vorhanden war oder wenn der letzte erfolgreiche Vorgang für dieses Element ein Löschvorgang war.

 Bedingte Schreibvorgänge sind in vielen Situationen hilfreich. Eine `PutItem`-Operation soll beispielsweise nur erfolgreich abgeschlossen werden, wenn noch kein Element mit demselben Primärschlüssel vorhanden ist. Sie können eine `UpdateItem`-Operation auch daran hindern, ein Element zu ändern, wenn eines seiner Attribute einen bestimmten Wert aufweist.

Bedingte Schreibvorgänge sind hilfreich, wenn mehrere Benutzer versuchen, dasselbe Element zu ändern. Betrachten Sie das folgende Diagramm, in dem zwei Benutzer (Alice und Bob) mit demselben Element aus einer DynamoDB-Tabelle arbeiten:

![\[Die Benutzer Alice und Bob versuchen, ein Element mit der ID 1 zu ändern, was zeigt, dass bedingte Schreibvorgänge erforderlich sind.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/update-no-condition.png)


Angenommen, Alice verwendet das, AWS CLI um das Attribut auf 8 zu aktualisieren. `Price`

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --update-expression "SET Price = :newval" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` werden in der Datei `expression-attribute-values.json` gespeichert:

```
{
    ":newval":{"N":"8"}
}
```

Angenommen, Bob erstellt später eine ähnliche `UpdateItem`-Anforderung, ändert den `Price` jedoch in 12. Für Bob sieht der Parameter `--expression-attribute-values` wie folgt aus:

```
{
    ":newval":{"N":"12"}
}
```

Bobs Anforderung wird erfolgreich ausgeführt, aber das Update, das Alice vorher vorgenommen hatte, geht verloren.

Für eine bedingte `PutItem`-, `DeleteItem`- oder `UpdateItem`-Anforderung geben Sie einen Bedingungsausdruck an. Ein *Bedingungsausdruck* ist eine Zeichenfolge, die Attributnamen, bedingte Operatoren und integrierte Funktionen enthält. Der gesamte Ausdruck muss mit True ausgewertet werden. Andernfalls schlägt sie fehl.

Betrachten Sie jetzt das folgende Diagramm, das zeigt, wie bedingte Schreibvorgänge verhindern würden, dass die von Alice vorgenommene Aktualisierung überschrieben wird:

![\[Durch bedingtes Schreiben wird verhindert, dass die Aktualisierung von Benutzer Bob die Änderung von Benutzerin Alice am selben Element überschreibt.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/update-yes-condition.png)


Alice versucht zunächst, `Price` auf 8 zu aktualisieren, jedoch nur wenn der aktuelle `Price` 10 beträgt.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --update-expression "SET Price = :newval" \
    --condition-expression "Price = :currval" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` werden in der Datei `expression-attribute-values.json` gespeichert.

```
{
    ":newval":{"N":"8"},
    ":currval":{"N":"10"}
}
```

Das Update von Alice wird erfolgreich ausgeführt, da die Bedingung mit True ausgewertet wird.

Als Nächstes versucht Bob, den `Price` auf 12 zu aktualisieren, jedoch nur wenn der aktuelle `Price` 10 beträgt. Für Bob sieht der Parameter `--expression-attribute-values` wie folgt aus:

```
{
    ":newval":{"N":"12"},
    ":currval":{"N":"10"}
}
```

Da Alice den `Price` zuvor in 8 geändert hat, wird der Bedingungsausdruck mit False ausgewertet und Bobs Aktualisierung schlägt fehl.

Weitere Informationen finden Sie unter [CLI-Beispiel für DynamoDB-Bedingungsausdrücke](Expressions.ConditionExpressions.md).

### Idempotenz von bedingten Schreibvorgängen
<a name="WorkingWithItems.ConditionalWrites.Idempotence"></a>

Bedingte Schreibvorgänge können *idempotent* sein, wenn die bedingte Prüfung für dasselbe Attribut ausgeführt wird, das aktualisiert wird. Das bedeutet, dass DynamoDB den jeweiligen Schreibvorgang nur ausführt, wenn bestimmte Attributwerte in dem Element mit den zum Zeitpunkt der Anforderung erwarteten Werten übereinstimmen. 

Angenommen, Sie erstellen eine `UpdateItem`-Anforderung, um den `Price` eines Elements um 3 zu erhöhen, jedoch nur wenn der `Price` aktuell 20 beträgt. Nachdem Sie die Anforderung senden und bevor Sie die Ergebnisse erhalten, tritt ein Netzwerkfehler auf und Sie wissen nicht, ob die Anforderung erfolgreich war. Da dieser bedingte Schreibvorgang idempotent ist, können Sie dieselbe `UpdateItem`-Anforderung wiederholen und DynamoDB aktualisiert das Element nur, wenn `Price` gegenwärtig 20 beträgt.

### Von bedingten Schreibvorgängen verbrauchte Kapazitätseinheiten
<a name="WorkingWithItems.ConditionalWrites.ReturnConsumedCapacity"></a>

Wenn `ConditionExpression` während eines bedingten Schreibvorgangs als falsch ausgewertet wird, verbraucht DynamoDB weiterhin Schreibkapazität aus der Tabelle. Die verbrauchte Menge hängt von der Größe des vorhandenen Elements ab (oder beträgt mindestens 1). Wenn beispielsweise ein vorhandenes Element 300 KB groß ist und das neue Element, das Sie erstellen oder aktualisieren möchten, 310 KB hat, entsprechen die verbrauchten Schreibkapazitätseinheiten 300, wenn die Bedingung fehlschlägt, und 310, wenn die Bedingung erfolgreich ist. Wenn es sich um ein neues Element handelt (kein vorhandenes Element), beträgt die verbrauchte Schreibkapazität 1, wenn die Bedingung fehlschlägt, und 310, wenn die Bedingung erfolgreich ist.

**Anmerkung**  
Schreibvorgänge verbrauchen nur *Schreib*kapazitätseinheiten. Sie belegen keine *Lese*kapazitätseinheiten.

Tritt bei einem bedingten Schreibvorgang ein Fehler auf, wird eine `ConditionalCheckFailedException` zurückgegeben. In diesem Fall erhalten Sie in der Antwort keine Informationen über die verbrauchte Schreibkapazität.

Um die Anzahl von Schreibkapazitätseinheiten zurückzugeben, die während eines bedingten Schreibvorgangs verbraucht wurden, verwenden Sie den Parameter `ReturnConsumedCapacity`:
+ `TOTAL` – Gibt die Gesamtanzahl der verbrauchten Schreibkapazitätseinheiten zurück.
+ `INDEXES` – Gibt die Gesamtzahl der verbrauchten Schreibkapazitätseinheiten mit Zwischensummen für die Tabelle und alle sekundären Indizes zurück, die vom Vorgang betroffen waren.
+ `NONE` – Es werden keine Schreibkapazitätsdetails zurückgegeben. (Dies ist die Standardeinstellung.)

  

**Anmerkung**  
Im Unterschied zu einem globalen sekundären Index teilt ein lokaler sekundärer Index seine bereitgestellte Durchsatzkapazität mit der Tabelle. Die Lese- und Schreibaktivität auf einem lokalen sekundären Index verbraucht die bereitgestellte Durchsatzkapazität aus der Tabelle.

# Verwenden von Ausdrücken in DynamoDB
<a name="Expressions"></a>

In Amazon DynamoDB können Sie mithilfe von *Ausdrücken* angeben, welche Attribute aus einem Element gelesen werden sollen, Daten schreiben, wenn eine Bedingung erfüllt ist, angeben, wie ein Element aktualisiert werden soll, Abfragen definieren und die Ergebnisse einer Abfrage filtern.

In dieser Tabelle werden die grundlegende Ausdrucksgrammatik und die verfügbaren Ausdrucksarten beschrieben.


| Ausdruckstyp | Description | 
| --- | --- | 
| Projektionsausdruck | Ein Projektionsausdruck identifiziert die Attribute, die Sie aus einem Element abrufen möchten GetItem, wenn Sie Operationen wie Abfragen oder Scannen verwenden. | 
| Bedingungsausdruck | Ein Bedingungsausdruck bestimmt, welche Elemente geändert werden sollen, wenn Sie die DeleteItem Operationen PutItem UpdateItem, und verwenden. | 
| Aktualisierungsausdruck | Ein Aktualisierungsausdruck gibt an, wie die Attribute eines Elements geändert UpdateItem werden, z. B. durch das Festlegen eines Skalarwerts oder das Entfernen von Elementen aus einer Liste oder einer Map. | 
| Schlüsselbedingungsausdruck | Ein Schlüsselbedingungsausdruck bestimmt, welche Elemente eine Abfrage aus einer Tabelle oder einem Index liest. | 
| Filterausdruck | Ein Filterausdruck bestimmt, welche Elemente in den Abfrageergebnissen zurückgegeben werden. Alle anderen Ergebnisse werden verworfen. | 

Weitere Informationen zur Ausdruckssyntax und Details zu jedem Ausdruckstyp finden Sie in folgenden Abschnitten.

**Topics**
+ [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](Expressions.Attributes.md)
+ [Ausdrucksattributnamen (Aliasse) in DynamoDB](Expressions.ExpressionAttributeNames.md)
+ [Verwenden von Ausdrucksattributwerten in DynamoDB](Expressions.ExpressionAttributeValues.md)
+ [Verwenden von Projektionsausdrücken in DynamoDB](Expressions.ProjectionExpressions.md)
+ [Verwenden von Aktualisierungsausdrücken in DynamoDB](Expressions.UpdateExpressions.md)
+ [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md)
+ [CLI-Beispiel für DynamoDB-Bedingungsausdrücke](Expressions.ConditionExpressions.md)

**Anmerkung**  
Für die Abwärtskompatibilität unterstützt DynamoDB ebenfalls bedingte Parameter, die keine Ausdrücke verwenden. Weitere Informationen finden Sie unter [Bedingte Legacy-Parameter für DynamoDB](LegacyConditionalParameters.md).  
Neue Anwendungen sollten Ausdrücke anstelle der Legacy-Parameter verwenden.

# Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB
<a name="Expressions.Attributes"></a>

Dieser Abschnitt beschreibt, wie Sie sich auf die Elementattribute in einem Ausdruck in Amazon DynamoDB beziehen können. Sie können mit jedem beliebigen Attribut arbeiten, auch wenn es tief innerhalb mehrerer Listen und Zuordnungen verschachtelt ist.

**Topics**
+ [Attribute der obersten Stufe](#Expressions.Attributes.TopLevelAttributes)
+ [Verschachtelte Attribute](#Expressions.Attributes.NestedAttributes)
+ [Dokumentpfade](#Expressions.Attributes.NestedElements.DocumentPathExamples)

**Ein Beispielelement: ProductCatalog**  
Bei den Beispielen auf dieser Seite wurde folgendes Musterelement in der `ProductCatalog`-Tabelle verwendet. (Diese Tabelle wird in [Beispieltabellen und -daten zur Verwendung in DynamoDB](AppendixSampleTables.md) beschrieben.)

```
{
    "Id": 123,
    "Title": "Bicycle 123",
    "Description": "123 description",
    "BicycleType": "Hybrid",
    "Brand": "Brand-Company C",
    "Price": 500,
    "Color": ["Red", "Black"],
    "ProductCategory": "Bicycle",
    "InStock": true,
    "QuantityOnHand": null,
    "RelatedItems": [
        341,
        472,
        649
    ],
    "Pictures": {
        "FrontView": "http://example.com/products/123_front.jpg",
        "RearView": "http://example.com/products/123_rear.jpg",
        "SideView": "http://example.com/products/123_left_side.jpg"
    },
    "ProductReviews": {
	    "FiveStar": [
	    		"Excellent! Can't recommend it highly enough! Buy it!",
	    		"Do yourself a favor and buy this."
	    ],
	    "OneStar": [
	    		"Terrible product! Do not buy this."
	    ]
    },
    "Comment": "This product sells out quickly during the summer",
    "Safety.Warning": "Always wear a helmet"
 }
```

Beachten Sie Folgendes:
+ Der Partitions-Schlüsselwert (`Id`) ist `123`. Es gibt keinen Sortierschlüssel.
+ Die meisten Attribute verfügen über skalare Datentypen, z. B. `String`, `Number`, `Boolean` und `Null`.
+ Ein Attribut (`Color`) ist ein `String Set`.
+ Die folgenden Attribute sind Dokumentdatentypen:
  + Eine Liste von `RelatedItems`. Jedes Element ist eine `Id` für ein zugehöriges Produkt.
  + Eine Zuordnung von `Pictures`. Jedes Element ist eine kurze Beschreibung eines Bildes, zusammen mit einem URL für die entsprechende Imagedatei.
  + Eine Zuordnung von `ProductReviews`. Jedes Element repräsentiert eine Bewertung und eine Liste von Rezensionen dieser Bewertung. Zunächst wird diese Zuordnung mit 5-Sterne- und 1-Stern-Rezensionen gefüllt.

## Attribute der obersten Stufe
<a name="Expressions.Attributes.TopLevelAttributes"></a>

Ein Attribut befindet sich auf *oberster Ebene*, wenn es nicht in einem anderen Attribut eingebettet ist. Für das `ProductCatalog`-Element lauten die Attribute auf oberster Ebene wie folgt:
+ `Id`
+ `Title`
+ `Description`
+ `BicycleType`
+ `Brand`
+ `Price`
+ `Color`
+ `ProductCategory`
+ `InStock`
+ `QuantityOnHand`
+ `RelatedItems`
+ `Pictures`
+ `ProductReviews`
+ `Comment`
+ `Safety.Warning`

Alle diese Attribute auf oberster Ebene sind Skalare, mit Ausnahme von `Color` (Liste), `RelatedItems` (Liste), `Pictures` (Zuordnung) und `ProductReviews` (Zuordnung).

## Verschachtelte Attribute
<a name="Expressions.Attributes.NestedAttributes"></a>

Ein Attribut gilt als *verschachtelt*, wenn es in einem anderen Attribut eingebettet ist. Um auf das verschachtelte Attribut zuzugreifen, verwenden Sie die *Dereferenzierungsoperatoren*:
+ `[n]` – für Listenelemente
+ `.` (Punkt) – für Zuordnungselemente

### Zugriff auf Listenelemente
<a name="Expressions.Attributes.NestedElements.AccessingListElements"></a>

Der Dereferenzierungsoperator für das Listenelement ist **[*N*]**, wobei *n* die Elementnummer ist. Listenelemente sind nullbasiert, sodass [0] das erste Element in der Liste darstellt, [1] das zweite und so weiter. Hier sind einige Beispiele:
+ `MyList[0]`
+ `AnotherList[12]`
+ `ThisList[5][11]`

Das Element `ThisList[5]` ist selbst eine verschachtelte Liste. Daher bezieht sich `ThisList[5][11]` auf das zwölfte Element in dieser Liste.

Die Zahl innerhalb der eckigen Klammern muss eine nicht negative ganze Zahl sein. Daher sind die folgenden Ausdrücke ungültig:
+ `MyList[-1]`
+ `MyList[0.4]`

### Zugriff auf Zuweisungselemente
<a name="Expressions.Attributes.NestedElements.AccessingMapElements"></a>

Der Dereferenzierungsoperator für ein Zuordnungselement ist **.** (Punkt). Verwenden Sie einen Punkt als Trennzeichen zwischen den Elementen in einer Zuordnung:
+ `MyMap.nestedField`
+ `MyMap.nestedField.deeplyNestedField`

## Dokumentpfade
<a name="Expressions.Attributes.NestedElements.DocumentPathExamples"></a>

In einem Ausdruck verwenden Sie einen *Dokumentpfad*, um DynamoDB mitzuteilen, wo ein Attribut zu finden ist. Für eine Attribut auf oberster Ebene ist der Dokumentpfad einfach der Attributname. Sie erstellen den Dokumentpfad für ein verschachteltes Attribut mithilfe des Dereferenzoperators.

Es folgen einige Beispiele für Dokumentpfade. (Beziehen Sie sich auf das Element, das in [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](#Expressions.Attributes) gezeigt wird.)
+ Ein skalares Attribut auf oberster Ebene.

   `Description`
+ Ein Listenattribut auf oberster Ebene. (Dies gibt die gesamte Liste zurück und nicht nur einige der Elemente.)

  `RelatedItems`
+ Das dritte Element aus der `RelatedItems`-Liste. (Denken Sie daran, dass Listenelemente nullbasiert sind.)

  `RelatedItems[2]`
+ Das Bild des Produkts in der Vorderansicht

  `Pictures.FrontView`
+ Alle 5-Sterne-Rezensionen

  `ProductReviews.FiveStar`
+ Die erste 5-Sterne-Rezension

  `ProductReviews.FiveStar[0]`

**Anmerkung**  
Die maximale Tiefe eines Dokumentpfads ist 32. Aus diesem Grund kann die Anzahl der Dereferenzoperatoren in einem Pfad diesen Grenzwert nicht überschreiten.

Sie können jeden Attributnamen in einem Dokumentpfad verwenden, sofern er die folgenden Anforderungen erfüllt:
+ Das erste Zeichen ist `a-z` oder `A-Z` und/oder `0-9`.
+ Das zweite Zeichen (falls vorhanden) ist `a-z`, `A-Z`.

**Anmerkung**  
Wenn ein Attributname diesen Anforderungen nicht entspricht, müssen Sie einen Ausdrucksattributnamen als Platzhalter definieren.

Weitere Informationen finden Sie unter [Ausdrucksattributnamen (Aliasse) in DynamoDB](Expressions.ExpressionAttributeNames.md).

# Ausdrucksattributnamen (Aliasse) in DynamoDB
<a name="Expressions.ExpressionAttributeNames"></a>

Ein *Ausdrucksattributname* ist ein Alias (oder Platzhalter), den Sie in einem Amazon-DynamoDB-Ausdruck als Alternative zu einem tatsächlichen Attributnamen verwenden. Ein Ausdrucksattributname muss mit einem Rautezeichen (`#`) beginnen, gefolgt von einem oder mehreren alphanumerischen Zeichen. Der Unterstrich (`_`) ist ebenfalls zulässig.

Dieser Abschnitt beschreibt einige Situationen, in denen Sie Ausdrucksattributnamen verwenden müssen.

**Anmerkung**  
Die Beispiele in diesem Abschnitt verwenden das AWS Command Line Interface (AWS CLI). 

**Topics**
+ [Reservierte Wörter](#Expressions.ExpressionAttributeNames.ReservedWords)
+ [Attributnamen mit Sonderzeichen](#Expressions.ExpressionAttributeNames.AttributeNamesContainingSpecialCharacters)
+ [Verschachtelte Attribute](#Expressions.ExpressionAttributeNames.NestedAttributes)
+ [Wiederholtes Verweisen auf Attributnamen](#Expressions.ExpressionAttributeNames.RepeatingAttributeNames)

## Reservierte Wörter
<a name="Expressions.ExpressionAttributeNames.ReservedWords"></a>

In einigen Fällen kann es erforderlich sein, einen Ausdruck mit einem Attributnamen zu erstellen, der mit einem für DynamoDB reservierten Wort in Konflikt steht. (Eine vollständige Liste der reservierten Wörter finden Sie unter [Reservierte Wörter in DynamoDB](ReservedWords.md).)

Das folgende Beispiel würde AWS CLI beispielsweise fehlschlagen, da es sich um ein reserviertes Wort `COMMENT` handelt.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "Comment"
```

Um dieses Problem zu vermeiden, können Sie `Comment` durch einen Ausdrucksattributnamen wie `#c` ersetzen. Das Rautezeichen `#` ist erforderlich und gibt an, dass es sich um einen Platzhalter für einen Attributnamen handelt. Das AWS CLI Beispiel würde jetzt wie folgt aussehen.

```
aws dynamodb get-item \
     --table-name ProductCatalog \
     --key '{"Id":{"N":"123"}}' \
     --projection-expression "#c" \
     --expression-attribute-names '{"#c":"Comment"}'
```

**Anmerkung**  
Wenn ein Attributname mit einer Zahl beginnt, ein Leerzeichen oder ein reserviertes Wort enthält, *müssen* Sie einen Ausdrucksattributnamen verwenden, um den Namen des Attributs im Ausdruck zu ersetzen.

## Attributnamen mit Sonderzeichen
<a name="Expressions.ExpressionAttributeNames.AttributeNamesContainingSpecialCharacters"></a>

In einem Ausdruck wird ein Punkt (".") als Trennzeichen in einem Dokumentpfad interpretiert. DynamoDB bietet allerdings die Möglichkeit, ein Punktzeichen und andere Sonderzeichen wie einen Bindestrich („-“) in einem Attributnamen zu verwenden. Dies kann in einigen Fällen zweideutig sein. Angenommen, Sie möchten das Attribut `Safety.Warning` aus einem `ProductCatalog`-Element abrufen (siehe [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](Expressions.Attributes.md)).

In diesem Beispiel gehen wir davon aus, dass Sie auf `Safety.Warning` mit einem Projektionsausdruck zugreifen möchten.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "Safety.Warning"
```

DynamoDB gibt statt der erwarteten Zeichenfolge („`Always wear a helmet`“) ein leeres Ergebnis zurück. Der Grund dafür ist, dass DynamoDB einen Punkt in einem Ausdruck als Dokumentpfadtrennzeichen interpretiert. In diesem Fall müssen Sie einen Ausdrucksattributnamen (z. B. `#sw`) als Ersatz für `Safety.Warning` definieren. Anschließend können Sie den folgenden Projektionsausdruck verwenden.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#sw" \
    --expression-attribute-names '{"#sw":"Safety.Warning"}'
```

DynamoDB gibt dann das richtige Ergebnis zurück.

**Anmerkung**  
Wenn ein Attributname einen Punkt („.“) oder einen Bindestrich („-“) enthält, *müssen* Sie einen Ausdrucksattributnamen verwenden, um den Namen dieses Attributs im Ausdruck zu ersetzen.

## Verschachtelte Attribute
<a name="Expressions.ExpressionAttributeNames.NestedAttributes"></a>

Angenommen, Sie möchten auf das verschachtelte Attribut `ProductReviews.OneStar` zugreifen. In einem Ausdrucksattributnamen behandelt DynamoDB den Punkt („.“) als Zeichen in einem Attributnamen. Um auf das verschachtelte Attribut zu verweisen, definieren Sie einen Ausdrucksattributnamen für jedes Element im Dokumentpfad:
+ `#pr — ProductReviews`
+ `#1star — OneStar`

Anschließend können Sie `#pr.#1star` für den folgenden Projektionsausdruck verwenden.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#pr.#1star"  \
    --expression-attribute-names '{"#pr":"ProductReviews", "#1star":"OneStar"}'
```

DynamoDB gibt dann das richtige Ergebnis zurück.

## Wiederholtes Verweisen auf Attributnamen
<a name="Expressions.ExpressionAttributeNames.RepeatingAttributeNames"></a>

Ausdrucksattributnamen sind hilfreich, wenn Sie sich wiederholt auf den gleichen Attributnamen beziehen müssen. Betrachten Sie z. B. den folgenden Ausdruck zum Abrufen einiger Rezensionen aus einem `ProductCatalog`-Element.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "ProductReviews.FiveStar, ProductReviews.ThreeStar, ProductReviews.OneStar"
```

Um den Ausdruck prägnanter zu gestalten, können Sie `ProductReviews` durch einen Ausdrucksattributnamen wie `#pr` ersetzen. Der geänderte Ausdruck sieht wie folgt aus:
+  `#pr.FiveStar, #pr.ThreeStar, #pr.OneStar` 

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#pr.FiveStar, #pr.ThreeStar, #pr.OneStar" \
    --expression-attribute-names '{"#pr":"ProductReviews"}'
```

Wenn Sie einen Ausdrucksattributnamen definieren, müssen Sie ihn im gesamten Ausdruck einheitlich verwenden. Sie dürfen außerdem nicht das Symbol `#` weglassen. 

# Verwenden von Ausdrucksattributwerten in DynamoDB
<a name="Expressions.ExpressionAttributeValues"></a>

*Ausdrucksattributwerte* in Amazon DynamoDB agieren als Variablen. Sie ersetzen die tatsächlichen Werte, die Sie vergleichen möchten – Werte, die Sie möglicherweise bis zur Laufzeit nicht kennen. Ein Ausdrucksattributwert muss mit einem Doppelpunkt (`:`) beginnen, gefolgt von einem oder mehreren alphanumerischen Zeichen.

Angenommen, Sie möchten alle `ProductCatalog`-Elemente, die in `Black` verfügbar sind und `500` oder weniger kosten, zurückgeben. Sie können eine `Scan`-Operation mit einem Filterausdruck verwenden, wie in diesem AWS Command Line Interface (AWS CLI)-Beispiel gezeigt:

```
aws dynamodb scan \
    --table-name ProductCatalog \
    --filter-expression "contains(Color, :c) and Price <= :p" \
    --expression-attribute-values file://values.json
```

Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.

```
{
    ":c": { "S": "Black" },
    ":p": { "N": "500" }
}
```

Wenn Sie einen Ausdrucksattributwert definieren, müssen Sie ihn während des gesamten Ausdrucks einheitlich verwenden. Sie dürfen außerdem das Symbol `:` nicht weglassen. 

Ausdrucksattributwerte werden mit Schlüsselbedingungsausdrücken, Bedingungsausdrücken, Aktualisierungsausdrücken und Filterausdrücken verwendet.

# Verwenden von Projektionsausdrücken in DynamoDB
<a name="Expressions.ProjectionExpressions"></a>

Um Daten aus einer Tabelle zu lesen, verwenden sie Operationen wie `GetItem`, `Query` oder `Scan`. Amazon DynamoDB gibt standardmäßig alle Elementattribute zurück. Verwenden Sie einen Projektionsausdruck, um nur einige und nicht alle Attribute abzurufen.

Ein *Projektionsausdruck* ist eine Zeichenfolge, mit der die gewünschten Attribute identifiziert werden. Zum Abrufen eines einzelnen Attributs geben Sie seinen Namen an. Für mehrere Attribute müssen die Namen durch Kommas getrennt werden.

Es folgen einige Beispiele für Projektionsausdrücke, basierend auf dem `ProductCatalog`-Element von [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](Expressions.Attributes.md):
+ Ein einzelnes Attribut auf oberster Ebene:

  `Title `
+ Drei Attribute auf oberster Ebene. DynamoDB ruft die gesamte `Color`-Einstellung.

  `Title, Price, Color`
+ Vier Attribute auf oberster Ebene. DynamoDB gibt den gesamten Inhalt von `RelatedItems` und `ProductReviews` zurück.

  `Title, Description, RelatedItems, ProductReviews`

**Anmerkung**  
Der Projektionsausdruck wirkt sich nicht auf den Verbrauch des bereitgestellten Durchsatzes aus. DynamoDB ermittelt die verbrauchten Kapazitätseinheiten basierend auf der Elementgröße, nicht anhand der Menge der Daten, die an eine Anwendung zurückgegeben werden.

**Reservierte Wörter und Sonderzeichen**

DynamoDB verfügt über reservierte Wörter und Sonderzeichen. DynamoDB lässt diese reservierten Wörter und Sonderzeichen für Namen zu. Dennoch empfehlen wir, diese nicht zu verwenden, da Sie Aliasse für diese Namen definieren müssen, sobald Sie sie in einem Ausdruck verwenden. Eine vollständige Liste finden Sie hier: [Reservierte Wörter in DynamoDB](ReservedWords.md).

In folgenden Fällen müssen Sie Ausdrucksattributnamen anstelle des eigentlichen Namens verwenden: 
+ Der Attributname steht auf der Liste der reservierten Wörter von DynamoDB.
+ Der Attributname erfüllt nicht die Anforderung, dass das erste Zeichen `a-z` oder `A-Z` und das zweite Zeichen (falls vorhanden) `a-Z`, `A-Z` oder `0-9` sein muss.
+ Der Attributname enthält **\$1** (Raute) oder **:** (Doppelpunkt).

Das folgende AWS CLI Beispiel zeigt, wie ein Projektionsausdruck mit einer `GetItem` Operation verwendet wird. Dieser Projektionsausdruck ruft ein skalares Attribut auf oberster Ebene (`Description`), das erste Element in einer Liste (`RelatedItems[0]`) und eine Liste, die innerhalb einer Zuordnung verschachtelt ist (`ProductReviews.FiveStar`), ab.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '"Id": { "N": "123" } \
    --projection-expression "Description, RelatedItems[0], ProductReviews.FiveStar"
```

In diesem Beispiel wird der folgende JSON zurückgegeben.

```
{
    "Item": {
        "Description": {
            "S": "123 description"
        },
        "ProductReviews": {
            "M": {
                "FiveStar": {
                    "L": [
                        {
                            "S": "Excellent! Can't recommend it highly enough! Buy it!"
                        },
                        {
                            "S": "Do yourself a favor and buy this."
                        }
                    ]
                }
            }
        },
        "RelatedItems": {
            "L": [
                {
                    "N": "341"
                }
            ]
        }
    }
}
```

# Verwenden von Aktualisierungsausdrücken in DynamoDB
<a name="Expressions.UpdateExpressions"></a>

Die `UpdateItem`-Operation aktualisiert ein vorhandenes Elements oder fügt ein neues Element in die Tabelle ein, wenn es noch nicht existiert. Sie müssen den Schlüssel des Elements angeben, das Sie aktualisieren möchten. Außerdem müssen Sie einen Aktualisierungsausdruck angeben, der die zu ändernden Attribute sowie die Werte enthält, die Sie ihnen zuweisen möchten. 

Ein *Aktualisierungsausdruck* gibt an, wie `UpdateItem` die Attribute eines Elements ändert, z. B. durch Festlegen eines Skalarwerts oder durch Entfernen von Elementen aus einer Liste oder Zuordnung.

Im Folgenden finden Sie eine Syntaxzusammenfassung für Aktualisierungsausdrücke.

```
update-expression ::=
    [ SET action [, action] ... ]
    [ REMOVE action [, action] ...]
    [ ADD action [, action] ... ]
    [ DELETE action [, action] ...]
```

Ein Aktualisierungsausdruck besteht aus einer oder mehreren Klauseln. Jede Klausel beginnt mit einem `SET`-, `REMOVE`-, `ADD`- oder `DELETE`-Schlüsselwort. Sie können jede dieser Klauseln in beliebiger Reihenfolge in einen Aktualisierungsausdruck einfügen. Jedes Aktionsschlüsselwort kann jedoch nur einmal angezeigt werden.

Jede Klausel umfasst eine oder mehrere Aktionen, die durch Komma getrennt sind. Jede Aktion stellt eine Datenänderung dar.

Die Beispiele in diesem Abschnitt basieren auf dem Element `ProductCatalog`, wie in [Verwenden von Projektionsausdrücken in DynamoDB](Expressions.ProjectionExpressions.md) dargestellt.

Die folgenden Themen behandeln verschiedene Anwendungsfälle für die `SET`-Aktion.

**Topics**
+ [SET – Ändern oder Hinzufügen von Elementattributen](#Expressions.UpdateExpressions.SET)
+ [REMOVE – Löschen von Attributen aus einem Element](#Expressions.UpdateExpressions.REMOVE)
+ [ADD – Aktualisieren von Zahlen und Sätzen](#Expressions.UpdateExpressions.ADD)
+ [DELETE – Entfernen von Elementen aus einem Satz](#Expressions.UpdateExpressions.DELETE)
+ [Verwenden mehrerer Aktualisierungsausdrücke](#Expressions.UpdateExpressions.Multiple)

## SET – Ändern oder Hinzufügen von Elementattributen
<a name="Expressions.UpdateExpressions.SET"></a>

Verwenden Sie die `SET`-Aktion in einem Aktualisierungsausdruck, um ein oder mehrere Attribute zu einem Element hinzuzufügen. Wenn diese Attribute bereits vorhanden sind, werden sie durch die neuen Werte überschrieben. Wenn Sie verhindern möchten, dass ein vorhandenes Attribut überschrieben wird, können Sie `SET` mit der Funktion `if_not_exists` verwenden. Die Funktion `if_not_exists` gilt spezifisch für die `SET`-Aktion und kann nur in einem Aktualisierungsausdruck verwendet werden.

Wenn Sie `SET` verwenden, um ein Listenelement zu aktualisieren, wird der Inhalt dieses Elements durch die neuen Daten ersetzt, die Sie angeben. Wenn das Element noch nicht vorhanden ist, fügt `SET` das neue Element am Ende der Liste an.

Wenn Sie mehrere Elemente in einer einzigen `SET`-Operation hinzufügen, werden die Elemente nach Elementnummer sortiert.

Sie können `SET` auch verwenden, um einen Wert zu einem Attribut des Typs `Number` zu addieren oder von diesem zu subtrahieren. Wenn Sie mehrere `SET`-Aktionen durchführen möchten, trennen Sie sie durch Komma.

Schauen Sie sich die folgende Syntaxzusammenfassung an:
+ Das *path* Element ist der Dokumentpfad zu dem Element.
+ Ein **operand**Element kann entweder ein Dokumentpfad zu einem Element oder eine Funktion sein.

```
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function

function ::=
    if_not_exists (path, value)
```

Wenn das Element kein Attribut im angegebenen Pfad enthält, ergibt `if_not_exists` `value`. Andernfalls ergibt es `path`.

Die folgende `PutItem`-Operation erstellt ein Beispielelement, auf das wir uns in den Beispielen beziehen werden.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

Die Argumente für `--item` werden in der Datei `item.json` gespeichert. (Der Einfachheit halber werden nur wenige Elementattribute verwendet.)

```
{
    "Id": {"N": "789"},
    "ProductCategory": {"S": "Home Improvement"},
    "Price": {"N": "52"},
    "InStock": {"BOOL": true},
    "Brand": {"S": "Acme"}
}
```

**Topics**
+ [Ändern von Attributen](#Expressions.UpdateExpressions.SET.ModifyingAttributes)
+ [Hinzufügen von Listen und Zuordnungen](#Expressions.UpdateExpressions.SET.AddingListsAndMaps)
+ [Hinzufügen von Elementen zu einer Liste](#Expressions.UpdateExpressions.SET.AddingListElements)
+ [Hinzufügen verschachtelter Zuordnungsattribute](#Expressions.UpdateExpressions.SET.AddingNestedMapAttributes)
+ [Vergrößern und Verkleinern numerischer Attribute](#Expressions.UpdateExpressions.SET.IncrementAndDecrement)
+ [Anfügen von Elementen zu einer Liste](#Expressions.UpdateExpressions.SET.UpdatingListElements)
+ [Verhindern der Überschreibung eines vorhandenen Attributs](#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites)

### Ändern von Attributen
<a name="Expressions.UpdateExpressions.SET.ModifyingAttributes"></a>

**Example**  
Aktualisieren Sie die Attribute `ProductCategory` und `Price`.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET ProductCategory = :c, Price = :p" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":c": { "S": "Hardware" },
    ":p": { "N": "60" }
}
```

**Anmerkung**  
In der Operation `UpdateItem` führt `--return-values ALL_NEW` dazu, dass DynamoDB das Element so zurückgibt, wie es nach der Aktualisierung erscheint.

### Hinzufügen von Listen und Zuordnungen
<a name="Expressions.UpdateExpressions.SET.AddingListsAndMaps"></a>

**Example**  
Hinzufügen einer neuen Liste und Zuordnung:  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":ri": {
        "L": [
            { "S": "Hammer" }
        ]
    },
    ":pr": {
        "M": {
            "FiveStar": {
                "L": [
                    { "S": "Best product ever!" }
                ]
            }
        }
    }
}
```

### Hinzufügen von Elementen zu einer Liste
<a name="Expressions.UpdateExpressions.SET.AddingListElements"></a>

**Example**  
Fügen Sie der Liste `RelatedItems` ein neues Attribut hinzu. (Denken Sie daran, dass Listenelemente nullbasiert sind, sodass [0] das erste Element in der Liste darstellt, [1] das zweite und so weiter.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :ri" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":ri": { "S": "Nails" }
}
```

**Anmerkung**  
Wenn Sie `SET` verwenden, um ein Listenelement zu aktualisieren, wird der Inhalt dieses Elements durch die neuen Daten ersetzt, die Sie angeben. Wenn das Element noch nicht vorhanden ist, fügt `SET` das neue Element am Ende der Liste an.  
Wenn Sie mehrere Elemente in einer einzigen `SET`-Operation hinzufügen, werden die Elemente nach Elementnummer sortiert.

### Hinzufügen verschachtelter Zuordnungsattribute
<a name="Expressions.UpdateExpressions.SET.AddingNestedMapAttributes"></a>

**Example**  
Fügen Sie einige verschachtelte Zuordnungsattribute hinzu.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
    --expression-attribute-names file://names.json \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Die Argumente für `--expression-attribute-names` werden in der Datei `names.json` gespeichert.  

```
{
    "#pr": "ProductReviews",
    "#5star": "FiveStar",
    "#3star": "ThreeStar"
}
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":r5": { "S": "Very happy with my purchase" },
    ":r3": {
        "L": [
            { "S": "Just OK - not that great" }
        ]
    }
}
```

**Wichtig**  
Sie können die Attribute einer verschachtelten Map nicht aktualisieren, wenn die übergeordnete Map nicht existiert. Wenn Sie versuchen, ein verschachteltes Attribut zu aktualisieren (z. B.`ProductReviews.FiveStar`), obwohl die übergeordnete Zuordnung (`ProductReviews`) nicht vorhanden ist, gibt DynamoDB a `ValidationException` mit der Meldung *„Der im Aktualisierungsausdruck angegebene Dokumentpfad ist für die Aktualisierung ungültig*“ zurück.  
Wenn Sie Elemente erstellen, für die die Attribute der verschachtelten Map später aktualisiert werden, initialisieren Sie leere Maps für die übergeordneten Attribute. Beispiel:  

```
{
    "Id": {"N": "789"},
    "ProductReviews": {"M": {}},
    "Metadata": {"M": {}}
}
```
Auf diese Weise können Sie verschachtelte Attribute ohne Fehler aktualisieren. `ProductReviews.FiveStar`

### Vergrößern und Verkleinern numerischer Attribute
<a name="Expressions.UpdateExpressions.SET.IncrementAndDecrement"></a>

Sie können ein vorhandenes numerisches Attribut vergrößern oder verkleinern. Dazu verwenden Sie die Operatoren `+` (plus) und `-` (minus).

**Example**  
Verringern Sie den `Price` eines Elements.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```
Um den `Price` zu erhöhen, verwenden Sie den Operator `+` im Aktualisierungsausdruck.

### Anfügen von Elementen zu einer Liste
<a name="Expressions.UpdateExpressions.SET.UpdatingListElements"></a>

Sie können Elemente an das Ende einer Liste anfügen. Dazu verwenden Sie `SET` mit der Funktion `list_append`. (Beim Funktionsnamen muss die Groß- und Kleinschreibung beachtet werden.) Die Funktion `list_append` gilt spezifisch für die `SET`-Aktion und kann nur in einem Aktualisierungsausdruck verwendet werden. Die Syntax ist wie folgt.
+ `list_append (list1, list2)`

Die Funktion nimmt zwei Listen als Eingabe und fügt alle Elemente von `list2` bis ` list1` an.

**Example**  
Unter [Hinzufügen von Elementen zu einer Liste](#Expressions.UpdateExpressions.SET.AddingListElements) erstellen Sie die Liste `RelatedItems` und fügen ihr zwei Elemente hinzu: `Hammer` und `Nails`. Nun fügen Sie zwei weitere Elemente an das Ende von `RelatedItems` an.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(#ri, :vals)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values file://values.json  \
    --return-values ALL_NEW
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":vals": {
        "L": [
            { "S": "Screwdriver" },
            {"S": "Hacksaw" }
        ]
    }
}
```
Am Schluss fügen Sie ein weiteres Element an den *Anfang* von `RelatedItems` an. Vertauschen Sie dazu die Reihenfolge der `list_append`-Elemente. (Beachten Sie, dass `list_append` die beiden Listen als Eingabe übernimmt und die zweite Liste an die erste anfügt.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(:vals, #ri)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
    --return-values ALL_NEW
```
Das daraus resultierende Attribut `RelatedItems` enthält jetzt fünf Elemente in der folgenden Reihenfolge: `Chisel`, `Hammer`, `Nails`, `Screwdriver`, `Hacksaw`.

### Verhindern der Überschreibung eines vorhandenen Attributs
<a name="Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites"></a>

**Example**  
Legen Sie den `Price` eines Elements fest, jedoch nur dann, wenn das Element noch nicht über ein `Price`-Attribut verfügt. (Wenn `Price` bereits vorhanden ist, ändert sich nichts.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW
```

## REMOVE – Löschen von Attributen aus einem Element
<a name="Expressions.UpdateExpressions.REMOVE"></a>

Verwenden Sie die `REMOVE`-Aktion in einem Aktualisierungsausdruck, um ein oder mehrere Attribute aus einem Element in Amazon DynamoDB zu entfernen. Wenn Sie mehrere `REMOVE`-Aktionen durchführen möchten, trennen Sie sie durch Komma.

Im Folgenden finden Sie eine Syntaxzusammenfassung für `REMOVE` in einem Aktualisierungsausdruck. Der einzige Operand ist der Dokumentpfad für das Attribut, das Sie entfernen möchten.

```
remove-action ::=
    path
```

**Example**  
Löschen einiger Attribute aus einem Element. (Wenn die Attribute nicht vorhanden sind, ändert sich nichts.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE Brand, InStock, QuantityOnHand" \
    --return-values ALL_NEW
```

### Entfernen von Elementen aus einer Liste
<a name="Expressions.UpdateExpressions.REMOVE.RemovingListElements"></a>

Sie können `REMOVE` verwenden, um einzelne Element aus einer Liste zu löschen.

**Example**  
Unter [Anfügen von Elementen zu einer Liste](#Expressions.UpdateExpressions.SET.UpdatingListElements) haben Sie ein Listenattribut (`RelatedItems`) so geändert, dass es fünf Elemente enthält:   
+ `[0]`—`Chisel`
+ `[1]`—`Hammer`
+ `[2]`—`Nails`
+ `[3]`—`Screwdriver`
+ `[4]`—`Hacksaw`
Das folgende Beispiel AWS Command Line Interface (AWS CLI) löscht `Hammer` und `Nails` aus der Liste.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
    --return-values ALL_NEW
```
Nach dem Entfernen von `Hammer` und `Nails` werden die verbleibenden Elemente verschoben. Die Liste enthält nun Folgendes:  
+ `[0]`—`Chisel`
+ `[1]`—`Screwdriver`
+ `[2]`—`Hacksaw`

## ADD – Aktualisieren von Zahlen und Sätzen
<a name="Expressions.UpdateExpressions.ADD"></a>

**Anmerkung**  
Im Allgemeinen empfehlen wir, idempotente Operationen `ADD` zu verwenden, `SET` anstatt sie sicherzustellen.

Verwenden Sie die `ADD`-Aktion in einem Aktualisierungsausdruck, um ein neues Attribut mit seinen zugehörigen Werten einem Element hinzuzufügen.

Wenn das Attribut bereits vorhanden ist, hängt das Verhalten von `ADD` vom Datentyp des Attributs ab.
+ Wenn das vorhandene Attribut eine Zahl ist und der Wert, den Sie hinzufügen, ebenfalls eine Zahl, wird der Wert mathematisch zum vorhandenen Attribut addiert. (Wenn der Wert eine negative Zahl ist, wird er vom vorhandenen Attribut abgezogen.)
+ Wenn es sich bei dem Attribut um einen Satz handelt und der Wert, den Sie hinzufügen, ebenfalls ein Satz ist, wird der Wert an den vorhandenen Satz angefügt.

**Anmerkung**  
Die `ADD`-Aktion unterstützt nur die Datentypen "Zahl" und "Satz".

Wenn Sie mehrere `ADD`-Aktionen durchführen möchten, trennen Sie sie durch Komma.

Schauen Sie sich die folgende Syntaxzusammenfassung an:
+ Das *path* Element ist der Dokumentpfad zu einem Attribut. Das Attribut muss entweder vom Datentyp `Number` oder "Satz" sein. 
+ Das *value* Element ist eine Zahl, die Sie dem Attribut hinzufügen möchten (für `Number` Datentypen), oder ein Satz, der an das Attribut angehängt werden soll (für Satztypen).

```
add-action ::=
    path value
```

Die folgenden Themen behandeln verschiedene Anwendungsfälle für die `ADD`-Aktion.

**Topics**
+ [Hinzufügen einer Zahl](#Expressions.UpdateExpressions.ADD.Number)
+ [Hinzufügen von Elementen zu einem Satz](#Expressions.UpdateExpressions.ADD.Set)

### Hinzufügen einer Zahl
<a name="Expressions.UpdateExpressions.ADD.Number"></a>

Angenommen, das Attribut `QuantityOnHand` ist nicht vorhanden. Im folgenden AWS CLI Beispiel wird der Wert `QuantityOnHand` auf 5 gesetzt.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW
```

Da `QuantityOnHand` nun vorhanden ist, können Sie das Beispiel erneut ausführen, um `QuantityOnHand` jedes Mal um 5 zu erhöhen.

### Hinzufügen von Elementen zu einem Satz
<a name="Expressions.UpdateExpressions.ADD.Set"></a>

Angenommen, das Attribut `Color` ist nicht vorhanden. Im folgenden AWS CLI -Beispiel wird `Color` auf einen Zeichenfolgensatz mit zwei Elementen festgelegt.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
    --return-values ALL_NEW
```

Da `Color` nun vorhanden ist, können wir weitere Elemente hinzufügen.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
    --return-values ALL_NEW
```

## DELETE – Entfernen von Elementen aus einem Satz
<a name="Expressions.UpdateExpressions.DELETE"></a>

**Wichtig**  
Die `DELETE`-Aktion unterstützt nur den Datentyp `Set`.

Verwenden Sie die `DELETE`-Aktion in einem Aktualisierungsausdruck, um ein oder mehrere Elemente aus einem Satz zu entfernen. Wenn Sie mehrere `DELETE`-Aktionen durchführen möchten, trennen Sie sie durch Komma.

Schauen Sie sich die folgende Syntaxzusammenfassung an:
+ Das *path* Element ist der Dokumentpfad zu einem Attribut. Das Attribut muss vom Datentyp "Satz" sein.
+ Das *subset* ist ein oder mehrere Elemente, aus denen Sie löschen möchten*path*. Sie müssen einen Satztyp angeben*subset*.

```
delete-action ::=
    path subset
```

**Example**  
Unter [Hinzufügen von Elementen zu einem Satz](#Expressions.UpdateExpressions.ADD.Set) erstellen Sie den `Color`-Zeichenfolgendsatz. In diesem Beispiel werden einige der Elemente aus diesem Satz entfernt:  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "DELETE Color :p" \
    --expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
    --return-values ALL_NEW
```

## Verwenden mehrerer Aktualisierungsausdrücke
<a name="Expressions.UpdateExpressions.Multiple"></a>

Sie können mehrere Aktionen in einem einzigen Aktualisierungsausdruck verwenden. Alle Attributverweise werden anhand des Status des Elements aufgelöst, bevor eine der Aktionen angewendet wird.

**Example**  
Bei einem bestimmten Element `{"id": "1", "a": 1, "b": 2, "c": 3}` entfernt `a` und verschiebt der folgende Ausdruck die Werte von `b` und`c`:  

```
aws dynamodb update-item \
    --table-name test \
    --key '{"id":{"S":"1"}}' \
    --update-expression "REMOVE a SET b = a, c = b" \
    --return-values ALL_NEW
```
Das Ergebnis ist`{"id": "1", "b": 1, "c": 2}`. Obwohl `a` es entfernt und im selben Ausdruck neu zugewiesen `b` wird, werden beide Verweise auf ihre ursprünglichen Werte aufgelöst.

**Example**  
Wenn Sie den Wert eines Attributs ändern und ein anderes Attribut vollständig entfernen möchten, können Sie eine SET-Aktion und eine REMOVE-Aktion in einer einzelnen Anweisung verwenden. Dieser Vorgang würde den `Price`-Wert auf 15 verringern und gleichzeitig das `InStock`-Attribut aus dem Element entfernen.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p REMOVE InStock" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```

**Example**  
Wenn Sie einer Liste etwas hinzufügen und gleichzeitig den Wert eines anderen Attributs ändern möchten, können Sie zwei SET-Aktionen in einer einzelnen Anweisung verwenden. Diese Operation würde dem `RelatedItems`-Listenattribut „Nails“ hinzufügen und den `Price`-Wert auf 21 setzen.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :newValue, Price = :newPrice" \
    --expression-attribute-values '{":newValue": {"S":"Nails"}, ":newPrice": {"N":"21"}}'  \
    --return-values ALL_NEW
```

# Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB
<a name="Expressions.OperatorsAndFunctions"></a>

Zum Bearbeiten der Daten in einer DynamoDB-Tabelle verwenden Sie die Operationen `PutItem`, `UpdateItem` und `DeleteItem`. Für diese Datenmanipulationsoperationen können Sie einen Bedingungsausdruck angeben, um zu ermitteln, welche Elemente geändert werden sollten. Wenn der Bedingungsausdruck „true“ ergibt, ist die Operation erfolgreich. Andernfalls schlägt sie fehl.

In diesem Abschnitt werden die integrierten Funktionen und Schlüsselwörter zum Schreiben von Filter- und Bedingungsausdrücken in Amazon DynamoDB erörtert. Ausführlichere Informationen zu Funktionen und Programmierung mit DynamoDB finden Sie unter [Programmieren mit DynamoDB und AWS SDKs](Programming.md) und in der [DynamoDB-API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/).

**Topics**
+ [Syntax für Filter- und Bedingungsausdrücke](#Expressions.OperatorsAndFunctions.Syntax)
+ [Durchführen von Vergleichen](#Expressions.OperatorsAndFunctions.Comparators)
+ [Funktionen](#Expressions.OperatorsAndFunctions.Functions)
+ [Logische Auswertungen](#Expressions.OperatorsAndFunctions.LogicalEvaluations)
+ [Klammern](#Expressions.OperatorsAndFunctions.Parentheses)
+ [Priorität in Bedingungen](#Expressions.OperatorsAndFunctions.Precedence)

## Syntax für Filter- und Bedingungsausdrücke
<a name="Expressions.OperatorsAndFunctions.Syntax"></a>

In der folgenden Syntaxzusammenfassung *operand* kann ein wie folgt lauten: 
+ Ein Attributname auf oberster Ebene, z. B. `Id`, `Title`, `Description` oder `ProductCategory`
+ Ein Dokumentpfad, der auf ein verschachteltes Attribut verweist

```
condition-expression ::=
      operand comparator operand
    | operand BETWEEN operand AND operand
    | operand IN ( operand (',' operand (, ...) ))
    | function
    | condition AND condition
    | condition OR condition
    | NOT condition
    | ( condition )

comparator ::=
    =
    | <>
    | <
    | <=
    | >
    | >=

function ::=
    attribute_exists (path)
    | attribute_not_exists (path)
    | attribute_type (path, type)
    | begins_with (path, substr)
    | contains (path, operand)
    | size (path)
```

## Durchführen von Vergleichen
<a name="Expressions.OperatorsAndFunctions.Comparators"></a>

Verwenden Sie diese Komparatoren, um einen Operanden mit einem einzelnen Wert zu vergleichen:
+ `a = b`— Wahr, wenn gleich *a* ist*b*.
+ `a <> b`— Wahr, wenn ungleich *a* ist*b*.
+ `a < b`— Stimmt, wenn *a* es kleiner ist als*b*.
+ `a <= b`— Wahr, wenn kleiner oder gleich *a* ist*b*.
+ `a > b`— Stimmt, wenn größer als *a* ist*b*.
+ `a >= b`— Wahr, wenn größer als oder gleich *a* ist*b*.

Verwenden Sie die Schlüsselwörter `BETWEEN` und `IN`, um einen Operanden mit einer Reihe von Werten oder einer Aufzählung von Werten zu vergleichen:
+ `a BETWEEN b AND c`— Wahr*b*, wenn größer als oder gleich und kleiner als oder gleich *a* ist*c*.
+ `a IN (b, c, d) `— Wahr, wenn *a* der Wert einem beliebigen Wert in der Liste entspricht, z. B. einem beliebigen Wert von *b**c*, oder. *d* Die Liste kann bis zu 100 Werte enthalten, die durch Kommas getrennt sind.

## Funktionen
<a name="Expressions.OperatorsAndFunctions.Functions"></a>

Verwenden Sie die folgenden Funktionen, um zu bestimmen, ob ein Attribut in einem Element vorhanden ist, oder um den Wert eines Attributs zu bewerten. Bei Funktionsnamen wird zwischen Groß- und Kleinschreibung unterschieden. Bei einem verschachtelten Attribut müssen Sie den vollständigen Dokumentpfad angeben.


****  

| Funktion | Description | 
| --- | --- | 
|  `attribute_exists (path)`  | True, wenn das Element das von `path` angegebene Attribut enthält. Beispiel: Prüfung, ob ein Element in der Tabelle `Product` über ein Seitenansichtsbild verfügt. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 
|  `attribute_not_exists (path)`  | True, wenn das Element das von `path` angegebene Attribut nicht enthält. Beispiel: Prüfung, ob ein Element über ein `Manufacturer`-Attribut verfügt [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 
|  `attribute_type (path, type)`  |  True, wenn das Attribut am angegebenen Pfad einen bestimmten Datentyp hat. Der Parameter `type` muss einer der folgenden Werte aufweisen: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Sie müssen einen Ausdrucksattributwert für den Parameter `type` verwenden. Beispiel: Prüfung, ob das Attribut `QuantityOnHand` vom Typ Liste ist. In diesem Beispiel ist `:v_sub` ein Platzhalter für die Zeichenfolge `L`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Sie müssen einen Ausdrucksattributwert für den Parameter `type` verwenden.   | 
|  `begins_with (path, substr)`  |  True, wenn das von `path` angegebene Attribut mit einer bestimmten Teilzeichenfolge beginnt. Beispiel: Prüfung, ob die ersten Zeichen der URL zum Vorderansichtsbild `http://` lauten. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `http://`.  | 
|  `contains (path, operand)`  | True, wenn das von `path` angegebene Attribut Folgendes ist: [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Wenn das von `path` angegebene Attribut eine `String` ist, muss der `operand` `String` sein. Wenn das von `path` angegebene Attribut `Set` ist muss `operand` der Elementtyp des Satzes sein. Der Pfad und der Operand müssen unterschiedlich sein. Das heißt, bei `contains (a, a)` wird ein Fehler zurückgegeben. Beispiel: Prüfung, ob das Attribut `Brand` die Teilzeichenfolge `Company` enthält. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `Company`. Beispiel: Prüfung, ob das Produkt in rot verfügbar ist. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `Red`. | 
|  `size (path)`  | Gibt eine Zahl zurück, die für die Größe eines Attributs steht. Die folgenden sind gültige Datentypen, die mit `size` verwendet werden können.  Wenn das Attribut vom Typ `String` ist, gibt `size` die Länge der Zeichenfolge zurück. Beispiel: Prüfung, ob die Zeichenfolge `Brand` kleiner oder gleich 20 Zeichen ist. Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `20`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Wenn das Attribut vom Typ `Binary` ist, gibt `size` die Anzahl der Bytes im Attributwert zurück. Beispiel: Angenommen, das Element `ProductCatalog` verfügt über ein binäres Attribut mit der Bezeichnung `VideoClip`, das ein kurzes Video über das betreffende Produkt enthält. Der folgende Ausdruck überprüft, ob `VideoClip` 64.000 Byte überschreitet. Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `64000`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Wenn das Attribut vom Typ `Set` ist, gibt `size` die Anzahl der Elemente im Satz zurück.  Beispiel: Prüfung, ob das Produkt in mehr als einer Farbe verfügbar ist. Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `1`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Wenn das Attribut vom Typ `List` oder `Map` ist, gibt `size` die Anzahl der untergeordneten Elemente zurück. Beispiel: Prüfung, ob die Anzahl der `OneStar`-Rezensionen einen bestimmten Grenzwert überschritten hat. Der Ausdrucksattributwert `:v_sub` ist ein Platzhalter für `3`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 

## Logische Auswertungen
<a name="Expressions.OperatorsAndFunctions.LogicalEvaluations"></a>

Verwenden Sie die Schlüsselwörter `AND`, `OR` und `NOT`, um logische Auswertungen durchzuführen. In der folgenden Liste *a* und *b* stellen Bedingungen dar, die ausgewertet werden sollen.
+ `a AND b`— Stimmt, wenn *a* und beide wahr *b* sind.
+ `a OR b`— Stimmt, wenn entweder *a* oder *b* (oder beide) wahr sind.
+ `NOT a`— Wahr, wenn falsch *a* ist. Falsch, wenn *a* es wahr ist.

Im Folgenden finden Sie ein Codebeispiel für AND in einer Operation.

`dynamodb-local (*)> select * from exprtest where a > 3 and a < 5;`

## Klammern
<a name="Expressions.OperatorsAndFunctions.Parentheses"></a>

Verwenden Sie Klammern, um die Priorität einer logischen Auswertung zu ändern. Nehmen wir zum Beispiel an, dass die Bedingungen *a* und wahr *b* sind und diese Bedingung falsch *c* ist. Der folgenden Ausdruck ergibt True:
+ `a OR b AND c`

Wenn Sie jedoch eine Bedingung in Klammern setzen, wird diese zuerst ausgewertet. Folgendes ergibt z. B. False:
+  `(a OR b) AND c`

**Anmerkung**  
Sie können Klammern in einem Ausdruck schachteln. Die innersten Klammern werden zuerst ausgewertet.

Im Folgenden finden Sie ein Codebeispiel mit Klammern in einer logischen Auswertung.

`dynamodb-local (*)> select * from exprtest where attribute_type(b, string) or ( a = 5 and c = “coffee”);`

## Priorität in Bedingungen
<a name="Expressions.OperatorsAndFunctions.Precedence"></a>

 DynamoDB wertet Bedingungen von links nach rechts entsprechend der folgenden Prioritätsregeln aus:
+ `= <> < <= > >=`
+ `IN`
+ `BETWEEN`
+ `attribute_exists attribute_not_exists begins_with contains`
+ Klammern
+ `NOT`
+ `AND`
+ `OR`

# CLI-Beispiel für DynamoDB-Bedingungsausdrücke
<a name="Expressions.ConditionExpressions"></a>

Im Folgenden finden Sie einige AWS Command Line Interface (AWS CLI) Beispiele für die Verwendung von Bedingungsausdrücken. Diese Beispiele basieren auf der Tabelle `ProductCatalog`, die in [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](Expressions.Attributes.md) eingeführt wurde. Der Partitionsschlüssel für diese Tabelle lautet `Id`. Es gibt keinen Sortierschlüssel. Die folgende `PutItem`-Operation erstellt ein `ProductCatalog`-Beispielelement, auf das wir uns in den Beispielen beziehen werden:

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

Die Argumente für `--item` werden in der Datei `item.json` gespeichert. (Der Einfachheit halber werden nur wenige Elementattribute verwendet.)

```
{
    "Id": {"N": "456" },
    "ProductCategory": {"S": "Sporting Goods" },
    "Price": {"N": "650" }
}
```

**Topics**
+ [Conditional Put (Bedingtes Setzen)](#Expressions.ConditionExpressions.PreventingOverwrites)
+ [Bedingte Löschungen](#Expressions.ConditionExpressions.AdvancedComparisons)
+ [Bedingte Aktualisierungen](#Expressions.ConditionExpressions.SimpleComparisons)
+ [Beispiele für bedingte Ausdrücke](#Expressions.ConditionExpressions.ConditionalExamples)

## Conditional Put (Bedingtes Setzen)
<a name="Expressions.ConditionExpressions.PreventingOverwrites"></a>

Die `PutItem`-Operation überschreibt ein Element mit demselben Primärschlüssel (falls vorhanden). Wenn Sie dies vermeiden möchten, verwenden Sie einen Bedingungsausdruck. Dies ermöglicht das Fortsetzen des Schreibvorgangs nur dann, wenn das in Frage stehende Element nicht bereits über denselben Primärschlüssel verfügt.

Im folgenden Beispiel wird mit `attribute_not_exists()` überprüft, ob der Primärschlüssel in der Tabelle vorhanden ist, bevor versucht wird, den Schreibvorgang durchzuführen. 

**Anmerkung**  
Wenn Ihr Primärschlüssel sowohl aus einem Partitionsschlüssel (pk) als auch aus einem Sortierschlüssel (sk) besteht, überprüft der Parameter, ob `attribute_not_exists(pk)` UND `attribute_not_exists(sk)` als gesamte Anweisung als wahr oder falsch ausgewertet werden, bevor versucht wird, den Schreibvorgang durchzuführen.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json \
    --condition-expression "attribute_not_exists(Id)"
```

Wenn der Bedingungsausdruck mit „falsch“ ausgewertet wird, gibt DynamoDB die folgende Fehlermeldung zurück: Die bedingte Anforderung ist fehlgeschlagen.

**Anmerkung**  
Weitere Informationen zu `attribute_not_exists` und anderen Funktionen finden Sie unter [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md).

## Bedingte Löschungen
<a name="Expressions.ConditionExpressions.AdvancedComparisons"></a>

Um ein bedingtes Löschen durchzuführen, nutzen Sie eine `DeleteItem`-Operation mit einem Bedingungsausdruck. Der Bedingungsausdruck muss mit "true" ausgewertet werden, damit die Operation erfolgreich ist; andernfalls schlägt sie fehl.

Betrachten Sie das oben definierte Element.

Angenommen, Sie möchten das Element löschen, aber nur unter den folgenden Bedingungen:
+  Die `ProductCategory` ist entweder "Sportartikel" oder "Gartenzubehör".
+  Der `Price` liegt zwischen 500 und 600.

Im folgenden Beispiel wird versucht, das Element zu löschen:

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"456"}}' \
    --condition-expression "(ProductCategory IN (:cat1, :cat2)) and (Price between :lo and :hi)" \
    --expression-attribute-values file://values.json
```

Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.

```
{
    ":cat1": {"S": "Sporting Goods"},
    ":cat2": {"S": "Gardening Supplies"},
    ":lo": {"N": "500"},
    ":hi": {"N": "600"}
}
```

**Anmerkung**  
In dem Bedingungsausdruck weist der `:` (Doppelpunkt) auf einen *Ausdrucksattributwert* hin – Platzhalter für den tatsächlichen Wert. Weitere Informationen finden Sie unter [Verwenden von Ausdrucksattributwerten in DynamoDB](Expressions.ExpressionAttributeValues.md).  
Weitere Informationen zu `IN`, `AND` und anderen Schlüsselwörtern finden Sie unter [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md).

In diesem Beispiel wird der `ProductCategory`-Vergleich mit True, aber der `Price`-Vergleich mit False ausgewertet. Dadurch wird der Bedingungsausdruck mit "false" ausgewertet und die `DeleteItem`-Operation schlägt fehl.

## Bedingte Aktualisierungen
<a name="Expressions.ConditionExpressions.SimpleComparisons"></a>

Um eine bedingte Aktualisierung durchzuführen, nutzen Sie eine `UpdateItem`-Operation mit einem Bedingungsausdruck. Der Bedingungsausdruck muss mit "true" ausgewertet werden, damit die Operation erfolgreich ist; andernfalls schlägt sie fehl.

**Anmerkung**  
`UpdateItem` unterstützt auch *Aktualisierungsausdrücke*, in denen Sie die gewünschten Änderungen festlegen, die Sie an einem Element durchführen möchten. Weitere Informationen finden Sie unter [Verwenden von Aktualisierungsausdrücken in DynamoDB](Expressions.UpdateExpressions.md).

Angenommen, Sie beginnen mit dem oben definierten Element.

Das folgende Beispiel führt eine `UpdateItem`-Operation durch. Es versucht, den `Price` eines Produkts um 75 zu reduzieren – der Bedingungsausdruck verhindert jedoch die Aktualisierung, wenn der aktuelle `Price` unter 500 liegt.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --update-expression "SET Price = Price - :discount" \
    --condition-expression "Price > :limit" \
    --expression-attribute-values file://values.json
```

Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.

```
{
    ":discount": { "N": "75"},
    ":limit": {"N": "500"}
}
```

Wenn der Start-`Price` 650 ist, reduziert die `UpdateItem`-Operation den `Price` auf 575. Wenn Sie die `UpdateItem`-Operation erneut ausführen, wird der `Price` auf 500 reduziert. Wenn Sie ein drittes Mal ausführen, wird der Bedingungsausdruck mit False ausgewertet und die Aktualisierung schlägt fehl.

**Anmerkung**  
In dem Bedingungsausdruck weist der `:` (Doppelpunkt) auf einen *Ausdrucksattributwert* hin – Platzhalter für den tatsächlichen Wert. Weitere Informationen finden Sie unter [Verwenden von Ausdrucksattributwerten in DynamoDB](Expressions.ExpressionAttributeValues.md).  
Weitere Informationen zu "*>*" und anderen Operatoren finden Sie unter [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md).

## Beispiele für bedingte Ausdrücke
<a name="Expressions.ConditionExpressions.ConditionalExamples"></a>

Weitere Hinweise zu den Funktionen, die in den folgenden Beispielen verwendet werden, finden Sie unter [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md). Weitere Informationen zum Angeben verschiedener Attributtypen in einem Ausdruck finden Sie unter [Verweisen auf Elementattribute beim Verwenden von Ausdrücken in DynamoDB](Expressions.Attributes.md). 

### Überprüfen der Attribute in einem Element
<a name="Expressions.ConditionExpressions.CheckingForAttributes"></a>

Sie können das Vorhandensein (oder Fehlen) jedes Attributs überprüfen. Wenn der Bedingungsausdruck mit "true" ausgewertet wird, ist die Operation erfolgreich; andernfalls schlägt sie fehl.

Das folgenden Beispiel verwendet `attribute_not_exists` zum Löschen eines Produkts nur, wenn es noch nicht über ein `Price`-Attribut verfügt:

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_not_exists(Price)"
```

DynamoDB stellt auch eine `attribute_exists`-Funktion bereit. Das folgende Beispiel löscht ein Produkt nur dann, wenn es schlechte Bewertungen erhalten hat.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_exists(ProductReviews.OneStar)"
```

### Prüfung auf Attributtyp
<a name="Expressions.ConditionExpressions.CheckingForAttributeType"></a>

Mit der `attribute_type`-Funktion können Sie den Datentyp eines Attributwerts überprüfen. Wenn der Bedingungsausdruck mit "true" ausgewertet wird, ist die Operation erfolgreich; andernfalls schlägt sie fehl.

Im folgenden Beispiel wird `attribute_type` nur dann zum Löschen eines Produkts verwendet, wenn es über ein `Color`-Attribut des Typs String Set verfügt. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_type(Color, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` sind in der expression-attribute-values JSON-Datei gespeichert.

```
{
    ":v_sub":{"S":"SS"}
}
```

### Prüfen des Startwerts der Zeichenfolge
<a name="Expressions.ConditionExpressions.CheckingBeginsWith"></a>

Sie können überprüfen, ob ein Zeichenfolge-Attributwert mit einer bestimmten Teilzeichenfolge beginnt, indem Sie die `begins_with`-Funktion verwenden. Wenn der Bedingungsausdruck mit "true" ausgewertet wird, ist die Operation erfolgreich; andernfalls schlägt sie fehl. 

Im folgenden Beispiel wird `begins_with` nur dann zum Löschen eines Produkts verwendet, wenn das `FrontView`-Element der `Pictures`-Karte mit einem bestimmten Wert beginnt.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "begins_with(Pictures.FrontView, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` werden in der expression-attribute-values JSON-Datei gespeichert.

```
{
    ":v_sub":{"S":"http://"}
}
```

### Prüfen auf ein Element in einem Satz
<a name="Expressions.ConditionExpressions.CheckingForContains"></a>

Sie können nach einem Element in einem Satz oder nach einer Teilzeichenfolge innerhalb einer Zeichenfolge suchen, indem Sie die `contains`-Funktion verwenden. Wenn der Bedingungsausdruck mit "true" ausgewertet wird, ist die Operation erfolgreich; andernfalls schlägt sie fehl. 

Im folgenden Beispiel wird `contains` nur dann zum Löschen eines Produkts verwendet, wenn der `Color`-Zeichenfolgensatz ein Element mit einem bestimmten Wert aufweist. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "contains(Color, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` werden in der expression-attribute-values JSON-Datei gespeichert.

```
{
    ":v_sub":{"S":"Red"}
}
```

### Überprüfen der Größe eines Attributwerts
<a name="Expressions.ConditionExpressions.CheckingForSize"></a>

Sie können die Größe eines Attributwerts überprüfen, indem Sie die `size`-Funktion verwenden. Wenn der Bedingungsausdruck mit "true" ausgewertet wird, ist die Operation erfolgreich; andernfalls schlägt sie fehl. 

Im folgenden Beispiel wird `size` nur dann zum Löschen eines Produkts verwendet, wenn die Größe des `VideoClip`-Binärattributs größer als `64000` Byte ist. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "size(VideoClip) > :v_sub" \
    --expression-attribute-values file://expression-attribute-values.json
```

Die Argumente für `--expression-attribute-values` werden in der expression-attribute-values JSON-Datei gespeichert.

```
{
    ":v_sub":{"N":"64000"}
}
```

# Verwenden von Time to Live (TTL) in DynamoDB
<a name="TTL"></a>

Time To Live (TTL) für DynamoDB ist eine kosteneffiziente Methode zum Löschen von Elementen, die nicht mehr relevant sind. TTL ermöglicht es Ihnen, einen Ablaufzeitstempel pro Element zu definieren, um festzulegen, wann ein Element nicht mehr benötigt wird. DynamoDB löscht abgelaufene Elemente automatisch innerhalb weniger Tage nach ihrem Ablauftermin, ohne dass dafür Schreibdurchsatz verbraucht wird. 

Um TTL zu verwenden, aktivieren Sie es zunächst in einer Tabelle. Definieren Sie dann ein bestimmtes Attribut zum Speichern des TTL-Ablaufzeitstempels. Der Zeitstempel muss als Datentyp [Zahl](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes) im [Unix-Epochenzeitformat](https://en.wikipedia.org/wiki/Unix_time) mit der Granularität Sekunden gespeichert werden. Elemente mit einem TTL-Attribut, das kein Zahlentyp ist, werden vom TTL-Prozess ignoriert. Immer, wenn ein Element erstellt oder aktualisiert wird, können Sie die Ablaufzeit berechnen und sie im TTL-Attribut speichern.

Elemente mit gültigen, abgelaufenen TTL-Attributen können vom System jederzeit gelöscht werden. In der Regel geschieht das innerhalb weniger Tage nach ihrem Ablauf. Sie können die abgelaufenen Elemente, deren Löschung noch aussteht, weiterhin aktualisieren. Dazu gehören auch das Ändern oder Entfernen ihrer TTL-Attribute. Wenn Sie ein abgelaufenes Element aktualisieren, empfiehlt es sich, einen Bedingungsausdruck zu verwenden, um sicherzustellen, dass das Element anschließend nicht gelöscht wurde. Verwenden Sie Filterausdrücke, um abgelaufene Elemente aus [Scan](Scan.md#Scan.FilterExpression)- und [Abfrageergebnissen](Query.FilterExpression.md) zu entfernen.

Gelöschte Elemente funktionieren ähnlich wie Objekte, die bei typischen Löschvorgängen gelöscht wurden. Nach dem Löschen fließen Elemente als Servicelöschungen statt als Benutzerlöschungen in DynamoDB Streams ein und werden wie andere Löschvorgänge aus lokalen und globalen sekundären Indizes entfernt. 

Wenn Sie [Version 2019.11.21 der globalen Tabellen (aktuell)](GlobalTables.md) und außerdem die TTL-Funktion verwenden, repliziert DynamoDB TTL-Löschungen in alle Replikattabellen. Die anfängliche TTL-Löschung verbraucht keine Schreibkapazitätseinheiten (WCU) in der Region, in der die TTL abläuft. Die in die Replikattabellen replizierte TTL-Löschung verbraucht jedoch in jeder Region mit einem Replikat bei Verwendung bereitgestellter Kapazität eine Einheit für replizierte Schreibkapazität bzw. bei Verwendung von On-Demand-Kapazität eine replizierte Schreibeinheit. Dafür werden die entsprechenden Gebühren berechnet.

Weitere Informationen zu TTL finden Sie in den folgenden Themen:

**Topics**
+ [Aktivieren von Time to Live (TTL) in DynamoDB](time-to-live-ttl-how-to.md)
+ [Berechnen der Time to Live (TTL) in DynamoDB](time-to-live-ttl-before-you-start.md)
+ [Arbeiten mit abgelaufenen Elementen und Time to Live (TTL)](ttl-expired-items.md)

# Aktivieren von Time to Live (TTL) in DynamoDB
<a name="time-to-live-ttl-how-to"></a>

**Anmerkung**  
Um das Debugging und die Verifizierung des ordnungsgemäßen Betriebs der TTL-Funktion zu erleichtern, werden die Werte für die Element-TTL in DynamoDB-Diagnoseprotokollen in Klartext angegeben.

Sie können TTL in der Amazon DynamoDB DynamoDB-Konsole, der AWS Command Line Interface (AWS CLI), oder mithilfe der [Amazon DynamoDB DynamoDB-API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/) mit einer der angegebenen Optionen aktivieren. AWS SDKs Es dauert ungefähr eine Stunde, um TTL auf allen Partitionen zu aktivieren.

## DynamoDB TTL über die Konsole aktivieren AWS
<a name="time-to-live-ttl-how-to-enable-console"></a>

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie **Tabellen** und anschließend die Tabelle aus, die Sie ändern möchten.

1. Wählen Sie auf der Registerkarte **Zusätzliche Einstellungen** im Abschnitt **Time to Live (TTL)** die Option **Einschalten** aus, um TTL zu aktivieren.

1. Wenn Sie TTL für eine Tabelle aktivieren, müssen Sie bei DynamoDB einen bestimmten Attributnamen angeben, nach dem der Service sucht, wenn bestimmt wird, ob der Ablauf eines Elements veranlasst werden soll. Beim Namen des TTL-Attributs (siehe unten) wird zwischen Groß- und Kleinschreibung unterschieden. Außerdem muss er mit dem in Ihren Lese- und Schreibvorgängen definierten Attribut übereinstimmen. Andernfalls werden abgelaufene Elemente nicht gelöscht. Um das TTL-Attribut umzubenennen, müssen Sie TTL zunächst deaktivieren und dann mit dem neuen Attribut aktivieren. TTL verarbeitet Löschungen etwa 30 Minuten lang weiter, nachdem es deaktiviert wurde. Bei wiederhergestellten Tabellen muss TTL neu konfiguriert werden.  
![\[TTL-Attributname mit Berücksichtigung von Groß- und Kleinschreibung, anhand dessen DynamoDB bestimmt, ob ein Element abläuft.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/EnableTTL-Settings.png)

1. (Optional) Sie können einen Test durchführen, indem Sie Datum und Uhrzeit des Ablaufs simulieren und einige Elemente abgleichen. Dadurch erhalten Sie eine Beispielliste mit Elementen, die bestätigt, dass es Elemente mit dem angegebenen TTL-Attributnamen und der Ablaufzeit gibt.

Nachdem TTL aktiviert wurde, wird das TTL-Attribut mit **TTL** gekennzeichnet, wenn Sie Elemente in der DynamoDB-Konsole ansehen. Sie können den Termin anzeigen, an dem ein Element abläuft, indem Sie mit dem Mauszeiger über das Attribut fahren. 

## Aktivieren von DynamoDB TTL mithilfe der API
<a name="time-to-live-ttl-how-to-enable-api"></a>

------
#### [ Python ]

Sie können TTL mithilfe des Vorgangs mit Code aktivieren. [UpdateTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/update_time_to_live.html)

```
import boto3


def enable_ttl(table_name, ttl_attribute_name):
    """
    Enables TTL on DynamoDB table for a given attribute name
        on success, returns a status code of 200
        on error, throws an exception

    :param table_name: Name of the DynamoDB table
    :param ttl_attribute_name: The name of the TTL attribute being provided to the table.
    """
    try:
        dynamodb = boto3.client('dynamodb')

        # Enable TTL on an existing DynamoDB table
        response = dynamodb.update_time_to_live(
            TableName=table_name,
            TimeToLiveSpecification={
                'Enabled': True,
                'AttributeName': ttl_attribute_name
            }
        )

        # In the returned response, check for a successful status code.
        if response['ResponseMetadata']['HTTPStatusCode'] == 200:
            print("TTL has been enabled successfully.")
        else:
            print(f"Failed to enable TTL, status code {response['ResponseMetadata']['HTTPStatusCode']}")
    except Exception as ex:
        print("Couldn't enable TTL in table %s. Here's why: %s" % (table_name, ex))
        raise


# your values
enable_ttl('your-table-name', 'expirationDate')
```

Sie können überprüfen, ob TTL aktiviert ist, indem Sie den [DescribeTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/describe_time_to_live.html)Vorgang verwenden, der den TTL-Status in einer Tabelle beschreibt. Der `TimeToLive`-Status ist entweder `ENABLED` oder `DISABLED`.

```
# create a DynamoDB client
dynamodb = boto3.client('dynamodb')

# set the table name
table_name = 'YourTable'

# describe TTL
response = dynamodb.describe_time_to_live(TableName=table_name)
```

------
#### [ JavaScript ]

Sie können TTL mithilfe des Vorgangs mit Code aktivieren. [UpdateTimeToLiveCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-dynamodb/Class/UpdateTimeToLiveCommand/)

```
import { DynamoDBClient, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";

const enableTTL = async (tableName, ttlAttribute) => {

    const client = new DynamoDBClient({});

    const params = {
        TableName: tableName,
        TimeToLiveSpecification: {
            Enabled: true,
            AttributeName: ttlAttribute
        }
    };

    try {
        const response = await client.send(new UpdateTimeToLiveCommand(params));
        if (response.$metadata.httpStatusCode === 200) {
            console.log(`TTL enabled successfully for table ${tableName}, using attribute name ${ttlAttribute}.`);
        } else {
            console.log(`Failed to enable TTL for table ${tableName}, response object: ${response}`);
        }
        return response;
    } catch (e) {
        console.error(`Error enabling TTL: ${e}`);
        throw e;
    }
};

// call with your own values
enableTTL('ExampleTable', 'exampleTtlAttribute');
```

------

## Aktivieren Sie Time to Live mit dem AWS CLI
<a name="time-to-live-ttl-how-to-enable-cli-sdk"></a>

1. Aktivieren Sie TTL in der `TTLExample`-Tabelle.

   ```
   aws dynamodb update-time-to-live --table-name TTLExample --time-to-live-specification "Enabled=true, AttributeName=ttl"
   ```

1. Beschreiben Sie TTL in der `TTLExample`-Tabelle.

   ```
   aws dynamodb describe-time-to-live --table-name TTLExample
   {
       "TimeToLiveDescription": {
           "AttributeName": "ttl",
           "TimeToLiveStatus": "ENABLED"
       }
   }
   ```

1. Fügen Sie der `TTLExample`-Tabelle mit dem Time-to-Live-Attributsatz ein Element mit der BASH-Shell und AWS CLI hinzu: 

   ```
   EXP=`date -d '+5 days' +%s`
   aws dynamodb put-item --table-name "TTLExample" --item '{"id": {"N": "1"}, "ttl": {"N": "'$EXP'"}}'
   ```

In diesem Beispiel wurde mit dem aktuellen Datum begonnen und es wurden 5 Tage hinzugefügt, um ein Ablaufdatum zu erstellen. Anschließend wird das Ablaufdatum in ein Epoch-Zeitformat umgewandelt, um der Tabelle "`TTLExample`" ein Element hinzuzufügen. 

**Anmerkung**  
 Eine Möglichkeit, Ablaufwerte für Time to Live festzulegen, besteht darin, die Anzahl von Sekunden zu berechnen, die dem Ablaufdatum hinzugefügt werden. Beispielsweise sind 5 Tage 432.000 Sekunden. Es ist jedoch häufig besser, mit einem Datum zu beginnen und dieses als Ausgangspunkt zu nehmen.

Es ist relativ einfach, die aktuelle Zeit im Epoch-Zeitformat zu erhalten, wie in folgenden Beispielen veranschaulicht.
+ Linux-Terminal: `date +%s`
+ Python: `import time; int(time.time())`
+ Java: `System.currentTimeMillis() / 1000L`
+ JavaScript: `Math.floor(Date.now() / 1000)`

## Aktivieren Sie DynamoDB TTL mit CloudFormation
<a name="time-to-live-ttl-how-to-enable-cf"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  TTLExampleTable:
    Type: AWS::DynamoDB::Table
    Description: "A DynamoDB table with TTL Specification enabled"
    Properties:
      AttributeDefinitions:
        - AttributeName: "Album"
          AttributeType: "S"
        - AttributeName: "Artist"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Album"
          KeyType: "HASH"
        - AttributeName: "Artist"
          KeyType: "RANGE"
      ProvisionedThroughput:
        ReadCapacityUnits: "5"
        WriteCapacityUnits: "5"
      TimeToLiveSpecification:
        AttributeName: "TTLExampleAttribute"
        Enabled: true
```

[Weitere Informationen zur Verwendung von TTL in Ihren CloudFormation Vorlagen finden Sie hier.](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html)

# Berechnen der Time to Live (TTL) in DynamoDB
<a name="time-to-live-ttl-before-you-start"></a>

Eine gängige Methode zur Implementierung von TTL besteht darin, eine Ablaufzeit für Elemente festzulegen, die auf dem Erstellungs- oder letzten Aktualisierungsdatum basiert. Dies kann durch Hinzufügen von Zeit zu den Zeitstempeln `createdAt` und `updatedAt` erreicht werden. Beispielsweise kann die TTL für neu erstellte Elemente auf `createdAt` \$1 90 Tage festgelegt werden. Wenn das Element aktualisiert wird, kann die TTL mit `updatedAt` \$1 90 Tage neu berechnet werden.

Die berechnete Ablaufzeit muss im Unix-Format in Sekunden angegeben werden. Damit Elemente für Ablauf und Löschung infrage kommen, darf die TTL nicht länger als fünf Jahre zurückliegen. Wenn Sie ein anderes Format verwenden, ignorieren die TTL-Prozesse das Element. Wenn Sie die Ablaufzeit auf einen Zeitpunkt in der future festlegen, an dem der Artikel ablaufen soll, läuft der Artikel nach dieser Zeit ab. Angenommen, Sie haben die Ablaufzeit auf 1724241326 festgelegt (das ist Montag, 21. August 2024 11:55:26 (UTC)). Der Artikel läuft nach der angegebenen Zeit ab. Es gibt keine TTL-Mindestdauer. Sie können die Ablaufzeit auf einen beliebigen Zeitpunkt in der future festlegen, z. B. auf 5 Minuten ab der aktuellen Uhrzeit. DynamoDB löscht abgelaufene Elemente jedoch in der Regel innerhalb von 48 Stunden nach deren Ablauf, nicht sofort, wenn der Artikel abläuft.

**Topics**
+ [Erstellen eines Elements und Festlegen der Time to Live](#time-to-live-ttl-before-you-start-create)
+ [Aktualisieren eines Elements und der Time to Live](#time-to-live-ttl-before-you-start-update)

## Erstellen eines Elements und Festlegen der Time to Live
<a name="time-to-live-ttl-before-you-start-create"></a>

Das folgende Beispiel zeigt, wie die Ablaufzeit berechnet wird, wenn ein neues Element erstellt wird. Dabei wird `expireAt` als TTL-Attributname verwendet. Eine Zuweisungsanweisung ruft die aktuelle Uhrzeit als Variable ab. In diesem Beispiel wird die Ablaufzeit als 90 Tage ab der aktuellen Uhrzeit berechnet. Die Zeit wird dann in das Unix-Format umgewandelt und als Ganzzahl-Datentyp im TTL-Attribut gespeichert.

Die folgenden Codebeispiele veranschaulichen, wie Sie ein Element mit TTL erstellen.

------
#### [ Java ]

**SDK für Java 2.x**  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * Creates an item in a DynamoDB table with TTL attributes.
 * This class demonstrates how to add TTL expiration timestamps to DynamoDB items.
 */
public class CreateTTL {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String CREATION_DATE_ATTR = "creationDate";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String SUCCESS_MESSAGE = "%s PutItem operation with TTL successful.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs a CreateTTL instance with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public CreateTTL(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Constructs a CreateTTL with a default DynamoDB client.
     */
    public CreateTTL() {
        this.dynamoDbClient = null;
    }

    /**
     * Main method to demonstrate creating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new CreateTTL().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and create an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final CreateTTL createTTL = new CreateTTL(ddb);
            createTTL.createItemWithTTL(tableName, primaryKey, sortKey);
            return 0;
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * Creates an item in the specified table with TTL attributes.
     *
     * @param tableName The name of the table
     * @param primaryKeyValue The value for the primary key
     * @param sortKeyValue The value for the sort key
     * @return The response from the PutItem operation
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     */
    public PutItemResponse createItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long createDate = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = createDate + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        final Map<String, AttributeValue> itemMap = new HashMap<>();
        itemMap.put(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        itemMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());
        itemMap.put(
            CREATION_DATE_ATTR,
            AttributeValue.builder().n(String.valueOf(createDate)).build());
        itemMap.put(
            EXPIRE_AT_ATTR,
            AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final PutItemRequest request =
            PutItemRequest.builder().tableName(tableName).item(itemMap).build();

        try {
            final PutItemResponse response = dynamoDbClient.putItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  *Einzelheiten zur API finden Sie unter [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)API-Referenz.AWS SDK for Java 2.x * 

------
#### [ JavaScript ]

**SDK für JavaScript (v3)**  

```
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";

export function createDynamoDBItem(table_name, region, partition_key, sort_key) {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    // Get the current time in epoch second format
    const current_time = Math.floor(new Date().getTime() / 1000);

    // Calculate the expireAt time (90 days from now) in epoch second format
    const expire_at = Math.floor((new Date().getTime() + 90 * 24 * 60 * 60 * 1000) / 1000);

    // Create DynamoDB item
    const item = {
        'partitionKey': {'S': partition_key},
        'sortKey': {'S': sort_key},
        'createdAt': {'N': current_time.toString()},
        'expireAt': {'N': expire_at.toString()}
    };

    const putItemCommand = new PutItemCommand({
        TableName: table_name,
        Item: item,
        ProvisionedThroughput: {
            ReadCapacityUnits: 1,
            WriteCapacityUnits: 1,
        },
    });

    client.send(putItemCommand, function(err, data) {
        if (err) {
            console.log("Exception encountered when creating item %s, here's what happened: ", data, err);
            throw err;
        } else {
            console.log("Item created successfully: %s.", data);
            return data;
        }
    });
}

// Example usage (commented out for testing)
// createDynamoDBItem('your-table-name', 'us-east-1', 'your-partition-key-value', 'your-sort-key-value');
```
+  Einzelheiten zur API finden Sie [PutItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/PutItemCommand)in der *AWS SDK für JavaScript API-Referenz*. 

------
#### [ Python ]

**SDK für Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def create_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Creates a DynamoDB item with an attached expiry attribute.

    :param table_name: Table name for the boto3 resource to target when creating an item
    :param region: string representing the AWS region. Example: `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :return: Void (nothing)
    """
    try:
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expiration time (90 days from now) in epoch second format
        expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())

        item = {
            "primaryKey": primary_key,
            "sortKey": sort_key,
            "creationDate": current_time,
            "expireAt": expiration_time,
        }
        response = table.put_item(Item=item)

        print("Item created successfully.")
        return response
    except Exception as e:
        print(f"Error creating item: {e}")
        raise e


# Use your own values
create_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Einzelheiten zur API finden Sie [PutItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/PutItem)in *AWS SDK for Python (Boto3) API* Reference. 

------

## Aktualisieren eines Elements und der Time to Live
<a name="time-to-live-ttl-before-you-start-update"></a>

Dies ist eine Fortsetzung des Beispiels aus dem [vorherigen Abschnitt](#time-to-live-ttl-before-you-start-create). Die Ablaufzeit kann neu berechnet werden, wenn das Element aktualisiert wird. Im folgenden Beispiel wird der Zeitstempel `expireAt` neu berechnet, sodass er 90 Tage nach der aktuellen Uhrzeit liegt.

Die folgenden Codebeispiele veranschaulichen, wie Sie die TTL eines Elements aktualisieren.

------
#### [ Java ]

**SDK für Java 2.x**  
Aktualisieren Sie die TTL für ein vorhandenes DynamoDB-Element in einer Tabelle.  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

    public UpdateItemResponse updateItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = new HashMap<>();
        keyMap.put(PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        keyMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build());
        expressionAttributeValues.put(
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try {
            final UpdateItemResponse response = dynamoDbClient.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
```
+  Einzelheiten zur API finden Sie unter [UpdateItem AWS SDK for Java 2.x](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)*API-Referenz*. 

------
#### [ JavaScript ]

**SDK für JavaScript (v3)**  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItem = async (tableName, partitionKey, sortKey, region = 'us-east-1') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);
    const expireAt = Math.floor((Date.now() + 90 * 24 * 60 * 60 * 1000) / 1000);

    const params = {
        TableName: tableName,
        Key: marshall({
            partitionKey: partitionKey,
            sortKey: sortKey
        }),
        UpdateExpression: "SET updatedAt = :c, expireAt = :e",
        ExpressionAttributeValues: marshall({
            ":c": currentTime,
            ":e": expireAt
        }),
    };

    try {
        const data = await client.send(new UpdateItemCommand(params));
        const responseData = unmarshall(data.Attributes);
        console.log("Item updated successfully: %s", responseData);
        return responseData;
    } catch (err) {
        console.error("Error updating item:", err);
        throw err;
    }
}

// Example usage (commented out for testing)
// updateItem('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Einzelheiten zur API finden Sie [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)in der *AWS SDK für JavaScript API-Referenz*. 

------
#### [ Python ]

**SDK für Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def update_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Update an existing DynamoDB item with a TTL.
    :param table_name: Name of the DynamoDB table
    :param region: AWS Region of the table - example `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :return: Void (nothing)
    """
    try:
        # Create the DynamoDB resource.
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expireAt time (90 days from now) in epoch second format
        expire_at = int((datetime.now() + timedelta(days=90)).timestamp())

        table.update_item(
            Key={"partitionKey": primary_key, "sortKey": sort_key},
            UpdateExpression="set updatedAt=:c, expireAt=:e",
            ExpressionAttributeValues={":c": current_time, ":e": expire_at},
        )

        print("Item updated successfully.")
    except Exception as e:
        print(f"Error updating item: {e}")


# Replace with your own values
update_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Einzelheiten zur API finden Sie [UpdateItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)in *AWS SDK for Python (Boto3) API* Reference. 

------

Die in dieser Einführung vorgestellten TTL-Beispiele sind ein Weg, um sicherzustellen, dass nur kürzlich aktualisierte Elemente in einer Tabelle gespeichert bleiben. Die Lebensdauer aktualisierter Elemente wird verlängert, wohingegen Elemente, die seit ihrer Erstellung nicht mehr aktualisiert wurden, ablaufen und kostenlos gelöscht werden. So wird Speicherplatz reduziert und die Tabellen werden auf dem neuesten Stand gehalten.

# Arbeiten mit abgelaufenen Elementen und Time to Live (TTL)
<a name="ttl-expired-items"></a>

Abgelaufene Elemente, deren Löschung noch aussteht, können aus Lese- und Schreibvorgängen herausgefiltert werden. Dies ist nützlich in Szenarien, in denen abgelaufene Daten nicht mehr gültig sind und nicht verwendet werden sollten. Wenn sie nicht gefiltert werden, werden sie weiterhin bei Lese- und Schreibvorgängen angezeigt, bis sie vom Hintergrundprozess gelöscht werden.

**Anmerkung**  
Diese Elemente werden weiterhin auf die Speicher- und Lesekosten angerechnet, bis sie gelöscht werden.

TTL-Löschungen können in DynamoDB Streams identifiziert werden, jedoch nur in der Region, in der die Löschung stattgefunden hat. TTL-Löschungen, die in globale Tabellenbereiche repliziert werden, sind in DynamoDB-Streams in den Regionen, in die die Löschung repliziert wurde, nicht identifizierbar.

## Filtern abgelaufener Elemente aus Lesevorgängen
<a name="ttl-expired-items-filter"></a>

Bei Lesevorgängen wie [Scan](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) und [Abfrage](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) kann ein Filterausdruck abgelaufene Elemente herausfiltern, deren Löschung noch aussteht. Wie im folgenden Codeausschnitt gezeigt, kann der Filterausdruck Elemente herausfiltern, bei denen die TTL-Zeit gleich oder kleiner als die aktuelle Zeit ist. Der Python-SDK-Code enthält beispielsweise eine Zuweisungsanweisung, die die aktuelle Uhrzeit als Variable (`now`) abruft und sie in `int` für das Unix-Zeitformat konvertiert.

In den folgenden Codebeispielen wird gezeigt, wie TTL-Elemente abgefragt werden.

------
#### [ Java ]

**SDK für Java 2.x**  
Abfragen eines gefilterten Ausdrucks zum Sammeln von TTL-Elementen in einer DynamoDB-Tabelle mithilfe von. AWS SDK for Java 2.x  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.Map;
import java.util.Optional;

        final QueryRequest request = QueryRequest.builder()
            .tableName(tableName)
            .keyConditionExpression(KEY_CONDITION_EXPRESSION)
            .filterExpression(FILTER_EXPRESSION)
            .expressionAttributeNames(expressionAttributeNames)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final QueryResponse response = ddb.query(request);
            System.out.println("Query successful. Found " + response.count() + " items that have not expired yet.");

            // Print each item
            response.items().forEach(item -> {
                System.out.println("Item: " + item);
            });

            return 0;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
```
+  Weitere API-Informationen finden Sie unter [Abfragen](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/Query) in der *AWS SDK for Java 2.x -API-Referenz*. 

------
#### [ JavaScript ]

**SDK für JavaScript (v3)**  
Abfragen eines gefilterten Ausdrucks zum Sammeln von TTL-Elementen in einer DynamoDB-Tabelle mithilfe von. AWS SDK für JavaScript  

```
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const queryFiltered = async (tableName, primaryKey, region = 'us-east-1') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);

    const params = {
        TableName: tableName,
        KeyConditionExpression: "#pk = :pk",
        FilterExpression: "#ea > :ea",
        ExpressionAttributeNames: {
            "#pk": "primaryKey",
            "#ea": "expireAt"
        },
        ExpressionAttributeValues: marshall({
            ":pk": primaryKey,
            ":ea": currentTime
        })
    };

    try {
        const { Items } = await client.send(new QueryCommand(params));
        Items.forEach(item => {
            console.log(unmarshall(item))
        });
        return Items;
    } catch (err) {
        console.error(`Error querying items: ${err}`);
        throw err;
    }
}

// Example usage (commented out for testing)
// queryFiltered('your-table-name', 'your-partition-key-value');
```
+  Weitere API-Informationen finden Sie unter [Abfragen](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/QueryCommand) in der *AWS SDK für JavaScript -API-Referenz*. 

------
#### [ Python ]

**SDK für Python (Boto3)**  
Abfragen eines gefilterten Ausdrucks zum Sammeln von TTL-Elementen in einer DynamoDB-Tabelle mithilfe von. AWS SDK für Python (Boto3)  

```
from datetime import datetime

import boto3


def query_dynamodb_items(table_name, partition_key):
    """

    :param table_name: Name of the DynamoDB table
    :param partition_key:
    :return:
    """
    try:
        # Initialize a DynamoDB resource
        dynamodb = boto3.resource("dynamodb", region_name="us-east-1")

        # Specify your table
        table = dynamodb.Table(table_name)

        # Get the current time in epoch format
        current_time = int(datetime.now().timestamp())

        # Perform the query operation with a filter expression to exclude expired items
        # response = table.query(
        #    KeyConditionExpression=boto3.dynamodb.conditions.Key('partitionKey').eq(partition_key),
        #    FilterExpression=boto3.dynamodb.conditions.Attr('expireAt').gt(current_time)
        # )
        response = table.query(
            KeyConditionExpression=dynamodb.conditions.Key("partitionKey").eq(partition_key),
            FilterExpression=dynamodb.conditions.Attr("expireAt").gt(current_time),
        )

        # Print the items that are not expired
        for item in response["Items"]:
            print(item)

    except Exception as e:
        print(f"Error querying items: {e}")


# Call the function with your values
query_dynamodb_items("Music", "your-partition-key-value")
```
+  Weitere API-Informationen finden Sie unter [Abfragen](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/Query) in der *API-Referenz zum AWS  SDK für Python (Boto3)*. 

------

## Bedingtes Schreiben in abgelaufene Elemente
<a name="ttl-expired-items-conditional-write"></a>

Ein Bedingungsausdruck kann verwendet werden, um Schreibvorgänge auf abgelaufene Elemente zu verhindern. Der folgende Codeausschnitt ist eine bedingte Aktualisierung, die prüft, ob die Ablaufzeit nach der aktuellen Zeit liegt. Falls ja, wird der Schreibvorgang fortgesetzt.

In den folgenden Codebeispielen wird gezeigt, wie die TTL eines Elements bedingungsabhängig aktualisiert wird.

------
#### [ Java ]

**SDK für Java 2.x**  
Aktualisieren Sie die TTL für ein vorhandenes DynamoDB-Element in einer Tabelle mit einer Bedingung.  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.Map;
import java.util.Optional;

/**
 * Updates an item in a DynamoDB table with TTL attributes using a conditional expression.
 * This class demonstrates how to conditionally update TTL expiration timestamps.
 */
public class UpdateTTLConditional {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String UPDATED_AT_ATTR = "updatedAt";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String UPDATE_EXPRESSION = "SET " + UPDATED_AT_ATTR + "=:c, " + EXPIRE_AT_ATTR + "=:e";
    private static final String CONDITION_EXPRESSION = "attribute_exists(" + PRIMARY_KEY_ATTR + ")";
    private static final String SUCCESS_MESSAGE = "%s UpdateItem operation with TTL successful.";
    private static final String CONDITION_FAILED_MESSAGE = "Condition check failed. Item does not exist.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs an UpdateTTLConditional with a default DynamoDB client.
     */
    public UpdateTTLConditional() {
        this.dynamoDbClient = null;
    }

    /**
     * Constructs an UpdateTTLConditional with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public UpdateTTLConditional(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Main method to demonstrate conditionally updating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new UpdateTTLConditional().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and conditionally update an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = Map.of(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKey).build(),
            SORT_KEY_ATTR, AttributeValue.builder().s(sortKey).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = Map.of(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build(),
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .conditionExpression(CONDITION_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final UpdateItemResponse response = ddb.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return 0;
        } catch (ConditionalCheckFailedException e) {
            System.err.println(CONDITION_FAILED_MESSAGE);
            throw e;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  *Einzelheiten zur API finden Sie unter [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)API-Referenz.AWS SDK for Java 2.x * 

------
#### [ JavaScript ]

**SDK für JavaScript (v3)**  
Aktualisieren Sie die TTL für ein vorhandenes DynamoDB-Element in einer Tabelle mit einer Bedingung.  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItemConditional = async (tableName, partitionKey, sortKey, region = 'us-east-1', newAttribute = 'default-value') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);

    const params = {
        TableName: tableName,
        Key: marshall({
            artist: partitionKey,
            album: sortKey
        }),
        UpdateExpression: "SET newAttribute = :newAttribute",
        ConditionExpression: "expireAt > :expiration",
        ExpressionAttributeValues: marshall({
            ':newAttribute': newAttribute,
            ':expiration': currentTime
        }),
        ReturnValues: "ALL_NEW"
    };

    try {
        const response = await client.send(new UpdateItemCommand(params));
        const responseData = unmarshall(response.Attributes);
        console.log("Item updated successfully: ", responseData);
        return responseData;
    } catch (error) {
        if (error.name === "ConditionalCheckFailedException") {
            console.log("Condition check failed: Item's 'expireAt' is expired.");
        } else {
            console.error("Error updating item: ", error);
        }
        throw error;
    }
};

// Example usage (commented out for testing)
// updateItemConditional('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Einzelheiten zur API finden Sie [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)in der *AWS SDK für JavaScript API-Referenz*. 

------
#### [ Python ]

**SDK für Python (Boto3)**  
Aktualisieren Sie die TTL für ein vorhandenes DynamoDB-Element in einer Tabelle mit einer Bedingung.  

```
from datetime import datetime, timedelta

import boto3
from botocore.exceptions import ClientError


def update_dynamodb_item_ttl(table_name, region, primary_key, sort_key, ttl_attribute):
    """
    Updates an existing record in a DynamoDB table with a new or updated TTL attribute.

    :param table_name: Name of the DynamoDB table
    :param region: AWS Region of the table - example `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :param ttl_attribute: name of the TTL attribute in the target DynamoDB table
    :return:
    """
    try:
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Generate updated TTL in epoch second format
        updated_expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())

        # Define the update expression for adding/updating a new attribute
        update_expression = "SET newAttribute = :val1"

        # Define the condition expression for checking if 'expireAt' is not expired
        condition_expression = "expireAt > :val2"

        # Define the expression attribute values
        expression_attribute_values = {":val1": ttl_attribute, ":val2": updated_expiration_time}

        response = table.update_item(
            Key={"primaryKey": primary_key, "sortKey": sort_key},
            UpdateExpression=update_expression,
            ConditionExpression=condition_expression,
            ExpressionAttributeValues=expression_attribute_values,
        )

        print("Item updated successfully.")
        return response["ResponseMetadata"]["HTTPStatusCode"]  # Ideally a 200 OK
    except ClientError as e:
        if e.response["Error"]["Code"] == "ConditionalCheckFailedException":
            print("Condition check failed: Item's 'expireAt' is expired.")
        else:
            print(f"Error updating item: {e}")
    except Exception as e:
        print(f"Error updating item: {e}")


# replace with your values
update_dynamodb_item_ttl(
    "your-table-name",
    "us-east-1",
    "your-partition-key-value",
    "your-sort-key-value",
    "your-ttl-attribute-value",
)
```
+  Einzelheiten zur API finden Sie [UpdateItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)in *AWS SDK for Python (Boto3) API* Reference. 

------

## Identifizieren gelöschter Elemente in DynamoDB Streams
<a name="ttl-expired-items-identifying"></a>

Der Stream-Datensatz enthält ein Benutzeridentitätsfeld `Records[<index>].userIdentity`. Elemente, die durch den TTL-Prozess gelöscht wurden, haben die folgenden Felder:

```
Records[<index>].userIdentity.type
"Service"

Records[<index>].userIdentity.principalId
"dynamodb.amazonaws.com"
```

Der folgende JSON-Ausdruck zeigt den relevanten Teil eines einzelnen Stream-Datensatzes:

```
"Records": [ 
  { 
	... 
		"userIdentity": {
		"type": "Service", 
      	"principalId": "dynamodb.amazonaws.com" 
   	} 
   ... 
	} 
]
```

# Abfragen von Tabellen in DynamoDB
<a name="Query"></a>

Sie können die `Query`–API-Operation in Amazon DynamoDB verwenden, um Elemente auf der Basis von Primärschlüsselwerten zu finden.

Sie müssen den Namen des Partitionsschlüsselattributs und einen einzelnen Wert für dieses Attribut angeben. `Query` gibt alle Elemente mit diesem Partitionsschlüsselwert zurück. Sie können optional ein Sortierschlüsselattribut angeben und einen Vergleichsoperator verwenden, um die Suchergebnisse zu verfeinern.

Weitere Informationen zur Verwendung von `Query`, wie beispielsweise die Anforderungssyntax, Antwortparameter und zusätzliche Beispiele, finden Sie unter [Abfragen](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html) in der *API-Referenz zu Amazon DynamoDB*.

**Topics**
+ [Schlüsselbedingungsausdrücke für die Abfrage-Operation in DynamoDB](Query.KeyConditionExpressions.md)
+ [Filterausdrücke für die Abfrage-Operation in DynamoDB](Query.FilterExpression.md)
+ [Paginieren von Tabellenabfrageergebnissen in DynamoDB](Query.Pagination.md)
+ [Weitere Aspekte der Arbeit mit der Abfrage-Operation in DynamoDB](Query.Other.md)

# Schlüsselbedingungsausdrücke für die Abfrage-Operation in DynamoDB
<a name="Query.KeyConditionExpressions"></a>

Sie können alle Attributnamen in einem Schlüsselbedingungsausdruck verwenden, sofern das erste Zeichen `a-z` oder `A-Z` ist und die übrigen Zeichen (ab dem zweiten Zeichen, sofern vorhanden) `a-z`, `A-Z` oder `0-9` sind. Darüber hinaus müssen die Attributnamen nicht DynamoDB-reservierte Wörter sein. (Eine vollständige Liste finden Sie unter [Reservierte Wörter in DynamoDB](ReservedWords.md).) Wenn ein Attributname diesen Anforderungen nicht entspricht, müssen Sie einen Ausdruckattributnamen als Platzhalter definieren. Weitere Informationen finden Sie unter [Ausdrucksattributnamen (Aliasse) in DynamoDB](Expressions.ExpressionAttributeNames.md).

Für Objekte, die mit einem bestimmten Partitionsschlüsselwert versehen sind, speichert DynamoDB diese Elemente nah beieinander, sortiert nach Sortierschlüsselwerten. In einer `Query`-Operation ruft DynamoDB die Elemente sortiert ab und verarbeitet dann die Elemente mit `KeyConditionExpression` und allen `FilterExpression`, die möglicherweise vorhanden sind. Nur dann werden die `Query`-Ergebnisse an den Client zurückgesendet.

Die `Query`-Operation gibt immer eine Ergebnismenge zurück. Wenn keine übereinstimmenden Elemente gefunden werden, ist die Ergebnismenge leer.

`Query`-Ergebnisse werden immer von dem Sortierschlüsselwert sortiert. Wenn der Datentyp des Sortierschlüssels als `Number` festgelegt ist, werden die Ergebnisse in der numerischen Reihenfolge zurückgegeben. Andernfalls werden die Ergebnisse in der Reihenfolge der UTF-8-Bytes zurückgegeben. Standardmäßig ist die Sortierreihenfolge aufsteigend. Um die Reihenfolge umzukehren, setzen Sie den Parameter `ScanIndexForward` auf `false`.

Eine einzelne `Query`-Operation kann bis zu 1 MB an Daten abrufen. Diese Größenbeschränkung gilt, bevor ein `FilterExpression` oder `ProjectionExpression` den Ergebnissen zugeordnet wird. Wenn `LastEvaluatedKey` in der Antwort vorhanden ist und nicht Null ist, müssen Sie die Ergebnismenge wechseln (siehe [Paginieren von Tabellenabfrageergebnissen in DynamoDB](Query.Pagination.md)).

## Beispiele für Schlüsselbedingungsausdrücke
<a name="Query.KeyConditionExpressions-example"></a>

Wenn Sie Suchkriterien angeben, verwenden Sie einen *Schlüsselbedingungsausdruck* – eine Zeichenkette, die die Elemente bestimmt, die von der Tabelle oder dem Index gelesen werden müssen.

Sie müssen den Namen und Wert des Partitionsschlüssels als Gleichheitsbedingung angeben. Sie können kein Nicht-Schlüssel-Attribut in einem Schlüsselbedingungsausdruck verwenden.

Sie können optional eine zweite Bedingung für den Sortierschlüssel (sofern vorhanden) angeben. Die Bedingung des Sortierschlüssels muss einen der folgenden Vergleichsoperatoren verwenden:
+ `a = b`— wahr, wenn *a* das Attribut dem Wert entspricht *b*
+ `a < b`— wahr, wenn *a* es kleiner ist als *b*
+ `a <= b`— wahr, wenn kleiner oder gleich *a* ist *b*
+ `a > b`— wahr, wenn größer *a* ist als *b*
+ `a >= b`— wahr, wenn größer oder gleich *a* ist *b*
+ `a BETWEEN b AND c`— wahr, wenn größer als oder gleich *b* und kleiner als oder gleich *a* ist*c*.

Folgende Funktionen werden ebenfalls unterstützt:
+ `begins_with (a, substr)` – True, wenn der Wert von Attribut `a` mit einer bestimmten Teilkettenfolge beginnt.

Die folgenden Beispiele AWS Command Line Interface (AWS CLI) veranschaulichen die Verwendung von Ausdrücken für Schlüsselbedingungen. Diese Ausdrücke verwenden Platzhalter (z. B. `:name` und `:sub`) anstelle tatsächlicher Werte. Weitere Informationen erhalten Sie unter [Ausdrucksattributnamen (Aliasse) in DynamoDB](Expressions.ExpressionAttributeNames.md) und [Verwenden von Ausdrucksattributwerten in DynamoDB](Expressions.ExpressionAttributeValues.md).

**Example**  
Fragen Sie die `Thread`-Tabelle nach einem bestimmten `ForumName` (Partitionsschlüssel) ab. Alle Elemente mit diesem `ForumName`-Wert werden von der Abfrage gelesen, da der Sortierschlüssel (`Subject`) in `KeyConditionExpression` nicht enthalten ist.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name" \
    --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
```

**Example**  
Fragen Sie die `Thread`-Tabelle nach einem bestimmten `ForumName` (Partitions-Schlüssel) ab, aber dieses Mal geben Sie nur die Elemente mit einem bestimmten `Subject` (Sortierschlüssel) zurück.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name and Subject = :sub" \
    --expression-attribute-values  file://values.json
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":name":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"}
}
```

**Example**  
Fragen Sie die `Reply`-Tabelle nach einer bestimmten `Id` (Partitionsschlüssel) ab, aber geben Sie nur die Elemente zurück, deren `ReplyDateTime` (Sortierschlüssel) mit bestimmten Zeichen beginnt.  

```
aws dynamodb query \
    --table-name Reply \
    --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
    --expression-attribute-values  file://values.json
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
    ":dt":{"S":"2015-09"}
}
```

# Filterausdrücke für die Abfrage-Operation in DynamoDB
<a name="Query.FilterExpression"></a>

Wenn Sie die `Query`-Ergebnisse weiter eingrenzen müssen, können Sie optional einen Filterausdruck angeben. Ein *Filterausdruck* bestimmt, welche Elemente in den `Query`-Ergebnissen an Sie zurückgegeben werden. Alle anderen Ergebnisse werden verworfen.

Ein Filterausdruck wird angewendet, nachdem eine `Query` abgeschlossen ist, aber bevor die Ergebnisse zurückgegeben werden. Folglich verbraucht eine `Query` unabhängig davon, ob ein Filterausdruck vorhanden ist oder nicht, gleich viel Lesekapazität.

Eine `Query`-Operation kann bis zu 1 MB an Daten abrufen. Diese Größenbeschränkung gilt, bevor der Filterausdruck ausgewertet wird.

Ein Filterausdruck darf keine Partitionsschlüssel- oder Sortierschlüsselattribute enthalten. Sie müssen diese Attribute in dem Schlüsselbedingungsausdruck und nicht in dem Filterausdruck angeben.

Die Syntax für einen Filterausdruck ist der eines Schlüsselbedingungsausdrucks ähnlich. Filterausdrücke können dieselben Vergleichsoperatoren, Funktionen und logischen Operatoren wie ein Schlüsselbedingungsausdruck verwenden. Darüber hinaus können Filterausdrücke den Nicht-Gleichheitsoperator (`<>`), den`OR`-Operator, den`CONTAINS`-Operator, den `IN`-Operator, den `BEGINS_WITH`-Operator, den `BETWEEN`-Operator, den `EXISTS`-Operator und den`SIZE`-Operator verwenden. Weitere Informationen erhalten Sie unter [Schlüsselbedingungsausdrücke für die Abfrage-Operation in DynamoDB](Query.KeyConditionExpressions.md) und [Syntax für Filter- und Bedingungsausdrücke](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Syntax).

**Example**  
Im folgenden AWS CLI Beispiel wird die `Thread` Tabelle nach einem bestimmten `ForumName` (Partitionsschlüssel) und `Subject` (Sortierschlüssel) abgefragt. Von den gefundenen Elementen werden nur die beliebtesten Diskussionsthreads zurückgegeben, also nur die Threads mit mehr als einer bestimmten Anzahl von `Views`.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :fn and Subject begins_with :sub" \
    --filter-expression "#v >= :num" \
    --expression-attribute-names '{"#v": "Views"}' \
    --expression-attribute-values file://values.json
```
Die Argumente für `--expression-attribute-values` werden in der Datei `values.json` gespeichert.  

```
{
    ":fn":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"},
    ":num":{"N":"3"}
}
```
Beachten Sie, dass `Views` ein reserviertes Wort in DynamoDB ist (siehe [Reservierte Wörter in DynamoDB](ReservedWords.md)), daher verwendet dieses Beispiel `#v` als Platzhalter. Weitere Informationen finden Sie unter [Ausdrucksattributnamen (Aliasse) in DynamoDB](Expressions.ExpressionAttributeNames.md).

**Anmerkung**  
Ein Filterausdruck entfernt Elemente aus der `Query`-Ergebnismenge. Verwenden Sie nach Möglichkeit `Query` nicht, wenn Sie erwarten, eine große Anzahl von Elementen abzurufen, jedoch auch die meisten dieser Elemente verwerfen zu müssen.

# Paginieren von Tabellenabfrageergebnissen in DynamoDB
<a name="Query.Pagination"></a>

DynamoDB *paginiert* die Ergebnisse von `Query`-Operationen. Bei der Paginierung werden die `Query`-Ergebnisse in „Seiten“ mit Daten von einer Größe von 1 MB (oder weniger) unterteilt. Eine Anwendung kann die erste Ergebnisseite verarbeiten, dann die zweite Seite und so weiter.

Eine einzelne `Query` gibt nur einen Ergebnissatz zurück, der innerhalb des Grenzwerts von 1 MB liegt. Um zu bestimmen, ob es mehr Ergebnisse gibt, und diese seitenweise abzurufen, sollte eine Anwendung die folgenden Schritte ausführen: 

1. Überprüfen Sie das `Query`-Low-Level-Ergebnis:
   + Wenn das Ergebnis ein `LastEvaluatedKey`-Element enthält und es ist ungleich null, fahren Sie mit Schritt 2 fort.
   + Wenn im Ergebnis *kein* `LastEvaluatedKey` vorhanden ist, sind keine Elemente mehr zum Abrufen vorhanden.

1. Erstellen Sie eine `Query` mit demselben `KeyConditionExpression`. Verwenden Sie jedoch dieses Mal den `LastEvaluatedKey`-Wert aus Schritt 1 als `ExclusiveStartKey`-Parameter in der neuen `Query`-Anforderung.

1. Führen Sie die neue `Query`-Anforderung aus.

1. Fahren Sie mit Schritt 1 fort.

Mit anderen Worten: Der `LastEvaluatedKey` einer `Query`-Antwort sollte als `ExclusiveStartKey` für die nächste `Query`-Anforderung verwendet werden. Wenn in einer `LastEvaluatedKey`-Antwort kein `Query`-Element vorhanden ist, haben Sie die letzte Ergebnisseite abgerufen. Wenn `LastEvaluatedKey` nicht leer ist, bedeutet dies nicht notwendigerweise, dass die Ergebnismenge mehr Daten enthält. Die einzige Möglichkeit zu erfahren, dass das Ende des Ergebnissatzes erreicht wurde, ist, dass `LastEvaluatedKey` leer ist.

Sie können das verwenden AWS CLI , um sich dieses Verhalten anzusehen. Der AWS CLI sendet wiederholt `Query` Anfragen auf niedriger Ebene an DynamoDB, bis er in den Ergebnissen nicht mehr vorhanden `LastEvaluatedKey` ist. Betrachten Sie das folgende AWS CLI Beispiel, in dem Filmtitel aus einem bestimmten Jahr abgerufen werden.

```
aws dynamodb query --table-name Movies \
    --projection-expression "title" \
    --key-condition-expression "#y = :yyyy" \
    --expression-attribute-names '{"#y":"year"}' \
    --expression-attribute-values '{":yyyy":{"N":"1993"}}' \
    --page-size 5 \
    --debug
```

Normalerweise AWS CLI verarbeitet der die Seitennummerierung automatisch. In diesem Beispiel begrenzt der AWS CLI `--page-size` Parameter jedoch die Anzahl der Elemente pro Seite. Der `--debug`-Parameter gibt Low-Level-Informationen zu Anforderungen und Antworten aus.

Wenn Sie das Beispiel ausführen, sieht die erste Antwort von DynamoDB ungefähr folgendermaßen aus.

```
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'
```

Der `LastEvaluatedKey` in der Antwort gibt an, dass nicht alle Elemente abgerufen wurden. Das sendet AWS CLI dann eine weitere `Query` Anfrage an DynamoDB. Dieses Anforderungs- und Antwortmuster wird bis zur endgültigen Antwort fortgesetzt.

```
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'
```

Das Fehlen von `LastEvaluatedKey` gibt an, dass keine abrufbaren Elemente mehr vorhanden sind.

**Anmerkung**  
Sie AWS SDKs verarbeiten DynamoDB-Antworten auf niedriger Ebene (einschließlich des Vorhandenseins oder Fehlens von`LastEvaluatedKey`) und bieten verschiedene Abstraktionen für die Paginierung von Ergebnissen. `Query` Beispielsweise stellt SDK für die Java-Dokumentschnittstelle `java.util.Iterator`-Unterstützung bereit, sodass Sie die Ergebnisse nacheinander durchgehen können.  
Codebeispiele in verschiedenen Programmiersprachen finden Sie im [Amazon-DynamoDB-Handbuch für erste Schritte](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/) und in der AWS SDK-Dokumentation für Ihre Sprache.

Sie können die Seitengröße auch reduzieren, indem Sie die Anzahl der Elemente in der Ergebnismenge mit dem `Limit`-Parameter der`Query`-Operation verwenden.

Weitere Informationen zur Verwendung der Abfrage mit DynamoDB finden Sie unter [Abfragen von Tabellen in DynamoDB](Query.md).

# Weitere Aspekte der Arbeit mit der Abfrage-Operation in DynamoDB
<a name="Query.Other"></a>

In diesem Abschnitt werden weitere Aspekte der DynamoDB-Abfrageoperation behandelt, darunter die Beschränkung der Ergebnisgröße, das Zählen gescannter gegenüber zurückgegebener Elemente, die Überwachung des Lesekapazitätsverbrauchs und die Steuerung der Lesekonsistenz.

## Begrenzung der Anzahl an Elementen in der Ergebnismenge
<a name="Query.Limit"></a>

Die `Query`-Operation ermöglicht Ihnen, die Anzahl der Elemente einzuschränken, die gelesen werden. Legen Sie dazu den Parameter `Limit` auf die maximale Anzahl Elemente fest, die zurückgegeben werden sollen.

Beispiel: Sie führen eine `Query` für eine Tabelle mit einem `Limit`-Wert von `6` und ohne Filterausdruck durch. Das `Query`-Ergebnis enthält die ersten sechs Elemente der Tabelle, die mit dem Schlüsselbedingungsausdruck der Anforderung übereinstimmen.

Angenommen, Sie fügen nun einen Filterausdruck der `Query` hinzu. In diesem Fall liest DynamoDB bis zu sechs Elemente und gibt dann nur diejenigen zurück, die mit dem Filterausdruck übereinstimmen. Das `Query`-Endergebnis enthält sechs oder weniger Elemente, selbst wenn mehr Elemente mit dem Filterausdruck übereinstimmen würden, wenn DynamoDB weitere Elemente gelesen hätte.

## Zählen der Elemente in den Ergebnissen
<a name="Query.Count"></a>

Zusätzlich zu den Elementen, die mit Ihren Kriterien übereinstimmen, enthält die `Query`-Antwort noch die folgenden Elemente:
+ `ScannedCount` – die Anzahl der Elemente, die mit dem Schlüsselbedingungsausdruck übereinstimmten, *bevor* ein Filterausdruck (falls vorhanden) angewendet wurde.
+ `Count` – die Anzahl der Elemente, die verbleiben, *nachdem* ein Filterausdruck (falls vorhanden) angewendet wurde.

**Anmerkung**  
Wenn Sie keinen Filterausdruck verwenden, haben `ScannedCount` und `Count` den gleichen Wert.

Wenn der `Query`-Ergebnissatz größer als 1 MB ist, repräsentieren `ScannedCount` und `Count` nur eine Teilmenge der Gesamtelemente. Sie müssen mehrere `Query`-Operationen ausführen, um alle Ergebnisse abzurufen (siehe [Paginieren von Tabellenabfrageergebnissen in DynamoDB](Query.Pagination.md)).

Jede `Query`-Antwort enthält die `ScannedCount` und `Count` für die Elemente, die von der betreffenden `Query`-Anforderung verarbeitet wurden. Um eine Gesamtsumme für alle `Query`-Anforderungen zu erhalten, könnten Sie eine laufende Zählung der Werte `ScannedCount` und `Count` vornehmen.

## Durch die Abfrage verbrauchte Kapazitätseinheiten
<a name="Query.CapacityUnits"></a>

Sie können `Query` für jede Tabelle oder jeden sekundären Index verwenden, sofern Sie den Namen des Partitionsschlüsselattributs und einen einzelnen Wert für dieses Attribut angeben. `Query` gibt alle Elemente mit diesem Partitionsschlüsselwert zurück. Sie können optional ein Sortierschlüsselattribut angeben und einen Vergleichsoperator verwenden, um die Suchergebnisse zu verfeinern. `Query` API-Operationen verbrauchen Lesekapazitätseinheiten wie folgt.


****  

| Wenn Sie `Query` eine ... | DynamoDB verbraucht Lesekapazitätseinheiten von ... | 
| --- | --- | 
| Tabelle | Die bereitgestellte Lesekapazität der Tabelle. | 
| Globaler sekundärer Index | Die bereitgestellte Lesekapazität des Index. | 
| Lokaler sekundärer Index | Die bereitgestellte Lesekapazität der Basistabelle. | 

Standardmäßig gibt eine `Query`-Operation keine Daten über seinen Lesekapazitätsverbrauch zurück. Jedoch können Sie den `ReturnConsumedCapacity`-Parameter in einer `Query`-Anforderung angeben, um diese Information zu erhalten. Folgende sind die gültigen Einstellungen für `ReturnConsumedCapacity`:
+ `NONE` – Es werden keine verbrauchten Kapazitätsdaten zurückgegeben. (Dies ist die Standardeinstellung.)
+ `TOTAL` – Die Antwort enthält die zusammengefasste Anzahl der verbrauchten Lesekapazitätseinheiten.
+ `INDEXES` – Die Antwort zeigt die zusammengefasste Anzahl der verbrauchten Lesekapazitätseinheiten, zusammen mit der verbrauchten Kapazität für jede aufgerufene Tabelle und jeden aufgerufenen Index, an.

DynamoDB berechnet die Anzahl von verbrauchten Lesekapazitätseinheiten basierend auf der Anzahl und Größe der Elemente, nicht der Menge der Daten, die an eine Anwendung zurückgegeben werden. Aus diesem Grund bleibt die Anzahl der verbrauchten Kapazitätseinheiten gleich, unabhängig davon, ob Sie alle Attribute (das Standardverhalten) oder nur einige von ihnen anfordern (mithilfe eines Projektionsausdrucks). Die Anzahl ist auch gleich, unabhängig davon, ob Sie einen Filterausdruck verwenden oder nicht. `Query` verbraucht eine Mindestlesekapazitätseinheit für einen strikt konsistenten Lesevorgang pro Sekunde oder zwei letztendlich konsistente Lesevorgänge pro Sekunde für ein Element von bis zu 4 KB. Wenn Sie ein Element lesen möchten, das größer als 4 KB ist, benötigt DynamoDB zusätzliche Leseanforderungseinheiten. Bei leeren Tabellen und sehr großen Tabellen mit einer geringen Anzahl an Partitionsschlüsseln können zusätzliche RCUs Gebühren anfallen, die über die abgefragte Datenmenge hinausgehen. Dies deckt die Kosten für die `Query`-Bearbeitung der Anfrage, auch wenn keine Daten vorhanden sind.

## Lesekonsistenz für die Abfrage
<a name="Query.ReadConsistency"></a>

Eine `Query`-Operation führt standardmäßig lEventually Consistent-Lesevorgänge aus. Dies bedeutet, dass die `Query`-Ergebnisse Änderungen aufgrund kürzlich abgeschlossener `PutItem` oder `UpdateItem`-Operationen, nicht wiedergeben könnten. Weitere Informationen finden Sie unter [DynamoDB-Lesekonsistenz](HowItWorks.ReadConsistency.md).

Wenn Sie Strongly Consistent-Lesevorgänge benötigen, legen Sie den `ConsistentRead`-Parameter in der `Query`-Anforderung auf `true` fest.

# Scannen von Tabellen in DynamoDB
<a name="Scan"></a>

Eine `Scan`-Operation in Amazon DynamoDB liest jedes Element in einer Tabelle oder einem Sekundärindex. Standardmäßig gibt ein `Scan`-Vorgang für jedes Element in der Tabelle oder im Index alle Datenattribute zurück. Sie können den `ProjectionExpression`-Parameter verwenden, sodass `Scan` nur einige der Attribute und nicht alle zurückgibt.

`Scan` gibt immer einen Ergebnissatz zurück. Wenn keine übereinstimmenden Elemente gefunden werden, ist die Ergebnismenge leer.

Eine einzelne `Scan`-Anforderung kann maximal 1 MB Daten abrufen. DynamoDB kann optional einen Filterausdruck auf diese Daten anwenden, um die Ergebnisse einzugrenzen, bevor sie an den Benutzer zurückgegeben werden.

**Topics**
+ [Filterausdrücke für Scan](#Scan.FilterExpression)
+ [Begrenzung der Anzahl an Elementen in der Ergebnismenge](#Scan.Limit)
+ [Paginierung der Ergebnisse](#Scan.Pagination)
+ [Zählen der Elemente in den Ergebnissen](#Scan.Count)
+ [Durch die Abfrage verbrauchte Kapazitätseinheiten](#Scan.CapacityUnits)
+ [Lesekonsistenz für Scan](#Scan.ReadConsistency)
+ [Parallele Scans](#Scan.ParallelScan)

## Filterausdrücke für Scan
<a name="Scan.FilterExpression"></a>

Wenn Sie die `Scan`-Ergebnisse weiter eingrenzen müssen, können Sie optional einen Filterausdruck angeben. Ein *Filterausdruck* bestimmt, welche Elemente in den `Scan`-Ergebnissen an Sie zurückgegeben werden. Alle anderen Ergebnisse werden verworfen.

Ein Filterausdruck wird angewendet, nachdem eine `Scan` abgeschlossen ist, aber bevor die Ergebnisse zurückgegeben werden. Folglich verbraucht eine `Scan` unabhängig davon, ob ein Filterausdruck vorhanden ist oder nicht, gleich viel Lesekapazität.

Eine `Scan`-Operation kann bis zu 1 MB an Daten abrufen. Diese Größenbeschränkung gilt, bevor der Filterausdruck ausgewertet wird.

Mit `Scan` können Sie Attribute in einem Filterausdruck angeben—einschließlich Partitionsschlüsseln und Sortierschlüsselattributen.

Die Syntax für einen Filterausdruck ist identisch mit der für einen Bedingungsausdruck. Filterausdrücke können dieselben Vergleichsoperatoren, Funktionen und logischen Operatoren wie ein Bedingungsausdruck verwenden. Weitere Informationen zu logischen Operatoren finden Sie unter [Bedingungs- und Filterausdrücke, Operatoren und Funktionen in DynamoDB](Expressions.OperatorsAndFunctions.md).

**Example**  
Das folgende Beispiel AWS Command Line Interface (AWS CLI) scannt die `Thread` Tabelle und gibt nur die Elemente zurück, die zuletzt von einem bestimmten Benutzer gepostet wurden.  

```
aws dynamodb scan \
     --table-name Thread \
     --filter-expression "LastPostedBy = :name" \
     --expression-attribute-values '{":name":{"S":"User A"}}'
```

## Begrenzung der Anzahl an Elementen in der Ergebnismenge
<a name="Scan.Limit"></a>

Die `Scan`-Operation ermöglicht es Ihnen, die Anzahl der Elemente einzuschränken, die in den Ergebnissen zurückgegeben werden. Legen Sie dafür vor dem Filtern der Ausdrucksauswertung den Parameter `Limit` auf die maximale Anzahl von Elementen fest, die die `Scan`-Operation zurückgeben soll.

Beispiel: Sie führen eine `Scan`-Operation für eine Tabelle mit einem `Limit`-Wert von `6` und ohne Filterausdruck durch. Die`Scan`-Ergebnis enthält die ersten sechs Elemente der Tabelle.

Angenommen, Sie fügen nun einen Filterausdruck der `Scan` hinzu. In diesem Fall wendet DynamoDB den entsprechenden Filterausdruck auf die sechs zurückgegebenen Elemente an, wobei die nicht übereinstimmenden verworfen werden. Das letzte `Scan`-Ergebnis enthält sechs Elemente oder weniger, je nachdem, wie viele Elemente gefiltert wurden.

## Paginierung der Ergebnisse
<a name="Scan.Pagination"></a>

DynamoDB *paginiert* die Ergebnisse von `Scan`-Operationen. Bei der Paginierung werden die `Scan`-Ergebnisse in „Seiten“ mit Daten von einer Größe von 1 MB (oder weniger) unterteilt. Eine Anwendung kann die erste Ergebnisseite verarbeiten, dann die zweite Seite und so weiter.

Eine einzelne `Scan`-Operation gibt nur einen Ergebnissatz zurück, der innerhalb des Grenzwerts von 1 MB liegt. 

Um zu bestimmen, ob es mehr Ergebnisse gibt, und diese seitenweise abzurufen, sollten Anwendungen die folgenden Schritte ausführen:

1. Überprüfen Sie das `Scan`-Low-Level-Ergebnis:
   + Wenn das Ergebnis ein `LastEvaluatedKey`-Element enthält, fahren Sie mit Schritt 2 fort.
   + Wenn im Ergebnis *kein* `LastEvaluatedKey` vorhanden ist, sind keine Elemente mehr zum Abrufen vorhanden.

1. Erstellen Sie eine neue `Scan`-Anforderung mit den gleichen Parametern wie bei der vorherigen Anforderung. Verwenden Sie jedoch dieses Mal den `LastEvaluatedKey`-Wert aus Schritt 1 als `ExclusiveStartKey`-Parameter in der neuen `Scan`-Anforderung.

1. Führen Sie die neue `Scan`-Anforderung aus.

1. Fahren Sie mit Schritt 1 fort.

Mit anderen Worten: Der `LastEvaluatedKey` einer `Scan`-Antwort sollte als `ExclusiveStartKey` für die nächste `Scan`-Anforderung verwendet werden. Wenn in einer `Scan`-Antwort kein `LastEvaluatedKey`-Element vorhanden ist, haben Sie die letzte Ergebnisseite abgerufen. (Dass `LastEvaluatedKey` nicht vorhanden ist, ist der einzige Hinweis darauf, dass Sie das Ende des Ergebnissatzes erreicht haben.)

Sie können das verwenden AWS CLI , um sich dieses Verhalten anzusehen. Der AWS CLI sendet wiederholt `Scan` Anfragen auf niedriger Ebene an DynamoDB, bis er in den Ergebnissen nicht mehr vorhanden `LastEvaluatedKey` ist. Stellen Sie sich das folgende AWS CLI Beispiel vor, das die gesamte `Movies` Tabelle scannt, aber nur die Filme eines bestimmten Genres zurückgibt.

```
aws dynamodb scan \
    --table-name Movies \
    --projection-expression "title" \
    --filter-expression 'contains(info.genres,:gen)' \
    --expression-attribute-values '{":gen":{"S":"Sci-Fi"}}' \
    --page-size 100  \
    --debug
```

Normalerweise AWS CLI verarbeitet der die Seitennummerierung automatisch. In diesem Beispiel begrenzt der AWS CLI `--page-size` Parameter jedoch die Anzahl der Elemente pro Seite. Der `--debug`-Parameter gibt Low-Level-Informationen zu Anforderungen und Antworten aus.

**Anmerkung**  
Ihre Paginierungsergebnisse unterscheiden sich auch basierend auf den Eingabeparametern, die Sie übergeben.   
Die Verwendung von `aws dynamodb scan --table-name Prices --max-items 1` gibt `NextToken` zurück.
Die Verwendung von `aws dynamodb scan --table-name Prices --limit 1` gibt `LastEvaluatedKey` zurück.
Beachten Sie auch, dass insbesondere die Verwendung von `--starting-token` den Wert `NextToken` erfordert. 

Wenn Sie das Beispiel ausführen, sieht die erste Antwort von DynamoDB ungefähr folgendermaßen aus.

```
2017-07-07 12:19:14,389 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":7,"Items":[{"title":{"S":"Monster on the Campus"}},{"title":{"S":"+1"}},
{"title":{"S":"100 Degrees Below Zero"}},{"title":{"S":"About Time"}},{"title":{"S":"After Earth"}},
{"title":{"S":"Age of Dinosaurs"}},{"title":{"S":"Cloudy with a Chance of Meatballs 2"}}],
"LastEvaluatedKey":{"year":{"N":"2013"},"title":{"S":"Curse of Chucky"}},"ScannedCount":100}'
```

Der `LastEvaluatedKey` in der Antwort gibt an, dass nicht alle Elemente abgerufen wurden. Das sendet AWS CLI dann eine weitere `Scan` Anfrage an DynamoDB. Dieses Anforderungs- und Antwortmuster wird bis zur endgültigen Antwort fortgesetzt.

```
2017-07-07 12:19:17,830 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"WarGames"}}],"ScannedCount":6}'
```

Das Fehlen von `LastEvaluatedKey` gibt an, dass keine abrufbaren Elemente mehr vorhanden sind.

**Anmerkung**  
Sie AWS SDKs verarbeiten DynamoDB-Antworten auf niedriger Ebene (einschließlich des Vorhandenseins oder Fehlens von`LastEvaluatedKey`) und bieten verschiedene Abstraktionen für die Paginierung von Ergebnissen. `Scan` Beispielsweise stellt SDK für die Java-Dokumentschnittstelle `java.util.Iterator`-Unterstützung bereit, sodass Sie die Ergebnisse nacheinander durchgehen können.  
Codebeispiele in verschiedenen Programmiersprachen finden Sie im [Amazon-DynamoDB-Handbuch für erste Schritte](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/) und in der AWS SDK-Dokumentation für Ihre Sprache.

## Zählen der Elemente in den Ergebnissen
<a name="Scan.Count"></a>

Zusätzlich zu den Elementen, die mit Ihren Kriterien übereinstimmen, enthält die `Scan`-Antwort noch die folgenden Elemente:
+ `ScannedCount` – Anzahl der ausgewerteten Elemente vor jedem `ScanFilter` angewendet wird. Ein hoher `ScannedCount`-Wert mit wenigen oder gar keinen `Count`-Ergebnissen weist auf eine ineffiziente `Scan`-Operation hin. Wenn Sie keinen Filter in der Anforderung verwendet haben, haben `ScannedCount` und `Count` denselben Wert. 
+ `Count` – die Anzahl der Elemente, die verbleiben, *nachdem* ein Filterausdruck (falls vorhanden) angewendet wurde.

**Anmerkung**  
Wenn Sie keinen Filterausdruck verwenden, haben `ScannedCount` und `Count` denselben Wert.

Wenn der `Scan`-Ergebnissatz größer als 1 MB ist, repräsentieren `ScannedCount` und `Count` nur eine Teilmenge der Gesamtelemente. Sie müssen mehrere `Scan`-Operationen ausführen, um alle Ergebnisse abzurufen (siehe [Paginierung der Ergebnisse](#Scan.Pagination)).

Jede `Scan`-Antwort enthält die `ScannedCount` und `Count` für die Elemente, die von der betreffenden `Scan`-Anforderung verarbeitet wurden. Um eine Gesamtsumme für alle `Scan`-Anforderungen zu erhalten, könnten Sie eine laufende Zählung von `ScannedCount` und `Count` vornehmen.

## Durch die Abfrage verbrauchte Kapazitätseinheiten
<a name="Scan.CapacityUnits"></a>

Sie können `Scan` für jede Tabelle und jeden Sekundärindex ausführen. `Scan`-Operationen verbrauchen Lesekapazitätseinheiten wie folgt.


****  

| Wenn Sie `Scan` eine ... | DynamoDB verbraucht Lesekapazitätseinheiten von ... | 
| --- | --- | 
| Tabelle | Die bereitgestellte Lesekapazität der Tabelle. | 
| Globaler sekundärer Index | Die bereitgestellte Lesekapazität des Index. | 
| Lokaler sekundärer Index | Die bereitgestellte Lesekapazität der Basistabelle. | 

**Anmerkung**  
Kontoübergreifender Zugriff für sekundäre Indexscanvorgänge wird derzeit nicht für [ressourcenbasierte Richtlinien](access-control-resource-based.md) unterstützt.

Standardmäßig gibt eine `Scan`-Operation keine Daten über seinen Lesekapazitätsverbrauch zurück. Jedoch können Sie den `ReturnConsumedCapacity`-Parameter in einer `Scan`-Anforderung angeben, um diese Information zu erhalten. Folgende sind die gültigen Einstellungen für `ReturnConsumedCapacity`:
+ `NONE` – Es werden keine verbrauchten Kapazitätsdaten zurückgegeben. (Dies ist die Standardeinstellung.)
+ `TOTAL` – Die Antwort enthält die zusammengefasste Anzahl der verbrauchten Lesekapazitätseinheiten.
+ `INDEXES` – Die Antwort zeigt die zusammengefasste Anzahl der verbrauchten Lesekapazitätseinheiten, zusammen mit der verbrauchten Kapazität für jede aufgerufene Tabelle und jeden aufgerufenen Index, an.

DynamoDB berechnet die Anzahl von verbrauchten Lesekapazitätseinheiten basierend auf der Anzahl und Größe der Elemente, nicht der Menge der Daten, die an eine Anwendung zurückgegeben werden. Aus diesem Grund bleibt die Anzahl der verbrauchten Kapazitätseinheiten gleich, unabhängig davon, ob Sie alle Attribute (das Standardverhalten) oder nur einige von ihnen anfordern (mithilfe eines Projektionsausdrucks). Die Anzahl ist auch gleich, unabhängig davon, ob Sie einen Filterausdruck verwenden oder nicht. `Scan` verbraucht eine Mindestlesekapazitätseinheit für einen strikt konsistenten Lesevorgang pro Sekunde oder zwei letztendlich konsistente Lesevorgänge pro Sekunde für ein Element von bis zu 4 KB. Wenn Sie ein Element lesen möchten, das größer als 4 KB ist, benötigt DynamoDB zusätzliche Leseanforderungseinheiten. Bei leeren Tabellen und sehr großen Tabellen mit einer geringen Anzahl an Partitionsschlüsseln können zusätzliche RCUs Gebühren anfallen, die über die Menge der gescannten Daten hinausgehen. Damit werden die Kosten für die Bearbeitung der `Scan`-Anfrage gedeckt, auch wenn keine Daten vorhanden sind.

## Lesekonsistenz für Scan
<a name="Scan.ReadConsistency"></a>

Eine `Scan`-Operation führt standardmäßig lEventually Consistent-Lesevorgänge aus. Dies bedeutet, dass die `Scan`-Ergebnisse Änderungen aufgrund kürzlich abgeschlossener `PutItem` oder `UpdateItem`-Operationen, nicht wiedergeben könnten. Weitere Informationen finden Sie unter [DynamoDB-Lesekonsistenz](HowItWorks.ReadConsistency.md).

Wenn Sie Strongly Consistent-Lesevorgänge benötigen, setzen Sie zum Zeitpunkt, an dem der `Scan` beginnt, den `ConsistentRead`-Parameter in der `Scan`-Anforderung auf `true`. Dadurch wird sichergestellt, dass alle Schreibvorgänge, die vor `Scan`-Beginn abgeschlossen wurden, in die `Scan`-Antwort aufgenommen werden. 

Die Festlegung von `ConsistentRead` für `true` kann beim Backup von Tabellen oder in Replikationsszenarien mit [DynamoDB Streams](./Streams.html) hilfreich sein. Sie verwenden zuerst `Scan`, während `ConsistentRead` auf "true" eingestellt ist, um eine konsistente Kopie der Daten in der Tabelle zu erhalten. Während der `Scan`-Operation zeichnet DynamoDB Streams alle zusätzlichen Schreibaktivitäten auf, die in der Tabelle ausgeführt werden. Nach Abschluss der `Scan` können Sie die Schreibaktivität vom Stream auf die Tabelle anwenden.

**Anmerkung**  
Beachten Sie, dass eine `Scan`-Operation, bei der `ConsistentRead` auf `true` festgelegt ist, doppelt so viele Lesekapazitätseinheiten verbraucht wie mit dem `ConsistentRead`-Standardwert (`false`).

## Parallele Scans
<a name="Scan.ParallelScan"></a>

Standardmäßig verarbeitet die `Scan`-Operation Daten sequenziell. Amazon DynamoDB gibt Daten in Schritten von 1 MB an die Anwendung zurück, und eine Anwendung führt zusätzliche `Scan`-Operationen aus, um die nächsten 1 MB Daten abzurufen. 

Je größer die gescannte Tabelle oder der Index, desto mehr Zeit benötigt `Scan` um zu beenden. Außerdem kann eine sequenzielle `Scan` möglicherweise die bereitgestellte Lesedurchsatzkapazität nicht immer vollständig nutzen: Auch wenn DynamoDB die Daten einer großen Tabelle über mehrere physische Partitionen verteilt, kann eine `Scan`-Operation nur jeweils eine Partition lesen. Aus diesem Grund wird der Durchsatz einer `Scan`-Operation durch den maximalen Durchsatz einer einzelnen Partition beschränkt.

Um diese Probleme zu beheben, kann die `Scan`-Operation eine Tabelle oder einen sekundären Index in mehrere *Segmente* logisch unterteilen, wobei mehrere Anwendungs-Worker die Segmente parallel scannen. Jeder Worker kann ein Thread (in Programmiersprachen, die Multithreading unterstützen) oder ein Betriebssystemprozess sein. Zum Durchführen eines parallelen Scans erstellt jeder Worker eine eigene `Scan`-Anforderung mit den folgenden Parametern:
+ `Segment` – Ein Segment, das von einem bestimmten Worker gescannt werden soll. Jeder Worker sollte einen anderen Wert für `Segment` verwenden.
+ `TotalSegments` – Die Gesamtanzahl der Segmente für den parallelen Scan. Dieser Wert muss mit der Anzahl der Worker übereinstimmen, die Ihre Anwendung verwenden wird.

Das folgende Diagramm zeigt, wie eine Multithread-Anwendung eine parallele `Scan`-Operation mit drei Grad Parallelität ausführt.

![\[Eine Multithread-Anwendung, die einen parallelen Scan durchführt, indem sie eine Tabelle in drei Segmente unterteilt.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/ParallelScan.png)




In diesem Diagramm ruft die Anwendung drei Threads auf und weist jedem Thread eine Zahl zu. (Segmente sind nullbasiert, sodass die erste Zahl immer 0 ist.) Jeder Thread erstellt eine `Scan`-Anforderung, mit der `Segment` auf die zugewiesene Zahl und `TotalSegments` auf 3 eingestellt wird. Jeder Thread scannt ein zugewiesenes Segment, indem 1 MB Daten abgerufen werden, und gibt die Daten an den Haupt-Thread der Anwendung zurück.

DynamoDB weist Elemente *Segmenten* zu, indem es eine Hash-Funktion auf den Partitionsschlüssel jedes Elements anwendet. Bei einem bestimmten `TotalSegments` Wert werden alle Elemente mit demselben Partitionsschlüssel immer demselben zugewiesen. `Segment` Das bedeutet, dass in einer Tabelle, in der sich *Element 1**, Element 2* *und Element 3* alle teilen `pk="account#123"` (aber unterschiedliche Sortierschlüssel haben), diese Elemente von demselben Worker verarbeitet werden, unabhängig von den Sortierschlüsselwerten oder der Größe der *Elementsammlung*.

Da die *Segmentzuweisung* ausschließlich auf dem Hash des Partitionsschlüssels basiert, können Segmente ungleichmäßig verteilt sein. Einige Segmente enthalten möglicherweise keine Elemente, während andere viele Partitionsschlüssel mit großen Elementsammlungen enthalten können. Daher garantiert eine Erhöhung der Gesamtzahl der Segmente keine schnellere Scanleistung, insbesondere wenn die Partitionsschlüssel nicht gleichmäßig über den Schlüsselraum verteilt sind.

Die Werte für `Segment` und `TotalSegments` gelten für einzelne `Scan`-Anforderungen. Sie können jederzeit andere Werte verwenden. Sie müssen ggf. mit diesen Werten und der Anzahl der verwendeten Worker experimentieren, bis Ihre Anwendung eine optimale Leistung erzielt.

**Anmerkung**  
Ein paralleler Scan mit einer großen Anzahl von Workern kann leicht den gesamten bereitgestellten Durchsatz für die Tabelle oder den Index, die bzw. der gescannt wird, verbrauchen. Es ist am besten, solche Scans zu verhindern, wenn für die Tabelle oder den Index auch viele Lese- und Schreibaktivitäten von anderen Anwendungen erfolgen.  
Zur Steuerung der Datenmenge, die pro Anforderung zurückgegeben wird, verwenden Sie den Parameter `Limit`. Auf diese Weise können Sie Situationen verhindern, in denen ein Worker den gesamten bereitgestellten Durchsatz auf Kosten aller anderen Worker verbraucht.

# PartiQL – Eine SQL-kompatible Abfragesprache für Amazon DynamoDB
<a name="ql-reference"></a>

Amazon DynamoDB unterstützt [PartiQL](https://partiql.org/), eine SQL-kompatible Abfragesprache, um Daten in Amazon DynamoDB auszuwählen, einzufügen, zu aktualisieren und zu löschen. Mit PartiQL können Sie problemlos mit DynamoDB-Tabellen interagieren und Ad-hoc-Abfragen mithilfe von NoSQL Workbench und DynamoDB for PartiQL ausführen. AWS-Managementkonsole AWS Command Line Interface APIs 

PartiQL-Operationen bieten die gleiche Verfügbarkeit, Latenz und Performance wie die anderen DynamoDB-Datenebenen-Operationen.

In den folgenden Abschnitten wird die DynamoDB-Implementierung von PartiQL beschrieben.

**Topics**
+ [Was ist PartiQL?](#ql-reference.what-is)
+ [PartiQL in Amazon DynamoDB](#ql-reference.what-is)
+ [Erste Schritte](ql-gettingstarted.md)
+ [Datentypen](ql-reference.data-types.md)
+ [Anweisungen](ql-reference.statements.md)
+ [Funktionen](ql-functions.md)
+ [Betreiber](ql-operators.md)
+ [Transaktionen](ql-reference.multiplestatements.transactions.md)
+ [Batch-Vorgänge](ql-reference.multiplestatements.batching.md)
+ [IAM-Richtlinien](ql-iam.md)

## Was ist PartiQL?
<a name="ql-reference.what-is"></a>

*PartiQL* bietet SQL-kompatiblen Abfragezugriff über mehrere Datenspeicher mit strukturierten, halbstrukturierten und verschachtelten Daten hinweg. Es ist bei Amazon weit verbreitet und ist jetzt als Teil vieler AWS Dienste verfügbar, einschließlich DynamoDB.

Die PartiQL-Spezifikation und ein Tutorial zur Core-Abfragesprache finden Sie in der [PartiQL-Dokumentation](https://partiql.org/docs.html).

**Anmerkung**  
Amazon DynamoDB unterstützt eine *Teilmenge* der [PartiQL](https://partiql.org/)-Abfragesprache.
Amazon DynamoDB unterstützt das [Amazon-Ion](http://amzn.github.io/ion-docs/)-Datenformat oder Amazon-Ion-Literale nicht.

## PartiQL in Amazon DynamoDB
<a name="ql-reference.what-is"></a>

Zum Ausführen von PartiQL-Abfragen in DynamoDB können Sie Folgendes verwenden:
+ Die DynamoDB-Konsole
+ NoSQL Workbench
+ Das AWS Command Line Interface ()AWS CLI
+ Die DynamoDB APIs

Weitere Informationen zum Verwenden dieser Methoden für den Zugriff auf DynamoDB finden Sie unter [Zugreifen auf DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html).

# Erste Schritte mit PartiQL für DynamoDB
<a name="ql-gettingstarted"></a>

In diesem Abschnitt wird beschrieben, wie PartiQL für DynamoDB von der Amazon DynamoDB DynamoDB-Konsole, der AWS Command Line Interface ()AWS CLI und DynamoDB aus verwendet wird. APIs

In den folgenden Beispielen ist die DynamoDB-Tabelle, die im Tutorial [Erste Schritte mit DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html) definiert ist, eine Voraussetzung.

[Informationen zur Verwendung der DynamoDB-Konsole oder DynamoDB für den Zugriff auf DynamoDB finden Sie unter APIs Accessing DynamoDB. AWS Command Line Interface](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html)

Um die [NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html) [herunterzuladen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html) und zu verwenden, um [PartiQL for DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html) (PartiQL für DynamoDB) Anweisungen zu erstellen, wählen Sie **PartiQL operations** (PartiQL-Operationen) in der oberen rechten Ecke der NoSQL Workbench für DynamoDB [Operation Builder](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.querybuilder.operationbuilder.html).

------
#### [ Console ]

![\[PartiQL-Editor-Schnittstelle, die das Ergebnis der Abfrage-Operation in der Tabelle Music anzeigt.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/partiqlgettingstarted.png)


1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie im Navigationsbereich auf der linken Seite der Konsole **PartiQL editor** (PartiQL-Editor) aus.

1. Wählen Sie die Tabelle **Music** (Musik).

1. Klicken Sie auf die **Query table** (Abfragetabelle). Diese Aktion generiert eine Abfrage, die nicht zu einem vollständigen Tabellenscan führt.

1. ErsetzenSie `partitionKeyValue` mit dem Zeichenfolgen-Wert `Acme Band`. ErsetzenSie `sortKeyValue` mit dem Zeichenfolgen-Wert `Happy Day`.

1. Wählen Sie die Schaltfläche **Run** (Ausführen) aus. 

1. Sie können die Ergebnisse der Abfrage anzeigen, indem Sie die Schaltflächen **Table view** (Tabellenansicht) oder **JSON view** (JSON-Ansicht) auswählen. 

------
#### [ NoSQL workbench ]

![\[NoSQL Workbench-Schnittstelle. Sie zeigt eine PartiQL SELECT-Anweisung, die Sie in der Tabelle Music ausführen können.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/workbench/partiql.single.png)


1. Klicken Sie auf **PartiQL statement** (PartiQL-Anweisung).

1. Geben Sie die folgende PartiQL-[SELECT-Anweisung](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html) ein 

   ```
   SELECT *                                         
   FROM Music  
   WHERE Artist=? and SongTitle=?
   ```

1. So geben Sie einen Wert für den `Artist`- und `SongTitle`-Parameter ein:

   1. Klicken Sie auf **Optional request parameter** (Optionale Anfrageparameter).

   1. Klicken Sie auf **Add new parameters** (Fügen Sie neue Parameter hinzu).

   1. Wählen Sie den Attributtyp **string** (Zeichenfolge) und den Wert `Acme Band`.

   1. Wiederholen Sie die Schritte b und c, und wählen Sie den Typ **string** (Zeichenfolge) und den Wert `PartiQL Rocks`. 

1. Falls Sie Code generieren möchten, wählen Sie **Generate code** (Code generieren) aus.

   Wählen Sie in den angezeigten Tabs Ihre gewünschte Sprache aus. Sie können diesen Code jetzt kopieren und in Ihrer Anwendung verwenden.

1. Falls die Operation sofort ausgeführt werden soll, wählen Sie **Run** (Ausführen).

------
#### [ AWS CLI ]

1. Erstellen Sie mit der INSERT-PartiQL-Anweisung ein Element in der Tabelle `Music`. 

   ```
   aws dynamodb execute-statement --statement "INSERT INTO Music  \
   					    VALUE  \
   					    {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"
   ```

1. Rufen Sie mit der SELECT-PartiQL-Anweisung ein Element aus der Musiktabelle ab.

   ```
   aws dynamodb execute-statement --statement "SELECT * FROM Music   \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. Aktualisieren Sie ein Element in der Tabelle `Music` mit der UPDATE-PartiQL-Anweisung.

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardsWon=1  \
                                               SET AwardDetail={'Grammys':[2020, 2018]}  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Fügen Sie einen Listenwert für ein Element in der `Music`-Tabelle ein 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Entfernen Sie einen Listenwert für ein Element in der `Music`-Tabelle 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               REMOVE AwardDetail.Grammys[2]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Fügen Sie ein neues Kartenelement für ein Element in der `Music`-Tabelle ein 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.BillBoard=[2020]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Fügen Sie ein neues Zeichenfolgensatzattribut für ein Element in der `Music`-Tabelle hinzu. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =<<'member1', 'member2'>>  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Aktualisieren Sie ein neues Zeichenfolgensatzattribut für ein Element in der `Music`-Tabelle- 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =set_add(BandMembers, <<'newmember'>>)  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. Löschen Sie ein Element aus dem`Music`-Tabelle mit der DELETE-PartiQL-Anweisung.

   ```
   aws dynamodb execute-statement --statement "DELETE  FROM Music  \
       WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

------
#### [ Java ]

```
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import software.amazon.dynamodb.AmazonDynamoDB;
import software.amazon.dynamodb.AmazonDynamoDBClientBuilder;
import software.amazon.dynamodb.model.AttributeValue;
import software.amazon.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.dynamodb.model.ExecuteStatementRequest;
import software.amazon.dynamodb.model.ExecuteStatementResult;
import software.amazon.dynamodb.model.InternalServerErrorException;
import software.amazon.dynamodb.model.ItemCollectionSizeLimitExceededException;
import software.amazon.dynamodb.model.ProvisionedThroughputExceededException;
import software.amazon.dynamodb.model.RequestLimitExceededException;
import software.amazon.dynamodb.model.ResourceNotFoundException;
import software.amazon.dynamodb.model.TransactionConflictException;

public class DynamoDBPartiQGettingStarted {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-1");

        try {
            // Create ExecuteStatementRequest
            ExecuteStatementRequest executeStatementRequest = new ExecuteStatementRequest();
            List<AttributeValue> parameters= getPartiQLParameters();

            //Create an item in the Music table using the INSERT PartiQL statement
            processResults(executeStatementRequest(dynamoDB, "INSERT INTO Music value {'Artist':?,'SongTitle':?}", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //Update an item in the Music table using the UPDATE PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist=? and SongTitle=?", parameters));

            //Add a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  where Artist=? and SongTitle=?", parameters));

            //Remove a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music REMOVE AwardDetail.Grammys[2]   where Artist=? and SongTitle=?", parameters));

            //Add a new map member for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music set AwardDetail.BillBoard=[2020] where Artist=? and SongTitle=?", parameters));

            //Add a new string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =<<'member1', 'member2'>> where Artist=? and SongTitle=?", parameters));

            //update a string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =set_add(BandMembers, <<'newmember'>>) where Artist=? and SongTitle=?", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //delete an item from the Music Table
            processResults(executeStatementRequest(dynamoDB, "DELETE  FROM Music  where Artist=? and SongTitle=?", parameters));
        } catch (Exception e) {
            handleExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {
        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static List<AttributeValue> getPartiQLParameters() {
        List<AttributeValue> parameters = new ArrayList<AttributeValue>();
        parameters.add(new AttributeValue("Acme Band"));
        parameters.add(new AttributeValue("PartiQL Rocks"));
        return parameters;
    }

    private static ExecuteStatementResult executeStatementRequest(AmazonDynamoDB client, String statement, List<AttributeValue> parameters ) {
        ExecuteStatementRequest request = new ExecuteStatementRequest();
        request.setStatement(statement);
        request.setParameters(parameters);
        return client.executeStatement(request);
    }

    private static void processResults(ExecuteStatementResult executeStatementResult) {
        System.out.println("ExecuteStatement successful: "+ executeStatementResult.toString());

    }

    // Handles errors during ExecuteStatement execution. Use recommendations in error messages below to add error handling specific to
    // your application use-case.
    private static void handleExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("Condition check specified in the operation failed, review and update the condition " +
                                       "check before retrying. Error: " + ccfe.getErrorMessage());
        } catch (TransactionConflictException tce) {
            System.out.println("Operation was rejected because there is an ongoing transaction for the item, generally " +
                                       "safe to retry with exponential back-off. Error: " + tce.getErrorMessage());
        } catch (ItemCollectionSizeLimitExceededException icslee) {
            System.out.println("An item collection is too large, you\'re using Local Secondary Index and exceeded " +
                                       "size limit of items per partition key. Consider using Global Secondary Index instead. Error: " + icslee.getErrorMessage());
        } catch (Exception e) {
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " +
                                       "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                                       "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " +
                                       ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " +
                                       "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                                       "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                                       "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                                       "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

## Verwenden von parametrisierten Anweisungen
<a name="ql-gettingstarted.parameterized"></a>

Anstatt Werte direkt in eine PartiQL-Anweisungszeichenfolge einzubetten, können Sie Fragezeichen-Platzhalter (`?`) verwenden und die Werte separat in das Feld eingeben. `Parameters` Jeder Wert `?` wird durch den entsprechenden Parameterwert ersetzt, und zwar in der Reihenfolge, in der er angegeben wurde.

Die Verwendung parametrisierter Anweisungen ist eine bewährte Methode, da sie die Anweisungsstruktur von den Datenwerten trennt, sodass Anweisungen leichter zu lesen und wiederzuverwenden sind. Außerdem müssen Attributwerte in der Anweisungszeichenfolge nicht manuell formatiert und maskiert werden.

Parametrisierte Anweisungen werden in `ExecuteStatement``BatchExecuteStatement`, und `ExecuteTransaction` -Operationen unterstützt.

In den folgenden Beispielen wird mithilfe parametrisierter Werte für den Partitionsschlüssel und den Sortierschlüssel ein Element aus der `Music` Tabelle abgerufen.

------
#### [ AWS CLI parameterized ]

```
aws dynamodb execute-statement \
    --statement "SELECT * FROM \"Music\" WHERE Artist=? AND SongTitle=?" \
    --parameters '[{"S": "Acme Band"}, {"S": "PartiQL Rocks"}]'
```

------
#### [ Java parameterized ]

```
List<AttributeValue> parameters = new ArrayList<>();
parameters.add(new AttributeValue("Acme Band"));
parameters.add(new AttributeValue("PartiQL Rocks"));

ExecuteStatementRequest request = new ExecuteStatementRequest()
    .withStatement("SELECT * FROM Music WHERE Artist=? AND SongTitle=?")
    .withParameters(parameters);

ExecuteStatementResult result = dynamoDB.executeStatement(request);
```

------
#### [ Python parameterized ]

```
response = dynamodb_client.execute_statement(
    Statement="SELECT * FROM Music WHERE Artist=? AND SongTitle=?",
    Parameters=[
        {'S': 'Acme Band'},
        {'S': 'PartiQL Rocks'}
    ]
)
```

------

**Anmerkung**  
Das Java-Beispiel im vorherigen Abschnitt „Erste Schritte“ verwendet durchweg parametrisierte Anweisungen. Die `getPartiQLParameters()` Methode erstellt die Parameterliste, und jede Anweisung verwendet `?` Platzhalter anstelle von Inline-Werten.

# PartiQL-Datentypen für DynamoDB
<a name="ql-reference.data-types"></a>

In der folgenden Tabelle sind die Datentypen aufgeführt, die Sie mit PartiQL für DynamoDB verwenden können.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/ql-reference.data-types.html)

## Beispiele
<a name="ql-reference.data-types"></a>

Die folgende Anweisung veranschaulicht, wie die folgenden Datentypen eingefügt werden: `String`, `Number`, `Map`, `List`, `Number Set` und `String Set`.

```
INSERT INTO TypesTable value {'primarykey':'1', 
'NumberType':1,
'MapType' : {'entryname1': 'value', 'entryname2': 4}, 
'ListType': [1,'stringval'], 
'NumberSetType':<<1,34,32,4.5>>, 
'StringSetType':<<'stringval','stringval2'>>
}
```

Die folgende Anweisung veranschaulicht, wie neue Elemente in die `Map`, `List`, `Number Set` und `String Set`-Typen eingefügt werden und den Wert eines `Number`-Typ ändern.

```
UPDATE TypesTable 
SET NumberType=NumberType + 100 
SET MapType.NewMapEntry=[2020, 'stringvalue', 2.4]
SET ListType = LIST_APPEND(ListType, [4, <<'string1', 'string2'>>])
SET NumberSetType= SET_ADD(NumberSetType, <<345, 48.4>>)
SET StringSetType = SET_ADD(StringSetType, <<'stringsetvalue1', 'stringsetvalue2'>>)
WHERE primarykey='1'
```

Die folgende Anweisung veranschaulicht, wie neue Elemente aus den `Map`, `List`, `Number Set` und `String Set`-Typen entfernt werden und den Wert eines `Number`-Typ ändern.

```
UPDATE TypesTable 
SET NumberType=NumberType - 1
REMOVE ListType[1]
REMOVE MapType.NewMapEntry
SET NumberSetType = SET_DELETE( NumberSetType, <<345>>)
SET StringSetType = SET_DELETE( StringSetType, <<'stringsetvalue1'>>)
WHERE primarykey='1'
```

Weitere Informationen finden Sie unter [DynamoDB-Datentypen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes).

# PartiQL-Anweisungen für DynamoDB
<a name="ql-reference.statements"></a>

Amazon DynamoDB unterstützt die folgenden PartiQL-Anweisungen.

**Anmerkung**  
DynamoDB unterstützt nicht alle PartiQL-Anweisungen.  
Diese Referenz enthält grundlegende Syntax- und Verwendungsbeispiele für PartiQL-Anweisungen, die Sie manuell mit dem AWS CLI oder APIs ausführen.

*Data Manipulation Language* (DML) ist die Gruppe von PartiQL-Anweisungen, die Sie zum Verwalten von Daten in DynamoDB-Tabellen verwenden. Sie verwenden DML-Anweisungen, um Daten in einer Tabelle hinzuzufügen, zu ändern oder zu löschen.

Die folgenden Anweisungen für DML- und Abfragesprachen werden unterstützt:
+ [PartiQL-Select-Anweisungen für DynamoDB](ql-reference.select.md)
+ [Aktualisierungen für PartiQL-Anweisungen für DynamoDB](ql-reference.update.md)
+ [PartiQL-Insert-Anweisungen für DynamoDB](ql-reference.insert.md)
+ [PartiQL-Delete-Anweisungen für DynamoDB](ql-reference.delete.md)

[Ausführen von Transaktionen mit PartiQL für DynamoDB](ql-reference.multiplestatements.transactions.md) und [Ausführen von Batchoperationen mit PartiQL für DynamoDB](ql-reference.multiplestatements.batching.md) werden auch von PartiQL für DynamoDB unterstützt.

# PartiQL-Select-Anweisungen für DynamoDB
<a name="ql-reference.select"></a>

Verwenden Sie die `SELECT`-Anweisung zum Abrufen von Daten aus einer Tabelle in Amazon DynamoDB.

Die Verwendung der `SELECT`-Anweisung kann zu einem vollständigen Tabellenscan führen, wenn in der WHERE-Klausel keine Gleichheitsbedingung oder IN-Bedingung mit einem Partitionsschlüssel angegeben ist. Die Scan-Operation untersucht jedes Element auf die angeforderten Werte und kann den bereitgestellten Durchsatz für eine große Tabelle oder Index in einer einzigen Operation verbrauchen. 

Wenn Sie den vollständigen Tabellenscan in PartiQL vermeiden möchten, können Sie:
+ Erstellen Sie Ihre `SELECT`-Anweisungen so, dass keine vollständigen Tabellenscans durchgeführt werden, indem Sie sicherstellen, dass die Bedingung der [WHERE-Klausel entsprechend](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html#ql-reference.select.parameters) konfiguriert ist.
+ Deaktivieren Sie vollständige Tabellenscans mithilfe der IAM-Richtlinie, die unter [Beispiel: In PartiQL für DynamoDB Select-Anweisungen erlauben und vollständige Tabellenscan-Anweisungen verweigern](ql-iam.md#access-policy-ql-iam-example6) im DynamoDB-Entwicklerhandbuch.

Weitere Informationen finden Sie unter [Bewährte Methoden für das Abfragen und Scannen von Daten](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-query-scan.html) im DynamoDB-Entwicklerhandbuch.

**Topics**
+ [Syntax](#ql-reference.select.syntax)
+ [Parameters](#ql-reference.select.parameters)
+ [Beispiele](#ql-reference.select.examples)

## Syntax
<a name="ql-reference.select.syntax"></a>

```
SELECT expression  [, ...] 
FROM table[.index]
[ WHERE condition ] [ [ORDER BY key [DESC|ASC] , ...]
```

## Parameters
<a name="ql-reference.select.parameters"></a>

***expression***  
(erforderlich) Eine Projektion aus dem `*`-Platzhalter oder eine Projektionsliste aus einem oder mehreren Attributnamen oder Dokumentpfaden aus dem Ergebnissatz. Ein Ausdruck kann aus Aufrufen an [Verwenden von PartiQL-Funktionen mit DynamoDB](ql-functions.md) oder Feldern bestehen, die von [PartiQL-Arithmetik-, Vergleichs- und logische Operatoren für DynamoDB](ql-operators.md) geändert werden.

***table***  
(Erforderlich) Der abzufragende Tabellenname.

***index***  
(Optional) Der Name des abzufragenden Indexes.  
Sie müssen dem Tabellennamen und dem Indexnamen doppelte Anführungszeichen hinzufügen, wenn Sie einen Index abfragen.  

```
SELECT * 
FROM "TableName"."IndexName"
```

***condition***  
(Optional) Die Auswahlkriterien für die Abfrage.  
Um sicherzustellen, dass eine `SELECT`-Anweisung nicht zu einem vollständigen Tabellenscan führt, muss die `WHERE`-Klauselbedingung einen Partitionsschlüssel angeben. Verwenden Sie den Gleichheits- oder IN-Operator.  
Angenommen, Sie haben eine `Orders`-Tabelle mit `OrderID`-Partitionsschlüssel und andere Nicht-Schlüsselattribute, einschließlich eines `Address`, würden die folgenden Anweisungen nicht zu einem vollständigen Tabellenscan führen:  

```
SELECT * 
FROM "Orders" 
WHERE OrderID = 100

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 and Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 or OrderID = 200

SELECT * 
FROM "Orders" 
WHERE OrderID IN [100, 300, 234]
```
Folgende `SELECT`-Anweisungen führen jedoch zu einem vollständigen Tabellenscan:  

```
SELECT * 
FROM "Orders" 
WHERE OrderID > 1

SELECT * 
FROM "Orders" 
WHERE Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 OR Address='some address'
```

***key***  
(Optional) Ein Hash-Schlüssel oder ein Sortierschlüssel, der zum Sortieren von ausgegebenen Ergebnissen verwendet werden soll. Die Standardreihenfolge ist aufsteigend (`ASC`) Geben Sie an.`DESC`, wenn die Ergebnisse in absteigender Reihenfolge neu abgestimmt werden sollen.

**Anmerkung**  
Wenn Sie die `WHERE`-Klausel weglassen, werden alle Elemente in der Tabelle abgerufen.

## Beispiele
<a name="ql-reference.select.examples"></a>

Die folgende Abfrage gibt ein Element, falls vorhanden, aus der `Orders`-Tabelle zurück, indem der Partitionsschlüssel `OrderID` angegeben und der Gleichheitsoperator verwendet wird.

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1
```

Die folgende Abfrage gibt alle Elemente in der `Orders`-Tabelle mit einem bestimmten Partitionsschlüssel `OrderID` zurück, mithilde von Werten mit dem Operator OR.

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1 OR OrderID = 2
```

Die folgende Abfrage gibt alle Elemente in der `Orders`-Tabelle mit einem bestimmten Partitionsschlüssel `OrderID` zurück, mithilde von Werten mit dem Operator IN. Die zurückgegebenen Ergebnisse sind in absteigender Reihenfolge, basierend auf dem `OrderID`-Attributwert.

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID IN [1, 2, 3] ORDER BY OrderID DESC
```

Die folgende Abfrage zeigt einen vollständigen Tabellenscan, der alle Elemente aus der `Orders`-Tabelle zurückgibt, deren `Total` größer als 500 ist, wobei `Total` ein Nicht-Schlüsselattribut ist.

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total > 500
```

Die folgende Abfrage zeigt einen vollständigen Tabellenscan, der alle Elemente aus der `Orders`-Tabelle innerhalb eines bestimmten `Total`-Reihenfolgebereichs zurückgibt, wobei der IN-Operator und ein Nicht-Schlüsselattribut `Total` verwendet werden.

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total IN [500, 600]
```

Die folgende Abfrage zeigt einen vollständigen Tabellenscan, der alle Elemente aus der `Orders`-Tabelle innerhalb eines bestimmten `Total`-Reihenfolgebereichs zurückgibt, wobei der BETWEEN-Operator und ein Nicht-Schlüsselattribut `Total` verwendet werden.

```
SELECT OrderID, Total 
FROM "Orders" 
WHERE Total BETWEEN 500 AND 600
```

Die folgende Abfrage gibt das erste Datum zurück, an dem ein Firestick-Gerät zum Überwachen verwendet wurde, indem der `CustomerID`-Partitionsschlüssel und der `MovieID`-Sortierschlüssel in der Bedingung der WHERE-Klausel angegeben und Dokumentpfade in der SELECT-Klausel verwendet werden.

```
SELECT Devices.FireStick.DateWatched[0] 
FROM WatchList 
WHERE CustomerID= 'C1' AND MovieID= 'M1'
```

Die folgende Abfrage zeigt einen vollständigen Tabellenscan, der die Liste der Elemente zurückgibt, bei denen ein Firestick-Gerät nach dem 24.12.19 zum ersten Mal unter Verwendung von Dokumentpfaden in der WHERE-Klausel Bedingung verwendet wurde.

```
SELECT Devices 
FROM WatchList 
WHERE Devices.FireStick.DateWatched[0] >= '12/24/19'
```

# Aktualisierungen für PartiQL-Anweisungen für DynamoDB
<a name="ql-reference.update"></a>

Verwenden der `UPDATE`-Anweisung, um den Wert eines oder mehrerer Attribute innerhalb eines Elements in einer Amazon-DynamoDB-Tabelle zu ändern. 

**Anmerkung**  
Sie können nur ein Element gleichzeitig aktualisieren. Sie können keine einzelne DynamoDB-PartiQL-Anweisung ausgeben, die mehrere Elemente aktualisiert. Weitere Informationen zum Aktualisieren mehrerer Elemente finden Sie unter [Ausführen von Transaktionen mit PartiQL für DynamoDB](ql-reference.multiplestatements.transactions.md) oder [Ausführen von Batchoperationen mit PartiQL für DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntax](#ql-reference.update.syntax)
+ [Parameters](#ql-reference.update.parameters)
+ [Rückgabewert](#ql-reference.update.return)
+ [Beispiele](#ql-reference.update.examples)

## Syntax
<a name="ql-reference.update.syntax"></a>

```
UPDATE  table  
[SET | REMOVE]  path  [=  data] […]
WHERE condition [RETURNING returnvalues]
<returnvalues>  ::= [ALL OLD | MODIFIED OLD | ALL NEW | MODIFIED NEW] *
```

## Parameters
<a name="ql-reference.update.parameters"></a>

***table***  
(erforderlich) Die Benutzertabelle mit den zu ändernden Daten.

***path***  
(Erforderlich) Ein Attributname oder Dokumentpfad, der erstellt oder geändert werden soll.

***data***  
(Erforderlich) Ein Attributwert oder das Ergebnis einer Operation.  
Die unterstützten Operationen, die mit SET verwendet werden sollen:  
+ LIST\$1APPEND: fügt einem Listentyp einen Wert hinzu.
+ SET\$1ADD: fügt einem Zahlen- oder Zeichenfolgensatz einen Wert hinzu.
+ SET\$1DELETE: Entfernt einen Wert aus einem Zahlen- oder Zeichenfolgensatz.

***condition***  
(erforderlich) Die Auswahlkriterien für die Elemente, die geändert werden sollen. Diese Bedingung muss auf einen einzelnen Primärschlüsselwert aufgelöst werden.

***returnvalues***  
(Optional) Verwenden Sie `returnvalues`, wenn Sie die Elementattribute so abrufen möchten, wie sie vor oder nach der Aktualisierung angezeigt werden. Die gültigen Werte sind:   
+ `ALL OLD *` – Gibt alle Attribute des Elements so zurück, wie sie vor dem Aktualisieren dargestellt wurden.
+ `MODIFIED OLD *` – Gibt nur die aktualisierten Attribute so zurück, wie sie vor dem Aktualisieren dargestellt wurden.
+ `ALL NEW *` – Gibt alle Attribute des Elements zurück, wie sie nach dem Aktualisierungsvorgang angezeigt werden.
+ `MODIFIED NEW *` – Gibt nur die aktualisierten Attribute so zurück, wie sie nach dem `UpdateItem` vorkommen.

## Rückgabewert
<a name="ql-reference.update.return"></a>

Diese Anweisung gibt keinen Wert zurück, es sei denn der `returnvalues`-Parameter ist angegeben.

**Anmerkung**  
Wenn die WHERE-Klausel der UPDATE-Anweisung für kein Element in der DynamoDB-Tabelle als wahr ausgewertet wird, wird `ConditionalCheckFailedException` zurückgegeben.

## Beispiele
<a name="ql-reference.update.examples"></a>

Aktualisieren Sie einen Attributwert in einem vorhandenen Element. Wenn das Attribut nicht vorhanden ist, wird es erstellt.

Mit der folgenden Abfrage wird ein Element in der `"Music"`-Tabelle durch Hinzufügen eines Attributs vom Typ „number“ (`AwardsWon`) und ein Attribut vom Typ „map“ (`AwardDetail`) enthalten.

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Sie können `RETURNING ALL OLD *` hinzufügen, um die Attribute so zurückzugeben, wie sie vor der `Update`-Operation erschienen.

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL OLD *
```

Damit wird Folgendes zurückgegeben:

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

Sie können `RETURNING ALL NEW *` hinzufügen, um die Attribute so zurückzugeben, wie sie nach der `Update`-Operation erschienen.

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL NEW *
```

Damit wird Folgendes zurückgegeben:

```
{
    "Items": [
        {
            "AwardDetail": {
                "M": {
                    "Grammys": {
                        "L": [
                            {
                                "N": "2020"
                            },
                            {
                                "N": "2018"
                            }
                        ]
                    }
                }
            },
            "AwardsWon": {
                "N": "1"
            }
        }
    ]
}
```

Mit der folgenden Abfrage wird ein Element in der `"Music"`-Tabelle durch Anhängen an eine Liste `AwardDetail.Grammys` aktualisiert.

```
UPDATE "Music" 
SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Mit der folgenden Abfrage wird ein Element in der `"Music"`-Tabelle durch Entfernen aus einer Liste `AwardDetail.Grammys` aktualisiert.

```
UPDATE "Music" 
REMOVE AwardDetail.Grammys[2]   
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Mit der folgenden Abfrage wird ein Element in der `"Music"`-Tabelle durch Hinzufügen von `BillBoard` zur Karte `AwardDetail` aktualisiert.

```
UPDATE "Music" 
SET AwardDetail.BillBoard=[2020] 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Die folgende Abfrage aktualisiert ein Element in der `"Music"`-Tabelle durch Hinzufügen des Zeichenfolgensatzattributs `BandMembers`.

```
UPDATE "Music" 
SET BandMembers =<<'member1', 'member2'>> 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Die folgende Abfrage aktualisiert ein Element in der `"Music"`-Tabelle, indem `newbandmember` zum Zeichenfolgensatz `BandMembers` hinzugefügt wird.

```
UPDATE "Music" 
SET BandMembers =set_add(BandMembers, <<'newbandmember'>>) 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

# PartiQL-Delete-Anweisungen für DynamoDB
<a name="ql-reference.delete"></a>

Verwenden der`DELETE`-Anweisung verwenden, um ein vorhandenes Element aus Ihrer Amazon-DynamoDB-Tabelle zu löschen.

**Anmerkung**  
Sie können nur jeweils ein Element löschen. Sie können keine einzelne DynamoDB-PartiQL-Anweisung ausgeben, die mehrere Elemente löscht. Informationen zum Löschen mehrerer Elemente finden Sie unter [Ausführen von Transaktionen mit PartiQL für DynamoDB](ql-reference.multiplestatements.transactions.md) oder [Ausführen von Batchoperationen mit PartiQL für DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntax](#ql-reference.delete.syntax)
+ [Parameters](#ql-reference.delete.parameters)
+ [Rückgabewert](#ql-reference.delete.return)
+ [Beispiele](#ql-reference.delete.examples)

## Syntax
<a name="ql-reference.delete.syntax"></a>

```
DELETE FROM table 
 WHERE condition [RETURNING returnvalues]
 <returnvalues>  ::= ALL OLD *
```

## Parameters
<a name="ql-reference.delete.parameters"></a>

***table***  
(Erforderlich) Die DynamoDB-Tabelle, die das zu löschende Element enthält.

***condition***  
(Erforderlich) Die Auswahlkriterien für das zu löschende Element; diese Bedingung muss auf einen einzelnen Primärschlüsselwert aufgelöst werden.

***returnvalues***  
(Optional) Verwenden Sie `returnvalues`, wenn Sie die Elementattribute so erhalten möchten, wie sie vor dem Löschen dargestellt wurden. Die gültigen Werte sind:   
+ `ALL OLD *`- die Inhalte des alten Elements werden zurückgegeben. 

## Rückgabewert
<a name="ql-reference.delete.return"></a>

Diese Anweisung gibt keinen Wert zurück, es sei denn der `returnvalues`-Parameter ist angegeben.

**Anmerkung**  
Wenn in der DynamoDB-Tabelle kein Element mit demselben Primärschlüssel wie dem des Elements vorhanden ist, für das das DELETE ausgegeben wird, wird SUCCESS zurückgegeben, wobei 0 Elemente gelöscht wurden. Wenn die Tabelle ein Element mit demselben Primärschlüssel enthält, aber die Bedingung in der WHERE-Klausel der DELETE-Anweisung als falsch ausgewertet wird, wird `ConditionalCheckFailedException` zurückgegeben.

## Beispiele
<a name="ql-reference.delete.examples"></a>

Mit der folgenden Abfrage wird ein Element in der Tabelle `"Music"` gelöscht.

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks'
```

Sie können den Parameter `RETURNING ALL OLD *` hinzufügen, um die gelöschten Daten zurückzugeben.

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks' RETURNING ALL OLD *
```

Die `Delete`-Anweisung gibt nun Folgendes zurück:

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

# PartiQL-Insert-Anweisungen für DynamoDB
<a name="ql-reference.insert"></a>

Verwenden Sie die `INSERT`-Anweisung, um einer Tabelle in Amazon DynamoDB ein Element hinzuzufügen.

**Anmerkung**  
Sie können nur ein Element gleichzeitig einfügen. Sie können keine einzelne DynamoDB-PartiQL-Anweisung ausgeben, die mehrere Elemente einfügt. Weitere Informationen zum Einfügen mehrerer Elemente finden Sie unter [Ausführen von Transaktionen mit PartiQL für DynamoDB](ql-reference.multiplestatements.transactions.md) oder [Ausführen von Batchoperationen mit PartiQL für DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntax](#ql-reference.insert.syntax)
+ [Parameters](#ql-reference.insert.parameters)
+ [Rückgabewert](#ql-reference.insert.return)
+ [Beispiele](#ql-reference.insert.examples)

## Syntax
<a name="ql-reference.insert.syntax"></a>

Fügen Sie ein einzelnes Element ein.

```
INSERT INTO table VALUE item
```

## Parameters
<a name="ql-reference.insert.parameters"></a>

***table***  
(erforderlich) Die Tabelle, in der Sie die Daten einfügen möchten. Die Tabelle muss bereits vorhanden sein.

***item***  
(Erforderlich) Ein gültiges DynamoDB Element, das als [PartiQL-Tupel](https://partiql.org/docs.html) gezeigt wird. Sie müssen nur *ein* Element angeben, und bei jedem Attributnamen im Element wird die Groß-/Kleinschreibung beachtet und kann in PartiQL mit *einfachen* Anführungszeichen (`'...'`) gekennzeichnet werden.  
Zeichenfolgenwerte werden in PartiQL auch mit *einfachen* Anführungszeichen (`'...'`) angegeben.

## Rückgabewert
<a name="ql-reference.insert.return"></a>

Diese Anweisung gibt keine Werte zurück.

**Anmerkung**  
Wenn die DynamoDB-Tabelle bereits ein Element mit demselben Primärschlüssel wie der Primärschlüssel des einzufügenden Elements enthält, wird `DuplicateItemException` zurückgegeben.

## Beispiele
<a name="ql-reference.insert.examples"></a>

```
INSERT INTO "Music" value {'Artist' : 'Acme Band','SongTitle' : 'PartiQL Rocks'}
```

# Verwenden von PartiQL-Funktionen mit DynamoDB
<a name="ql-functions"></a>

PartiSQL in Amazon DynamoDB unterstützt die folgenden integrierten Varianten von SQL-Standardfunktionen.

**Anmerkung**  
SQL-Funktionen, die nicht in dieser Liste enthalten sind, werden derzeit in DynamoDB nicht unterstützt.

## Aggregationsfunktionen
<a name="ql-functions.aggregate"></a>
+ [Verwenden der SIZE-Funktion mit PartiQL für Amazon DynamoDB](ql-functions.size.md)

## Konditionale Funktionen
<a name="ql-functions.conditional"></a>
+ [Verwenden der EXISTS-Funktion mit PartiQL für DynamoDB](ql-functions.exists.md)
+ [Verwenden der ATTRIBUTE\$1TYPE-Funktion mit PartiQL für DynamoDB](ql-functions.attribute_type.md)
+ [Verwenden der BEGINS\$1WITH-Funktion mit PartiQL für DynamoDB](ql-functions.beginswith.md)
+ [Verwenden der CONTAINS-Funktion mit PartiQL für DynamoDB](ql-functions.contains.md)
+ [Verwenden der MISSING-Funktion mit PartiQL für DynamoDB](ql-functions.missing.md)

# Verwenden der EXISTS-Funktion mit PartiQL für DynamoDB
<a name="ql-functions.exists"></a>

Sie können EXISTS verwenden, um dieselbe Funktion wie `ConditionCheck` in der [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems)-API auszuführen. Die EXISTS-Funktion kann nur in Transaktionen verwendet werden.

Gibt bei Vorliegen eines Werts `TRUE` zurück, wenn der Wert eine nicht-leere Sammlung ist. Gibt andernfalls `FALSE` zurück.

**Anmerkung**  
Diese Funktion kann nur in Transaktionsoperationen verwendet werden.

## Syntax
<a name="ql-functions.exists.syntax"></a>

```
EXISTS ( statement )
```

## Argumente
<a name="ql-functions.exists.arguments"></a>

*statement*  
(Erforderlich) Die SELECT-Anweisung, die die Funktion auswertet.  
Die SELECT-Anweisung muss einen vollständigen Primärschlüssel und eine andere Bedingung angeben.

## Rückgabetyp
<a name="ql-functions.exists.return-type"></a>

`bool`

## Beispiele
<a name="ql-functions.exists.examples"></a>

```
EXISTS(
    SELECT * FROM "Music" 
    WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks')
```

# Verwenden der BEGINS\$1WITH-Funktion mit PartiQL für DynamoDB
<a name="ql-functions.beginswith"></a>

Gibt `TRUE` zurück, wenn das angegebene Attribut mit einer bestimmten Teilzeichenfolge beginnt.

## Syntax
<a name="ql-functions.beginswith.syntax"></a>

```
begins_with(path, value )
```

## Argumente
<a name="ql-functions.beginswith.arguments"></a>

*path*  
(Erforderlich) Der zu verwendende Attributname oder Dokumentpfad.

*value*  
(Erforderlich) Die Zeichenfolge, nach der gesucht werden soll.

## Rückgabetyp
<a name="ql-functions.beginswith.return-type"></a>

`bool`

## Beispiele
<a name="ql-functions.beginswith.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND begins_with("Address", '7834 24th')
```

# Verwenden der MISSING-Funktion mit PartiQL für DynamoDB
<a name="ql-functions.missing"></a>

Gibt `TRUE` zurück, wenn das Element das angegebene Attribut nicht enthält. Mit dieser Funktion können nur Gleichheits- und Ungleichheitsoperatoren verwendet werden.

## Syntax
<a name="ql-functions.missing.syntax"></a>

```
 attributename IS | IS NOT  MISSING 
```

## Argumente
<a name="ql-functions.missing.arguments"></a>

*attributename*  
(Erforderlich) Der Attributname, nach dem Sie suchen möchten.

## Rückgabetyp
<a name="ql-functions.missing.return-type"></a>

`bool`

## Beispiele
<a name="ql-functions.missing.examples"></a>

```
SELECT * FROM Music WHERE "Awards" is MISSING
```

# Verwenden der ATTRIBUTE\$1TYPE-Funktion mit PartiQL für DynamoDB
<a name="ql-functions.attribute_type"></a>

Gibt `TRUE` zurück, wenn das Attribut am angegebenen Pfad einen bestimmten Datentyp hat.

## Syntax
<a name="ql-functions.attribute_type.syntax"></a>

```
attribute_type( attributename, type )
```

## Argumente
<a name="ql-functions.attribute_type.arguments"></a>

*attributename*  
(Erforderlich) Der zu verwendende Attributname.

*type*  
(Erforderlich) Der Attributtyp, nach dem geprüft werden soll. Eine Liste der gültigen Werte finden Sie unter DynamoDB [attribute\$1type](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

## Rückgabetyp
<a name="ql-functions.attribute_type.return-type"></a>

`bool`

## Beispiele
<a name="ql-functions.attribute_type.examples"></a>

```
SELECT * FROM "Music" WHERE attribute_type("Artist", 'S')
```

# Verwenden der CONTAINS-Funktion mit PartiQL für DynamoDB
<a name="ql-functions.contains"></a>

Gibt `TRUE` zurück, wenn das vom Pfad angegebene Attribut Folgendes ist:
+ Eine Zeichenfolge, die eine bestimmte Teilzeichenfolge enthält 
+ Einen Satz, der ein bestimmtes Element innerhalb des Satzes enthält

Weitere Informationen finden Sie im Thema zur DynamoDB-[Contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions)-Funktion. 

## Syntax
<a name="ql-functions.contains.syntax"></a>

```
contains( path, substring )
```

## Argumente
<a name="ql-functions.contains.arguments"></a>

*path*  
(Erforderlich) Der zu verwendende Attributname oder Dokumentpfad.

*substring*  
(Erforderlich) Die Attribut-Teilzeichenfolge oder das Satz-Element, nach dem Sie suchen möchten Weitere Informationen finden Sie im Thema zur DynamoDB-[Contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions)-Funktion.

## Rückgabetyp
<a name="ql-functions.contains.return-type"></a>

`bool`

## Beispiele
<a name="ql-functions.contains.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND contains("Address", 'Kirkland')
```

# Verwenden der SIZE-Funktion mit PartiQL für Amazon DynamoDB
<a name="ql-functions.size"></a>

Gibt eine Zahl zurück, die für die Größe eines Attributs in Bytes steht. Die folgenden sind gültige Datentypen, die mit Größe verwendet werden können. Weitere Informationen finden Sie in der DynamoDB-[size](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions)-Funktion.

## Syntax
<a name="ql-functions.size.syntax"></a>

```
size( path)
```

## Argumente
<a name="ql-functions.size.arguments"></a>

*path*  
(Erforderlich) Der Attributname oder Dokumentpfad.   
Weitere Informationen zu unterstützten Typen finden Sie im Thema DynamoDB-[SIZE](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions)-Funktion.

## Rückgabetyp
<a name="ql-functions.size.return-type"></a>

`int`

## Beispiele
<a name="ql-functions.size.examples"></a>

```
 SELECT * FROM "Orders" WHERE "OrderID"=1 AND size("Image") >300
```

# PartiQL-Arithmetik-, Vergleichs- und logische Operatoren für DynamoDB
<a name="ql-operators"></a>

PartiSQL in Amazon DynamoDB unterstützt die folgenden [SQL-Standardoperatoren](https://www.w3schools.com/sql/sql_operators.asp).

**Anmerkung**  
SQL-Operatoren, die nicht in dieser Liste enthalten sind, werden derzeit in DynamoDB nicht unterstützt.

## Arithmetische Operatoren
<a name="ql-operators.arithmetic"></a>


****  

| Operator | Description | 
| --- | --- | 
| \$1 | Addition | 
| - | Subtraktion | 

## Vergleichsoperatoren
<a name="ql-operators.comparison"></a>


****  

| Operator | Description | 
| --- | --- | 
| = | gleich | 
| <> | nicht gleich | 
| \$1= | nicht gleich | 
| > | Größer als | 
| < | Kleiner als | 
| >= | Größer als oder gleich | 
| <= | Kleiner als oder gleich | 

## Logische Operatoren
<a name="ql-operators.logical"></a>


****  

| Operator | Description | 
| --- | --- | 
| AND | TRUE, wenn alle durch AND getrennten Bedingungen TRUE sind | 
| BETWEEN |  `TRUE`, wenn der Operand innerhalb des Vergleichsbereichs liegt. Dieser Operator umfasst die Unter- und Obergrenze der Operanden, auf die Sie ihn anwenden.  | 
| IN | `TRUE`wenn der Operand einem aus einer Liste von Ausdrücken entspricht (bei maximal 50 Hash-Attributwerten oder bei maximal 100 Nichtschlüsselattributwerten). Die Ergebnisse werden in Seiten mit bis zu 10 Elementen zurückgegeben. Wenn die `IN` Liste mehr Werte enthält, müssen Sie die in der Antwort `NextToken` zurückgegebenen Werte verwenden, um nachfolgende Seiten abzurufen. | 
| IS | TRUE, wenn der Operand ein bestimmter PartiQL-Datentyp ist, einschließlich NULL oder MISSING | 
| NOT | Kehrt den Wert eines gegebenen booleschen Ausdrucks um | 
| OR | TRUE, wenn eine der von OR getrennten Bedingungen TRUE ist | 

Weitere Informationen zu logischen Operatoren finden Sie unter [Durchführen von Vergleichen](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Comparators) und [Logische Auswertungen](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.LogicalEvaluations).

# Ausführen von Transaktionen mit PartiQL für DynamoDB
<a name="ql-reference.multiplestatements.transactions"></a>

In diesem Abschnitt wird die Verwendung von Transaktionen mit PartiQL für DynamoDB beschrieben. PartiQL-Transaktionen sind auf insgesamt 100 Anweisungen (Aktionen) begrenzt.

Weitere Informationen zu DynamoDB-Transaktionen finden Sie unter [Verwalten komplexer Workflows mit DynamoDB-Transaktionen](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html).

**Anmerkung**  
Die gesamte Transaktion muss entweder aus Leseanweisungen oder Schreibanweisungen bestehen. Sie können nicht beides in einer Transaktion mischen. Die EXISTS-Funktion ist eine Ausnahme. Sie können es verwenden, um den Zustand bestimmter Attribute des Elements auf ähnliche Weise wie `ConditionCheck` bei der [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems)API-Operation zu überprüfen.

**Topics**
+ [Syntax](#ql-reference.multiplestatements.transactions.syntax)
+ [Parameters](#ql-reference.multiplestatements.transactions.parameters)
+ [Rückgabewerte](#ql-reference.multiplestatements.transactions.return)
+ [Beispiele](#ql-reference.multiplestatements.transactions.examples)

## Syntax
<a name="ql-reference.multiplestatements.transactions.syntax"></a>

```
[
   {
      "Statement":" statement ",
      "Parameters":[
         {
            " parametertype " : " parametervalue "
         }, ...]
   } , ...
]
```

## Parameters
<a name="ql-reference.multiplestatements.transactions.parameters"></a>

***statement***  
(Erforderlich) Eine unterstützte PartiQL für DynamoDB-Anweisung.  
Die gesamte Transaktion muss entweder aus Leseanweisungen oder Schreibanweisungen bestehen. Sie können nicht beides in einer Transaktion mischen.

***parametertype***  
(Optional) Ein DynamoDB-Typ, wenn Parameter bei der Angabe der PartiQL-Anweisung verwendet wurden.

***parametervalue***  
(Optional) Ein Parameterwert, wenn Parameter bei der Angabe der PartiQL-Anweisung verwendet wurden.

## Rückgabewerte
<a name="ql-reference.multiplestatements.transactions.return"></a>

Diese Anweisung gibt keine Werte für Schreibvorgänge (INSERT, UPDATE oder DELETE) zurück. Sie gibt jedoch verschiedene Werte für Lesevorgänge (SELECT) basierend auf den in der WHERE-Klausel angegebenen Bedingungen zurück.

**Anmerkung**  
Wenn eine der Singleton-Operationen INSERT, UPDATE oder DELETE einen Fehler zurückgibt, werden die Transaktionen mit einer `TransactionCanceledException`-Ausnahme abgebrochen, und der Code für den Abbruchgrund enthält die Fehler der einzelnen Singleton-Operationen.

## Beispiele
<a name="ql-reference.multiplestatements.transactions.examples"></a>

Im folgenden Beispiel werden mehrere Anweisungen als Transaktion ausgeführt.

------
#### [ AWS CLI ]

1. Speichern Sie den folgenden JSON-Code in einer Datei mit dem Namen partiql.json. 

   ```
   [
       {
           "Statement": "EXISTS(SELECT * FROM \"Music\" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is  MISSING)"
       },
       {
           "Statement": "INSERT INTO Music value {'Artist':?,'SongTitle':'?'}",
           "Parameters": [{\"S\": \"Acme Band\"}, {\"S\": \"Best Song\"}]
       },
       {
           "Statement": "UPDATE \"Music\" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist='Acme Band' and SongTitle='PartiQL Rocks'"
       }
   ]
   ```

1. Führen Sie in der Eingabeaufforderung den folgenden Befehl aus.

   ```
   aws dynamodb execute-transaction --transact-statements  file://partiql.json
   ```

------
#### [ Java ]

```
public class DynamoDBPartiqlTransaction {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2");
        
        try {
            // Create ExecuteTransactionRequest
            ExecuteTransactionRequest executeTransactionRequest = createExecuteTransactionRequest();
            ExecuteTransactionResult executeTransactionResult = dynamoDB.executeTransaction(executeTransactionRequest);
            System.out.println("ExecuteTransaction successful.");
            // Handle executeTransactionResult

        } catch (Exception e) {
            handleExecuteTransactionErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {
        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static ExecuteTransactionRequest createExecuteTransactionRequest() {
        ExecuteTransactionRequest request = new ExecuteTransactionRequest();
        
        // Create statements
        List<ParameterizedStatement> statements = getPartiQLTransactionStatements();

        request.setTransactStatements(statements);
        return request;
    }

    private static List<ParameterizedStatement> getPartiQLTransactionStatements() {
        List<ParameterizedStatement> statements = new ArrayList<ParameterizedStatement>();

        statements.add(new ParameterizedStatement()
                               .withStatement("EXISTS(SELECT * FROM "Music" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is  MISSING)"));

        statements.add(new ParameterizedStatement()
                               .withStatement("INSERT INTO "Music" value {'Artist':'?','SongTitle':'?'}")
                               .withParameters(new AttributeValue("Acme Band"),new AttributeValue("Best Song")));

        statements.add(new ParameterizedStatement()
                               .withStatement("UPDATE "Music" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist='Acme Band' and SongTitle='PartiQL Rocks'"));

        return statements;
    }

    // Handles errors during ExecuteTransaction execution. Use recommendations in error messages below to add error handling specific to 
    // your application use-case.
    private static void handleExecuteTransactionErrors(Exception exception) {
        try {
            throw exception;
        } catch (TransactionCanceledException tce) {
            System.out.println("Transaction Cancelled, implies a client issue, fix before retrying. Error: " + tce.getErrorMessage());
        } catch (TransactionInProgressException tipe) {
            System.out.println("The transaction with the given request token is already in progress, consider changing " +
                "retry strategy for this type of error. Error: " + tipe.getErrorMessage());
        } catch (IdempotentParameterMismatchException ipme) {
            System.out.println("Request rejected because it was retried with a different payload but with a request token that was already used, " +
                "change request token for this payload to be accepted. Error: " + ipme.getErrorMessage());
        } catch (Exception e) {
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " + 
                "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " + 
                ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " + 
                "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

Das folgende Beispiel zeigt die verschiedenen Rückgabewerte, wenn DynamoDB-Elemente mit unterschiedlichen Bedingungen liest, die in der WHERE-Klausel angegeben sind.

------
#### [ AWS CLI ]

1. Speichern Sie den folgenden JSON-Code in einer Datei mit dem Namen partiql.json.

   ```
   [
       // Item exists and projected attribute exists
       {
           "Statement": "SELECT * FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'"
       },
       // Item exists but projected attributes do not exist
       {
           "Statement": "SELECT non_existent_projected_attribute FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'"
       },
       // Item does not exist
       {
           "Statement": "SELECT * FROM "Music" WHERE Artist='No One I Know' and SongTitle='Call You Today'"
       }
   ]
   ```

1.  Folgenden Befehl in der Eingabeaufforderung eingeben.

   ```
   aws dynamodb execute-transaction --transact-statements  file://partiql.json
   ```

1. Die folgende Antwort wird ausgegeben:

   ```
   {
       "Responses": [
           // Item exists and projected attribute exists
           {
               "Item": {
                   "Artist":{
                       "S": "No One You Know"
                   },
                   "SongTitle":{
                       "S": "Call Me Today"
                   }    
               }
           },
           // Item exists but projected attributes do not exist
           {
               "Item": {}
           },
           // Item does not exist
           {}
       ]
   }
   ```

------

# Ausführen von Batchoperationen mit PartiQL für DynamoDB
<a name="ql-reference.multiplestatements.batching"></a>

In diesem Abschnitt wird die Verwendung von Stapel-Anweisungen mit PartiQL für DynamoDB beschrieben.

**Anmerkung**  
Der gesamte Stapel muss entweder aus Leseanweisungen oder Schreibanweisungen bestehen; Sie können nicht beides in einem Stapel mischen.
`BatchExecuteStatement` und `BatchWriteItem` können nicht mehr als 25 Anweisungen pro Stapel ausführen.
`BatchExecuteStatement` verwendet `BatchGetItem`, was eine Liste von Primärschlüsseln in separaten Anweisungen verarbeitet.

**Topics**
+ [Syntax](#ql-reference.multiplestatements.batching.syntax)
+ [Parameters](#ql-reference.multiplestatements.batching.parameters)
+ [Beispiele](#ql-reference.multiplestatements.batching.examples)

## Syntax
<a name="ql-reference.multiplestatements.batching.syntax"></a>

```
[
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#9StkWHYTxm7x2AqSXcrfu7' AND sk = 'info'"
  },
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#isC2ChceGbxHgESc4szoTE' AND sk = 'info'"
  }
]
```

```
[
   {
      "Statement":" statement ",
      "Parameters":[
         {
            " parametertype " : " parametervalue "
         }, ...]
   } , ...
]
```

## Parameters
<a name="ql-reference.multiplestatements.batching.parameters"></a>

***statement***  
(Erforderlich) Eine unterstützte PartiQL für DynamoDB-Anweisung.  
+ Der gesamte Stapel muss entweder aus Leseanweisungen oder Schreibanweisungen bestehen; Sie können nicht beides in einem Stapel mischen.
+ `BatchExecuteStatement` und `BatchWriteItem` können nicht mehr als 25 Anweisungen pro Stapel ausführen.

***parametertype***  
(Optional) Ein DynamoDB-Typ, wenn Parameter bei der Angabe der PartiQL-Anweisung verwendet wurden.

***parametervalue***  
(Optional) Ein Parameterwert, wenn Parameter bei der Angabe der PartiQL-Anweisung verwendet wurden.

## Beispiele
<a name="ql-reference.multiplestatements.batching.examples"></a>

------
#### [ AWS CLI ]

1. Speichern Sie den folgenden JSON in einer Datei namens partiql.json

   ```
   [
      {
   	 "Statement": "INSERT INTO Music VALUE {'Artist':?,'SongTitle':?}",
   	  "Parameters": [{"S": "Acme Band"}, {"S": "Best Song"}]
   	},
   	{
   	 "Statement": "UPDATE Music SET AwardsWon=1, AwardDetail={'Grammys':[2020, 2018]} WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
       }
   ]
   ```

1. Führen Sie in der Eingabeaufforderung den folgenden Befehl aus.

   ```
   aws dynamodb batch-execute-statement  --statements  file://partiql.json
   ```

------
#### [ Java ]

```
public class DynamoDBPartiqlBatch {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2");
        
        try {
            // Create BatchExecuteStatementRequest
            BatchExecuteStatementRequest batchExecuteStatementRequest = createBatchExecuteStatementRequest();
            BatchExecuteStatementResult batchExecuteStatementResult = dynamoDB.batchExecuteStatement(batchExecuteStatementRequest);
            System.out.println("BatchExecuteStatement successful.");
            // Handle batchExecuteStatementResult

        } catch (Exception e) {
            handleBatchExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {

        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static BatchExecuteStatementRequest createBatchExecuteStatementRequest() {
        BatchExecuteStatementRequest request = new BatchExecuteStatementRequest();

        // Create statements
        List<BatchStatementRequest> statements = getPartiQLBatchStatements();

        request.setStatements(statements);
        return request;
    }

    private static List<BatchStatementRequest> getPartiQLBatchStatements() {
        List<BatchStatementRequest> statements = new ArrayList<BatchStatementRequest>();

        statements.add(new BatchStatementRequest()
                               .withStatement("INSERT INTO Music value {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"));

        statements.add(new BatchStatementRequest()
                               .withStatement("UPDATE Music set AwardDetail.BillBoard=[2020] where Artist='Acme Band' and SongTitle='PartiQL Rocks'"));

        return statements;
    }

    // Handles errors during BatchExecuteStatement execution. Use recommendations in error messages below to add error handling specific to 
    // your application use-case.
    private static void handleBatchExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (Exception e) {
            // There are no API specific errors to handle for BatchExecuteStatement, common DynamoDB API errors are handled below
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " + 
                "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " + 
                ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " + 
                "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

# IAM-Sicherheitsrichtlinien mit PartiQL für DynamoDB
<a name="ql-iam"></a>

Die folgenden Berechtigungen sind erforderlich:
+ Um Elemente mit PartiQL für DynamoDB zu lesen, müssen Sie über die `dynamodb:PartiQLSelect`-Berechtigung für die Tabelle oder den Index verfügen.
+ Um Elemente mit PartiQL für DynamoDB einzufügen, müssen Sie über die `dynamodb:PartiQLInsert`-Berechtigung für die Tabelle oder den Index verfügen.
+ Um Elemente mit PartiQL für DynamoDB zu aktualisieren, müssen Sie über die `dynamodb:PartiQLUpdate`-Berechtigung für die Tabelle oder den Index verfügen.
+ Um Elemente mit PartiQL für DynamoDB zu löschen, müssen Sie über die `dynamodb:PartiQLDelete`-Berechtigung für die Tabelle oder den Index verfügen.

## Beispiel: Alle PartiQL for DynamoDB-Anweisungen (Select/Insert/Update/Delete) in einer Tabelle zulassen
<a name="access-policy-ql-iam-example1"></a>

Mit der folgenden IAM-Richtlinie werden alle PartiQL für DynamoDB-Anweisungen in einer Tabelle erteilt. 

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Beispiel: PartiQL für DynamoDB-Auswahlanweisungen für eine Tabelle zulassen
<a name="access-policy-ql-iam-example2"></a>

Mit der folgenden IAM-Richtlinie werden die Berechtigungen zum Ausführen der `select`-Anweisung für eine bestimmte Tabelle erteilt

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Beispiel: PartiQL für DynamoDB-Einfügeanweisungen für einen Index zulassen
<a name="access-policy-ql-iam-example3"></a>

Mit der folgenden IAM-Richtlinie werden die Berechtigungen zum Ausführen des `insert`-Anweisung auf einen bestimmten Index. 

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music/index/index1"
         ]
      }
   ]
}
```

------

## Beispiel: PartiQL für DynamoDB-Transaktionsanweisungen nur für eine Tabelle zulassen
<a name="access-policy-ql-iam-example4"></a>

Mit der folgenden IAM-Richtlinie werden die Berechtigungen nur zum Ausführen transaktionaler Anweisungen für eine bestimmte Tabelle erteilt. 

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      }
   ]
}
```

------

## Beispiel: Erlauben Sie PartiQL für nicht-transaktionale DynamoDB-Lese- und Schreibvorgänge und blockieren Sie PartiQL-transaktionale Lese- und Schreibvorgänge in einer Tabelle.
<a name="access-policy-ql-iam-example5"></a>

 Die folgende IAM-Richtlinie gewährt Berechtigungen zum Ausführen von nicht-transaktionalen Lese-/Schreibvorgängen in PartiQL für DynamoDB, während transaktionale Lese-/Schreibvorgänge in PartiQL für DynamoDB blockiert werden.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Beispiel: In PartiQL für DynamoDB Select-Anweisungen erlauben und vollständige Tabellenscan-Anweisungen verweigern
<a name="access-policy-ql-iam-example6"></a>

Mit der folgenden IAM-Richtlinie werden die Berechtigungen zum Ausführen der `select`-Anweisung für eine bestimmte Tabelle beim Blockieren von `select`-Anweisungen, die zu einem vollständigen Tabellenscan führen.

------
#### [ JSON ]

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ],
         "Condition":{
            "Bool":{
               "dynamodb:FullTableScan":[
                  "true"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ]
      }
   ]
}
```

------

# Arbeiten mit Elementen: Java
<a name="JavaDocumentAPIItemCRUD"></a>

Sie können die AWS SDK für Java Dokument-API verwenden, um typische Erstellungs-, Lese-, Aktualisierungs- und Löschvorgänge (CRUD) für Amazon DynamoDB DynamoDB-Elemente in einer Tabelle durchzuführen.

**Anmerkung**  
Das SDK für Java stellt auch ein Objektpersistenzmodell bereit, mit dem Sie Ihre clientseitigen Klassen DynamoDB-Tabellen zuordnen können. Mit diesem Ansatz können Sie die Codemenge, die Sie schreiben müssen, verringern. Weitere Informationen finden Sie unter [Java 1.x: Dynamo DBMapper](DynamoDBMapper.md).

Dieser Abschnitt enthält Java-Beispiele zur Durchführung verschiedener Java-Dokument-API-Elementaktionen und mehrere vollständige Arbeitsbeispiele.

**Topics**
+ [Einfügen eines Elements](#PutDocumentAPIJava)
+ [Abrufen eines Elements](#JavaDocumentAPIGetItem)
+ [Batch Write: Einfügen und Löschen mehrerer Elemente](#BatchWriteDocumentAPIJava)
+ [Batch Get: Abrufen mehrerer Elemente](#JavaDocumentAPIBatchGetItem)
+ [Aktualisieren eines Elements](#JavaDocumentAPIItemUpdate)
+ [Löschen eines Elements](#DeleteMidLevelJava)
+ [Beispiel: CRUD-Operationen mit der AWS SDK für Java Dokument-API](JavaDocumentAPICRUDExample.md)
+ [Beispiel: Batch-Operationen mithilfe der AWS SDK für Java Dokument-API](batch-operation-document-api-java.md)
+ [Beispiel: Umgang mit binären Typattributen mithilfe der AWS SDK für Java Dokument-API](JavaDocumentAPIBinaryTypeExample.md)

## Einfügen eines Elements
<a name="PutDocumentAPIJava"></a>

Die `putItem`-Methode speichert ein Element in einer Tabelle. Wenn das Element bereits vorhanden ist, wird das ganze Element ersetzt. Anstatt das gesamte Element zu ersetzen und nur spezifische Attribute zu aktualisieren, können Sie die Methode `updateItem` verwenden. Weitere Informationen finden Sie unter [Aktualisieren eines Elements](#JavaDocumentAPIItemUpdate). 

------
#### [ Java v2 ]

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import java.util.HashMap;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 *
 * To place items into an Amazon DynamoDB table using the AWS SDK for Java V2,
 * its better practice to use the
 * Enhanced Client. See the EnhancedPutItem example.
 */
public class PutItem {
    public static void main(String[] args) {
        final String usage = """

                Usage:
                    <tableName> <key> <keyVal> <albumtitle> <albumtitleval> <awards> <awardsval> <Songtitle> <songtitleval>

                Where:
                    tableName - The Amazon DynamoDB table in which an item is placed (for example, Music3).
                    key - The key used in the Amazon DynamoDB table (for example, Artist).
                    keyval - The key value that represents the item to get (for example, Famous Band).
                    albumTitle - The Album title (for example, AlbumTitle).
                    AlbumTitleValue - The name of the album (for example, Songs About Life ).
                    Awards - The awards column (for example, Awards).
                    AwardVal - The value of the awards (for example, 10).
                    SongTitle - The song title (for example, SongTitle).
                    SongTitleVal - The value of the song title (for example, Happy Day).
                **Warning** This program will  place an item that you specify into a table!
                """;

        if (args.length != 9) {
            System.out.println(usage);
            System.exit(1);
        }

        String tableName = args[0];
        String key = args[1];
        String keyVal = args[2];
        String albumTitle = args[3];
        String albumTitleValue = args[4];
        String awards = args[5];
        String awardVal = args[6];
        String songTitle = args[7];
        String songTitleVal = args[8];

        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();

        putItemInTable(ddb, tableName, key, keyVal, albumTitle, albumTitleValue, awards, awardVal, songTitle,
                songTitleVal);
        System.out.println("Done!");
        ddb.close();
    }

    public static void putItemInTable(DynamoDbClient ddb,
            String tableName,
            String key,
            String keyVal,
            String albumTitle,
            String albumTitleValue,
            String awards,
            String awardVal,
            String songTitle,
            String songTitleVal) {

        HashMap<String, AttributeValue> itemValues = new HashMap<>();
        itemValues.put(key, AttributeValue.builder().s(keyVal).build());
        itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build());
        itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build());
        itemValues.put(awards, AttributeValue.builder().s(awardVal).build());

        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(itemValues)
                .build();

        try {
            PutItemResponse response = ddb.putItem(request);
            System.out.println(tableName + " was successfully updated. The request id is "
                    + response.responseMetadata().requestId());

        } catch (ResourceNotFoundException e) {
            System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName);
            System.err.println("Be sure that it exists and that you've typed its name correctly!");
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
}
```

------
#### [ Java v1 ]

Dazu gehen Sie wie folgt vor: 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse, um die Tabelle zu repräsentieren, mit der Sie arbeiten möchten.

1. Erstellen Sie eine Instance der `Item`-Klasse, um das neue Element zu repräsentieren. Sie müssen den Primärschlüssel und die Attribute für das neue Element angeben.

1. Rufen Sie die `putItem`-Methode des `Table`-Objekts auf, das das `Item` verwendet, das Sie im vorangegangenen Schritt erstellt haben.

Im folgenden Java-Codebeispiel werden die vorherigen Aufgaben veranschaulicht. Der Code schreibt ein neues Element in die `ProductCatalog`-Tabelle.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

// Build a list of related items
List<Number> relatedItems = new ArrayList<Number>();
relatedItems.add(341);
relatedItems.add(472);
relatedItems.add(649);

//Build a map of product pictures
Map<String, String> pictures = new HashMap<String, String>();
pictures.put("FrontView", "http://example.com/products/123_front.jpg");
pictures.put("RearView", "http://example.com/products/123_rear.jpg");
pictures.put("SideView", "http://example.com/products/123_left_side.jpg");

//Build a map of product reviews
Map<String, List<String>> reviews = new HashMap<String, List<String>>();

List<String> fiveStarReviews = new ArrayList<String>();
fiveStarReviews.add("Excellent! Can't recommend it highly enough!  Buy it!");
fiveStarReviews.add("Do yourself a favor and buy this");
reviews.put("FiveStar", fiveStarReviews);

List<String> oneStarReviews = new ArrayList<String>();
oneStarReviews.add("Terrible product!  Do not buy this.");
reviews.put("OneStar", oneStarReviews);

// Build the item
Item item = new Item()
    .withPrimaryKey("Id", 123)
    .withString("Title", "Bicycle 123")
    .withString("Description", "123 description")
    .withString("BicycleType", "Hybrid")
    .withString("Brand", "Brand-Company C")
    .withNumber("Price", 500)
    .withStringSet("Color",  new HashSet<String>(Arrays.asList("Red", "Black")))
    .withString("ProductCategory", "Bicycle")
    .withBoolean("InStock", true)
    .withNull("QuantityOnHand")
    .withList("RelatedItems", relatedItems)
    .withMap("Pictures", pictures)
    .withMap("Reviews", reviews);

// Write the item to the table
PutItemOutcome outcome = table.putItem(item);
```

Im vorangegangenen Beispiel verfügt das Element über Attribute, die skalar sind (`String`, `Number`, `Boolean`, `Null`), Sätze (`String Set`) sowie Dokumenttypen (`List`, `Map`).

------

### Angeben eines optionalen Parameters
<a name="PutItemJavaDocumentAPIOptions"></a>

Neben den erforderlichen Parametern können Sie auch optionale Parameter für die `putItem`-Methode angeben. Zum Beispiel verwendet das folgende Java-Codebeispiel einen optionalen Parameter, um eine Bedingung für das Hochladen des Elements anzugeben. Wenn die von Ihnen angegebene Bedingung nicht erfüllt ist, wird eine ausgelöst. AWS SDK für Java `ConditionalCheckFailedException` Das Codebeispiel gibt die folgenden optionalen Parameter in der `putItem`-Methode an:
+ Ein `ConditionExpression`, der die Bedingungen für die Anforderung definiert. In dem Codebeispiel ist die Bedingung definiert, zu der das vorhandene Element mit demselben Primärschlüssel nur dann ersetzt wird, wenn es über ein ISBN-Attribut verfügt, das mit einem bestimmten Wert übereinstimmt. 
+ Eine Zuordnung für `ExpressionAttributeValues`, die in der Bedingung verwendet wird. In diesem Fall ist nur eine Ersetzung erforderlich: Der Platzhalter `:val` im Bedingungsausdruck wird zur Laufzeit durch den tatsächlichen zu prüfenden ISBN-Wert ersetzt.

Im folgenden Beispiel wird ein neues Buchelement mit diesen optionalen Parameter hinzugefügt.

**Example**  

```
Item item = new Item()
    .withPrimaryKey("Id", 104)
    .withString("Title", "Book 104 Title")
    .withString("ISBN", "444-4444444444")
    .withNumber("Price", 20)
    .withStringSet("Authors",
        new HashSet<String>(Arrays.asList("Author1", "Author2")));

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val", "444-4444444444");

PutItemOutcome outcome = table.putItem(
    item,
    "ISBN = :val", // ConditionExpression parameter
    null,          // ExpressionAttributeNames parameter - we're not using it for this example
    expressionAttributeValues);
```

### PutItem und JSON-Dokumente
<a name="PutItemJavaDocumentAPI.JSON"></a>

Sie können ein JSON-Dokument in einer DynamoDB-Tabelle als Attribut speichern. Verwenden Sie dazu die `withJSON`-Methode `Item`. Diese Methode analysiert das JSON-Dokument und ordnet jedes Element einem nativen DynamoDB-Datentyp zu.

Angenommen, Sie möchten das folgende JSON-Dokument speichern, welches Anbieter enthält, die Bestellungen für ein bestimmtes Produkt erfüllen können.

**Example**  

```
{
    "V01": {
        "Name": "Acme Books",
        "Offices": [ "Seattle" ]
    },
    "V02": {
        "Name": "New Publishers, Inc.",
        "Offices": ["London", "New York"
        ]
    },
    "V03": {
        "Name": "Better Buy Books",
        "Offices": [ "Tokyo", "Los Angeles", "Sydney"
        ]
    }
}
```

Sie können die `withJSON`-Methode verwenden, um es in der `ProductCatalog`-Tabelle in einem `Map`´-Attribut mit dem Namen `VendorInfo` zu speichern. Das folgende Java-Codebeispiel veranschaulicht dies.

```
// Convert the document into a String.  Must escape all double-quotes.
String vendorDocument = "{"
    + "    \"V01\": {"
    + "        \"Name\": \"Acme Books\","
    + "        \"Offices\": [ \"Seattle\" ]"
    + "    },"
    + "    \"V02\": {"
    + "        \"Name\": \"New Publishers, Inc.\","
    + "        \"Offices\": [ \"London\", \"New York\"" + "]" + "},"
    + "    \"V03\": {"
    + "        \"Name\": \"Better Buy Books\","
    +          "\"Offices\": [ \"Tokyo\", \"Los Angeles\", \"Sydney\""
    + "            ]"
    + "        }"
    + "    }";

Item item = new Item()
    .withPrimaryKey("Id", 210)
    .withString("Title", "Book 210 Title")
    .withString("ISBN", "210-2102102102")
    .withNumber("Price", 30)
    .withJSON("VendorInfo", vendorDocument);

PutItemOutcome outcome = table.putItem(item);
```

## Abrufen eines Elements
<a name="JavaDocumentAPIGetItem"></a>

Um ein einzelnes Element abzurufen, verwenden Sie die `getItem`-Methode eines `Table`-Objekts. Dazu gehen Sie wie folgt vor: 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse, um die Tabelle zu repräsentieren, mit der Sie arbeiten möchten.

1. Rufen Sie die `getItem`-Methode für die `Table`-Instance auf. Sie müssen den Primärschlüssel des Elements angeben, das Sie abrufen möchten.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht. Im Codebeispiel wird das Element abgerufen, das den angegebenen Partitionsschlüssel aufweist.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

Item item = table.getItem("Id", 210);
```

### Angeben eines optionalen Parameters
<a name="GetItemJavaDocumentAPIOptions"></a>

Neben den erforderlichen Parametern können Sie auch optionale Parameter für die `getItem`-Methode angeben. Zum Beispiel verwendet das folgende Java-Codebeispiel eine optionale Methode zum Abrufen nur einer bestimmten Liste von Attributen und zum Angeben von Strongly Consistent-Lesevorgängen. (Weitere Informationen zur Lesekonsistenz finden Sie unter [DynamoDB-Lesekonsistenz](HowItWorks.ReadConsistency.md).)

Sie können einen `ProjectionExpression` verwenden, um nur spezifische Attribute oder Elemente anstelle eines ganzen Elements abzurufen. Ein `ProjectionExpression` kann Attribute auf oberster Ebene oder verschachtelte Attribute mithilfe von Dokumentpfaden angeben. Weitere Informationen finden Sie unter [Verwenden von Projektionsausdrücken in DynamoDB](Expressions.ProjectionExpressions.md).

Mit den Parametern der `getItem`-Methode kann keine Read Consistency angegeben werden. Sie können jedoch eine `GetItemSpec` erstellen, die vollständigen Zugriff auf die Eingaben für die `GetItem`-Low-Level-Operation bietet. Durch das Codebeispiel unten wird eine `GetItemSpec` erstellt. Es verwendet diese Spezifikation als Eingabe für die `getItem`-Methode.

**Example**  

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 206)
    .withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar")
    .withConsistentRead(true);

Item item = table.getItem(spec);

System.out.println(item.toJSONPretty());
```

 Um ein `Item` in einem vom Menschen lesbaren Format zu drucken, verwenden Sie die Methode `toJSONPretty`. Die Ausgabe aus dem vorherigen Beispiel sieht wie folgt aus.

```
{
  "RelatedItems" : [ 341 ],
  "Reviews" : {
    "FiveStar" : [ "Excellent! Can't recommend it highly enough! Buy it!", "Do yourself a favor and buy this" ]
  },
  "Id" : 123,
  "Title" : "20-Bicycle 123"
}
```

### GetItem und JSON-Dokumente
<a name="GetItemJavaDocumentAPI.JSON"></a>

Im Abschnitt [PutItem und JSON-Dokumente](#PutItemJavaDocumentAPI.JSON) haben Sie ein JSON-Dokument in einem `Map`-Attribut mit dem Namen `VendorInfo` gespeichert. Sie können die `getItem`-Methode verwenden, um das gesamte Dokument im JSON-Format abzurufen. Sie können auch die Dokumentpfadnotation verwenden, um nur einige der Elemente des Dokuments abzurufen. Das folgende Java-Codebeispiel veranschaulicht diese Vorgehensweisen.

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 210);

System.out.println("All vendor info:");
spec.withProjectionExpression("VendorInfo");
System.out.println(table.getItem(spec).toJSON());

System.out.println("A single vendor:");
spec.withProjectionExpression("VendorInfo.V03");
System.out.println(table.getItem(spec).toJSON());

System.out.println("First office location for this vendor:");
spec.withProjectionExpression("VendorInfo.V03.Offices[0]");
System.out.println(table.getItem(spec).toJSON());
```

Die Ausgabe aus dem vorherigen Beispiel sieht wie folgt aus.

```
All vendor info:
{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]},"V02":{"Name":"New Publishers, Inc.","Offices":["London","New York"]},"V01":{"Name":"Acme Books","Offices":["Seattle"]}}}
A single vendor:
{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]}}}
First office location for a single vendor:
{"VendorInfo":{"V03":{"Offices":["Tokyo"]}}}
```

**Anmerkung**  
Mit der `toJSON`-Methode können Sie jedes beliebige Element (oder seine Attribute) in eine JSON-formatierte Zeichenfolge umwandeln. Das folgende Codeausschnitt ruft mehrere Attribute auf oberster Ebene und verschachtelte Attribute ab und druckt die Ergebnisse im JSON-Format.  

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 210)
    .withProjectionExpression("VendorInfo.V01, Title, Price");

Item item = table.getItem(spec);
System.out.println(item.toJSON());
```
Die Ausgabe sieht wie folgt aus.  

```
{"VendorInfo":{"V01":{"Name":"Acme Books","Offices":["Seattle"]}},"Price":30,"Title":"Book 210 Title"}
```

## Batch Write: Einfügen und Löschen mehrerer Elemente
<a name="BatchWriteDocumentAPIJava"></a>

*Batch Write* bezieht sich auf das Einfügen und Löschen mehrerer Elemente in einem Batch. Die `batchWriteItem`-Methode ermöglicht Ihnen das Einfügen und Löschen von mehreren Elementen aus einer oder mehreren Tabellen anhand eines einzigen Aufrufs. Im Folgenden finden Sie die Schritte zum Einfügen oder Löschen mehrerer Elemente mithilfe der AWS SDK für Java Dokument-API.

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `TableWriteItems`-Klasse, die alle Einfügen- und Löschen-Operationen für eine Tabelle beschreibt. Wenn Sie mit einer einzigen BatchWrite-Operation in mehrere Tabellen schreiben möchten, müssen Sie eine `TableWriteItems`-Instance pro Tabelle erstellen.

1. Rufen Sie die `batchWriteItem`-Methode auf, indem Sie das bzw. die `TableWriteItems`-Objekt(e) bereitstellen, das/die Sie im vorangegangenen Schritt erstellt haben. 

1. Verarbeiten Sie die Antwort. Überprüfen Sie, ob in der Antwort nicht verarbeitete Anforderungselemente zurückgegeben wurden. Dies kann der Fall sein, wenn Sie das Kontingent für den bereitgestellten Durchsatz erreichen oder ein anderer vorübergehender Fehler auftritt. Außerdem begrenzt DynamoDB die Anforderungsgröße und die Anzahl der Vorgänge, die Sie in einer Anforderung angeben können. Wenn Sie diese Limits überschreiten, wird die Anforderung von DynamoDB abgelehnt. Weitere Informationen finden Sie unter [Kontingente in Amazon DynamoDB](ServiceQuotas.md). 

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht. Das folgende Beispiel führt eine `batchWriteItem`-Operation für zwei Tabellen durch: `Forum` und `Thread`. Die entsprechenden `TableWriteItems`-Objekte definieren die folgenden Aktionen:
+ Einfügen eines Elements in die `Forum`-Tabelle
+ Einfügen und Löschen eines Elements in der `Thread`-Tabelle

Der Code ruft dann `batchWriteItem` auf, um die Operation durchzuführen.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

TableWriteItems forumTableWriteItems = new TableWriteItems("Forum")
    .withItemsToPut(
        new Item()
            .withPrimaryKey("Name", "Amazon RDS")
            .withNumber("Threads", 0));

TableWriteItems threadTableWriteItems = new TableWriteItems("Thread")
    .withItemsToPut(
        new Item()
            .withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1")
    .withHashAndRangeKeysToDelete("ForumName","Some partition key value", "Amazon S3", "Some sort key value");

BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems);

// Code for checking unprocessed items is omitted in this example
```

Ein funktionierendes Beispiel finden Sie unter [Beispiel: Batch-Schreibvorgang mit der AWS SDK für Java Dokument-API](batch-operation-document-api-java.md#JavaDocumentAPIBatchWrite). 

## Batch Get: Abrufen mehrerer Elemente
<a name="JavaDocumentAPIBatchGetItem"></a>

Die `batchGetItem`-Methode ermöglicht Ihnen das Abrufen mehrerer Elemente aus einer oder mehreren Tabellen. Um ein einzelnes Element abzurufen, können Sie die `getItem`-Methode verwenden. 

Dazu gehen Sie wie folgt vor: 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `TableKeysAndAttributes`-Klasse, die eine Liste der Primärschlüsselwerte beschreibt, die von einer Tabelle abgerufen werden sollen. Wenn Sie mit einer einzigen BatchGet-Operation aus mehreren Tabellen lesen möchten, müssen Sie eine `TableKeysAndAttributes`-Instance pro Tabelle erstellen.

1. Rufen Sie die `batchGetItem`-Methode auf, indem Sie das bzw. die `TableKeysAndAttributes`-Objekt(e) bereitstellen, das/die Sie im vorangegangenen Schritt erstellt haben.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht. In dem Beispiel werden zwei Elemente aus der `Forum`-Tabelle und drei Elemente aus der `Thread`-Tabelle abgerufen.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

    TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName);
    forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
    "Amazon S3",
    "Amazon DynamoDB");

TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName);
threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject",
    "Amazon DynamoDB","DynamoDB Thread 1",
    "Amazon DynamoDB","DynamoDB Thread 2",
    "Amazon S3","S3 Thread 1");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(
    forumTableKeysAndAttributes, threadTableKeysAndAttributes);

for (String tableName : outcome.getTableItems().keySet()) {
    System.out.println("Items in table " + tableName);
    List<Item> items = outcome.getTableItems().get(tableName);
    for (Item item : items) {
        System.out.println(item);
    }
}
```

### Angeben eines optionalen Parameters
<a name="BatchGetItemJavaDocumentAPIOptions"></a>

Neben den erforderlichen Parametern können Sie bei Verwendung von `batchGetItem` auch optionale Parameter angeben. Beispielsweise können Sie einen `ProjectionExpression` mit jedem `TableKeysAndAttributes`, das Sie definieren, bereitstellen. So können Sie die Attribute angeben, die aus der Tabelle abgerufen werden sollen.

Im folgenden C\$1-Codebeispiel werden zwei Elemente aus der `Forum`-Tabelle abgerufen. Der Parameter `withProjectionExpression` gibt an, dass nur das Attribut `Threads` abgerufen werden soll.

**Example**  

```
TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes("Forum")
    .withProjectionExpression("Threads");

forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
    "Amazon S3",
    "Amazon DynamoDB");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes);
```

## Aktualisieren eines Elements
<a name="JavaDocumentAPIItemUpdate"></a>

Die `updateItem`-Methode eines `Table`-Objekts kann vorhandene Attributwerte aktualisieren, neue Attribute hinzuzufügen oder Attribute aus einem vorhandenen Element löschen. 

Die `updateItem`-Methode verhält sich wie folgt:
+ Wenn kein Element vorhanden ist (kein Element in der Tabelle mit dem angegebenen Primärschlüssel), fügt `updateItem` der Tabelle ein neues Element hinzu.
+ Wenn ein Element vorhanden ist, führt `updateItem` die Aktualisierung wie vom `UpdateExpression`-Parameter angegeben aus.

**Anmerkung**  
Es ist auch möglich, ein Element mit `putItem` zu "aktualisieren". Wenn Sie z. B. `putItem` aufrufen, um der Tabelle ein Element hinzuzufügen, aber bereits ein Element mit dem angegebenen Primärschlüssel vorhanden ist, wird das gesamte Element von `putItem` ersetzt. Wenn Attribute in dem vorhandenen Element nicht in der Eingabe angegeben sind, werden diese Attribute von `putItem` aus dem Element entfernt.  
Im Allgemeinen empfehlen wir, `updateItem` immer dann zu verwenden, wenn Sie Elementattribute ändern möchten. Die `updateItem`-Methode ändert nur die Elementattribute, die Sie in der Eingabe angeben. Die anderen Attribute im Element bleiben unverändert.

Dazu gehen Sie wie folgt vor: 

1. Erstellen Sie eine Instance der `Table`-Klasse, um die Tabelle zu repräsentieren, mit der Sie arbeiten möchten.

1. Rufen Sie die `updateTable`-Methode für die `Table`-Instance auf. Sie müssen den Primärschlüssel des abzurufenden Elements und einen `UpdateExpression` angeben, der die zu ändernden Attribute beschreibt und mitteilt, wie diese geändert werden sollen.

Im folgenden Java-Codebeispiel werden die vorherigen Aufgaben veranschaulicht. Das Beispiel aktualisiert ein Buchelement in der `ProductCatalog`-Tabelle. Es wird ein neuer Autor zum Satz der `Authors` hinzugefügt und das vorhandene `ISBN`-Attribut wird gelöscht. Darüber hinaus wird auch der Preis um eins gesenkt.

Im `ExpressionAttributeValues` wird eine `UpdateExpression`-Zuordnung verwendet. Die Platzhalter `:val1` und `:val2` werden zur Laufzeit durch die tatsächlichen Werte für `Authors` und `Price` ersetzt.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#A", "Authors");
expressionAttributeNames.put("#P", "Price");
expressionAttributeNames.put("#I", "ISBN");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1",
    new HashSet<String>(Arrays.asList("Author YY","Author ZZ")));
expressionAttributeValues.put(":val2", 1);   //Price

UpdateItemOutcome outcome =  table.updateItem(
    "Id",          // key attribute name
    101,           // key attribute value
    "add #A :val1 set #P = #P - :val2 remove #I", // UpdateExpression
    expressionAttributeNames,
    expressionAttributeValues);
```

### Angeben eines optionalen Parameters
<a name="UpdateItemJavaDocumentAPIOptions"></a>

Neben den erforderlichen Parametern können Sie auch optionale Parameter für die `updateItem`-Methode angeben, z. B. eine Bedingung, die erfüllt werden muss, damit die Aktualisierung erfolgt. Wenn die von Ihnen angegebene Bedingung nicht erfüllt ist, wird AWS SDK für Java eine `ConditionalCheckFailedException` ausgelöst. Beim folgenden Java-Codebeispiel wird der Preis eines Buchelements bedingungsabhängig auf 25 erhöht. Das Beispiel zeigt einen `ConditionExpression`, der besagt, dass der Preis nur aktualisiert werden soll, wenn der vorhandene Preis 20 lautet.

**Example**  

```
Table table = dynamoDB.getTable("ProductCatalog");

Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#P", "Price");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1", 25);  // update Price to 25...
expressionAttributeValues.put(":val2", 20);  //...but only if existing Price is 20

UpdateItemOutcome outcome = table.updateItem(
    new PrimaryKey("Id",101),
    "set #P = :val1", // UpdateExpression
    "#P = :val2",     // ConditionExpression
    expressionAttributeNames,
    expressionAttributeValues);
```

### Unteilbarer Zähler
<a name="AtomicCounterJavaDocumentAPI"></a>

Sie können `updateItem` verwenden, um einen unteilbaren Zähler zu implementieren, mit dem der Wert eines bestehenden Attributs erhöht oder verringert wird, ohne andere Schreibanforderungen zu beeinflussen. Zum Erhöhen eines unteilbaren Zählers verwenden Sie einen `UpdateExpression` mit einer `set`-Aktion, um einem vorhandenen Attribut vom Typ `Number` einen numerischen Wert hinzuzufügen.

Das folgende Codebeispiel zeigt diesen Vorgang und erhöht das Attribut `Quantity` um eins. Es zeigt auch die Verwendung des Parameters `ExpressionAttributeNames` in einem `UpdateExpression`.

```
Table table = dynamoDB.getTable("ProductCatalog");

Map<String,String> expressionAttributeNames = new HashMap<String,String>();
expressionAttributeNames.put("#p", "PageCount");

Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
expressionAttributeValues.put(":val", 1);

UpdateItemOutcome outcome = table.updateItem(
    "Id", 121,
    "set #p = #p + :val",
    expressionAttributeNames,
    expressionAttributeValues);
```

## Löschen eines Elements
<a name="DeleteMidLevelJava"></a>

Die `deleteItem`-Methode löscht ein Element aus einer Tabelle. Sie müssen den Primärschlüssel des Elements bereitstellen, das Sie löschen möchten.

Dazu gehen Sie wie folgt vor: 

1. Erstellen Sie eine Instance des `DynamoDB`-Clients.

1. Rufen Sie die `deleteItem`-Methode durch Angabe des Schlüssels des Elements auf, das Sie löschen möchten. 

Das folgende Java-Codebeispiel veranschaulicht diese Vorgehensweisen.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

DeleteItemOutcome outcome = table.deleteItem("Id", 101);
```

### Angeben eines optionalen Parameters
<a name="DeleteItemJavaDocumentAPIOptions"></a>

Sie können für `deleteItem` optionale Parameter angeben. Das folgende Java-Codebeispiel enthält einen `ConditionExpression`, der besagt, dass ein Buchelement im `InPublication` nur dann gelöscht werden darf, wenn das Buch nicht mehr veröffentlicht wird (das Attribut `ProductCatalog` ist False).

**Example**  

```
Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
expressionAttributeValues.put(":val", false);

DeleteItemOutcome outcome = table.deleteItem("Id",103,
    "InPublication = :val",
    null, // ExpressionAttributeNames - not used in this example
    expressionAttributeValues);
```

# Beispiel: CRUD-Operationen mit der AWS SDK für Java Dokument-API
<a name="JavaDocumentAPICRUDExample"></a>

Das folgende Codebeispiel veranschaulicht CRUD-Operationen für ein Amazon-DynamoDB-Element. In dem Beispiel wird ein Element erstellt, abgerufen, es werden verschiedene Aktualisierungen durchgeführt und es wird schließlich gelöscht.

**Anmerkung**  
Das SDK für Java stellt auch ein Objektpersistenzmodell bereit, mit dem Sie Ihre clientseitigen Klassen DynamoDB-Tabellen zuordnen können. Mit diesem Ansatz können Sie die Codemenge, die Sie schreiben müssen, verringern. Weitere Informationen finden Sie unter [Java 1.x: Dynamo DBMapper](DynamoDBMapper.md).

**Anmerkung**  
In diesem Codebeispiel wird davon ausgegangen, dass Sie bereits Daten für Ihr Konto in DynamoDB geladen haben, indem Sie die Anweisungen im [Erstellen von Tabellen und Laden von Daten für Codebeispiele in DynamoDB](SampleData.md)-Abschnitt befolgen.  
 step-by-stepAnweisungen zur Ausführung des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md).

```
package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class DocumentAPIItemCRUDExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String tableName = "ProductCatalog";

    public static void main(String[] args) throws IOException {

        createItems();

        retrieveItem();

        // Perform various updates.
        updateMultipleAttributes();
        updateAddNewAttribute();
        updateExistingAttributeConditionally();

        // Delete the item.
        deleteItem();

    }

    private static void createItems() {

        Table table = dynamoDB.getTable(tableName);
        try {

            Item item = new Item().withPrimaryKey("Id", 120).withString("Title", "Book 120 Title")
                    .withString("ISBN", "120-1111111111")
                    .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author12", "Author22")))
                    .withNumber("Price", 20).withString("Dimensions", "8.5x11.0x.75").withNumber("PageCount", 500)
                    .withBoolean("InPublication", false).withString("ProductCategory", "Book");
            table.putItem(item);

            item = new Item().withPrimaryKey("Id", 121).withString("Title", "Book 121 Title")
                    .withString("ISBN", "121-1111111111")
                    .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author21", "Author 22")))
                    .withNumber("Price", 20).withString("Dimensions", "8.5x11.0x.75").withNumber("PageCount", 500)
                    .withBoolean("InPublication", true).withString("ProductCategory", "Book");
            table.putItem(item);

        } catch (Exception e) {
            System.err.println("Create items failed.");
            System.err.println(e.getMessage());

        }
    }

    private static void retrieveItem() {
        Table table = dynamoDB.getTable(tableName);

        try {

            Item item = table.getItem("Id", 120, "Id, ISBN, Title, Authors", null);

            System.out.println("Printing item after retrieving it....");
            System.out.println(item.toJSONPretty());

        } catch (Exception e) {
            System.err.println("GetItem failed.");
            System.err.println(e.getMessage());
        }

    }

    private static void updateAddNewAttribute() {
        Table table = dynamoDB.getTable(tableName);

        try {

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 121)
                    .withUpdateExpression("set #na = :val1").withNameMap(new NameMap().with("#na", "NewAttribute"))
                    .withValueMap(new ValueMap().withString(":val1", "Some value"))
                    .withReturnValues(ReturnValue.ALL_NEW);

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after adding new attribute...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Failed to add new attribute in " + tableName);
            System.err.println(e.getMessage());
        }
    }

    private static void updateMultipleAttributes() {

        Table table = dynamoDB.getTable(tableName);

        try {

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)
                    .withUpdateExpression("add #a :val1 set #na=:val2")
                    .withNameMap(new NameMap().with("#a", "Authors").with("#na", "NewAttribute"))
                    .withValueMap(
                            new ValueMap().withStringSet(":val1", "Author YY", "Author ZZ").withString(":val2",
                                    "someValue"))
                    .withReturnValues(ReturnValue.ALL_NEW);

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after multiple attribute update...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Failed to update multiple attributes in " + tableName);
            System.err.println(e.getMessage());

        }
    }

    private static void updateExistingAttributeConditionally() {

        Table table = dynamoDB.getTable(tableName);

        try {

            // Specify the desired price (25.00) and also the condition (price =
            // 20.00)

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)
                    .withReturnValues(ReturnValue.ALL_NEW).withUpdateExpression("set #p = :val1")
                    .withConditionExpression("#p = :val2").withNameMap(new NameMap().with("#p", "Price"))
                    .withValueMap(new ValueMap().withNumber(":val1", 25).withNumber(":val2", 20));

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after conditional update to new attribute...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Error updating item in " + tableName);
            System.err.println(e.getMessage());
        }
    }

    private static void deleteItem() {

        Table table = dynamoDB.getTable(tableName);

        try {

            DeleteItemSpec deleteItemSpec = new DeleteItemSpec().withPrimaryKey("Id", 120)
                    .withConditionExpression("#ip = :val").withNameMap(new NameMap().with("#ip", "InPublication"))
                    .withValueMap(new ValueMap().withBoolean(":val", false)).withReturnValues(ReturnValue.ALL_OLD);

            DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);

            // Check the response.
            System.out.println("Printing item that was deleted...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Error deleting item in " + tableName);
            System.err.println(e.getMessage());
        }
    }
}
```

# Beispiel: Batch-Operationen mithilfe der AWS SDK für Java Dokument-API
<a name="batch-operation-document-api-java"></a>

Dieser Abschnitt enthält Beispiele für Batch-Write- und Batch-Abruf-Operationen in Amazon DynamoDB mithilfe der AWS SDK für Java Document API.

**Anmerkung**  
Das SDK für Java stellt auch ein Objektpersistenzmodell bereit, mit dem Sie Ihre clientseitigen Klassen DynamoDB-Tabellen zuordnen können. Mit diesem Ansatz können Sie die Codemenge, die Sie schreiben müssen, verringern. Weitere Informationen finden Sie unter [Java 1.x: Dynamo DBMapper](DynamoDBMapper.md).

**Topics**
+ [Beispiel: Batch-Schreibvorgang mit der AWS SDK für Java Dokument-API](#JavaDocumentAPIBatchWrite)
+ [Beispiel: Batch-Abruf-Vorgang mit der AWS SDK für Java Dokument-API](#JavaDocumentAPIBatchGet)

## Beispiel: Batch-Schreibvorgang mit der AWS SDK für Java Dokument-API
<a name="JavaDocumentAPIBatchWrite"></a>

Das folgende Java-Beispielcode verwendet die `batchWriteItem`-Methode zur Durchführung der folgenden Operationen zum Einfügen und Löschen:
+ Einfügen eines Elements in die `Forum`-Tabelle
+ Einfügen und Löschen eines Elements aus der `Thread`-Tabelle 

Bei der Erstellung Ihrer BatchWrite-Anforderung können Sie eine beliebige Anzahl von Einfüge- und Lösch-Anforderungen angeben. `batchWriteItem` begrenzt jedoch die Größe einer BatchWrite-Anforderung sowie die Anzahl der Einfüge- und Löschoperationen in einer einzelnen BatchWrite-Operation. Wenn Ihre Anforderung diese Grenzwerte überschreitet, wird sie abgelehnt. Wenn die Tabelle nicht über ausreichend bereitgestellten Durchsatz für diese Anforderung verfügt, werden nicht verarbeitete Anforderungselemente in der Antwort zurückgegeben. 

Im folgenden Beispiel wird die Antwort auf unverarbeitete Anforderungselemente überprüft. Liegen unverarbeitete Elemente vor, wird der Vorgang wiederholt und die `batchWriteItem`-Anforderung mit unverarbeiteten Elementen wird erneut gesendet. Wenn Sie die Beispiele in dieser Anleitung befolgt haben, sollten Sie die Tabellen `Forum` und `Thread` bereits erstellt haben. Sie können diese Tabellen auch programmgesteuert erstellen und auf die gleiche Weise Beispieldaten hochladen. Weitere Informationen finden Sie unter [Erstellen von Beispieltabellen und Hochladen von Daten mit dem AWS SDK für Java](AppendixSampleDataCodeJava.md).

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md). 

**Example**  

```
package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableWriteItems;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;

public class DocumentAPIBatchWrite {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String forumTableName = "Forum";
    static String threadTableName = "Thread";

    public static void main(String[] args) throws IOException {

        writeMultipleItemsBatchWrite();

    }

    private static void writeMultipleItemsBatchWrite() {
        try {

            // Add a new item to Forum
            TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName) // Forum
                    .withItemsToPut(new Item().withPrimaryKey("Name", "Amazon RDS").withNumber("Threads", 0));

            // Add a new item, and delete an existing item, from Thread
            // This table has a partition key and range key, so need to specify
            // both of them
            TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName)
                    .withItemsToPut(
                            new Item().withPrimaryKey("ForumName", "Amazon RDS", "Subject", "Amazon RDS Thread 1")
                                    .withString("Message", "ElastiCache Thread 1 message")
                                    .withStringSet("Tags", new HashSet<String>(Arrays.asList("cache", "in-memory"))))
                    .withHashAndRangeKeysToDelete("ForumName", "Subject", "Amazon S3", "S3 Thread 100");

            System.out.println("Making the request.");
            BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems);

            do {

                // Check for unprocessed keys which could happen if you exceed
                // provisioned throughput

                Map<String, List<WriteRequest>> unprocessedItems = outcome.getUnprocessedItems();

                if (outcome.getUnprocessedItems().size() == 0) {
                    System.out.println("No unprocessed items found");
                } else {
                    System.out.println("Retrieving the unprocessed items");
                    outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems);
                }

            } while (outcome.getUnprocessedItems().size() > 0);

        } catch (Exception e) {
            System.err.println("Failed to retrieve items: ");
            e.printStackTrace(System.err);
        }

    }

}
```

## Beispiel: Batch-Abruf-Vorgang mit der AWS SDK für Java Dokument-API
<a name="JavaDocumentAPIBatchGet"></a>

Das folgende Java-Codebeispiel verwendet die `batchGetItem`-Methode zum Abrufen mehrerer Elemente aus den Tabellen `Forum` und `Thread`. Die `BatchGetItemRequest` gibt die Tabellennamen sowie eine Liste der Schlüssel für jedes abzurufende Element an. In dem Beispiel wird die Antwort durch Drucken der abgerufenen Elemente verarbeitet.

**Anmerkung**  
In diesem Codebeispiel wird davon ausgegangen, dass Sie bereits Daten für Ihr Konto in DynamoDB geladen haben, indem Sie die Anweisungen im [Erstellen von Tabellen und Laden von Daten für Codebeispiele in DynamoDB](SampleData.md)-Abschnitt befolgen.  
 step-by-stepAnweisungen zur Ausführung des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md).

**Example**  

```
package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;

public class DocumentAPIBatchGet {
    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String forumTableName = "Forum";
    static String threadTableName = "Thread";

    public static void main(String[] args) throws IOException {
        retrieveMultipleItemsBatchGet();
    }

    private static void retrieveMultipleItemsBatchGet() {

        try {

            TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName);
            // Add a partition key
            forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB");

            TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName);
            // Add a partition key and a sort key
            threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject", "Amazon DynamoDB",
                    "DynamoDB Thread 1", "Amazon DynamoDB", "DynamoDB Thread 2", "Amazon S3", "S3 Thread 1");

            System.out.println("Making the request.");

            BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes,
                    threadTableKeysAndAttributes);

            Map<String, KeysAndAttributes> unprocessed = null;

            do {
                for (String tableName : outcome.getTableItems().keySet()) {
                    System.out.println("Items in table " + tableName);
                    List<Item> items = outcome.getTableItems().get(tableName);
                    for (Item item : items) {
                        System.out.println(item.toJSONPretty());
                    }
                }

                // Check for unprocessed keys which could happen if you exceed
                // provisioned
                // throughput or reach the limit on response size.
                unprocessed = outcome.getUnprocessedKeys();

                if (unprocessed.isEmpty()) {
                    System.out.println("No unprocessed keys found");
                } else {
                    System.out.println("Retrieving the unprocessed keys");
                    outcome = dynamoDB.batchGetItemUnprocessed(unprocessed);
                }

            } while (!unprocessed.isEmpty());

        } catch (Exception e) {
            System.err.println("Failed to retrieve items.");
            System.err.println(e.getMessage());
        }

    }

}
```

# Beispiel: Umgang mit binären Typattributen mithilfe der AWS SDK für Java Dokument-API
<a name="JavaDocumentAPIBinaryTypeExample"></a>

Das folgende Java-Codebeispiel veranschaulicht die Verarbeitung von Attributen des Typs Binärzahl. Bei dem Beispiel wird der `Reply`-Tabelle ein Element hinzugefügt. Das Element enthält ein Binärtypattribut (`ExtendedMessage`), in dem komprimierte Daten gespeichert sind. Daraufhin wird das Element abgerufen und es werden alle Attributwerte gedruckt. Zur Veranschaulichung wird in dem Beispiel die `GZIPOutputStream`-Klasse verwendet, um einen Beispiel-Stream zu komprimieren und dem `ExtendedMessage`-Attribut zuzuweisen. Wenn das Binärattribut abgerufen wird, wird es mit der `GZIPInputStream`-Klasse dekomprimiert. 

**Anmerkung**  
Das SDK für Java stellt auch ein Objektpersistenzmodell bereit, mit dem Sie Ihre clientseitigen Klassen DynamoDB-Tabellen zuordnen können. Mit diesem Ansatz können Sie die Codemenge, die Sie schreiben müssen, verringern. Weitere Informationen finden Sie unter [Java 1.x: Dynamo DBMapper](DynamoDBMapper.md).

Wenn Sie die Schritte im Abschnitt [Erstellen von Tabellen und Laden von Daten für Codebeispiele in DynamoDB](SampleData.md) befolgt haben, sollten Sie die `Reply`-Tabelle bereits erstellt haben. Sie können diese Tabelle auch programmgesteuert erstellen. Weitere Informationen finden Sie unter [Erstellen von Beispieltabellen und Hochladen von Daten mit dem AWS SDK für Java](AppendixSampleDataCodeJava.md).

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md). 

**Example**  

```
package com.amazonaws.codesamples.document;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.GetItemSpec;

public class DocumentAPIItemBinaryExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String tableName = "Reply";
    static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

    public static void main(String[] args) throws IOException {
        try {

            // Format the primary key values
            String threadId = "Amazon DynamoDB#DynamoDB Thread 2";

            dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            String replyDateTime = dateFormatter.format(new Date());

            // Add a new reply with a binary attribute type
            createItem(threadId, replyDateTime);

            // Retrieve the reply with a binary attribute type
            retrieveItem(threadId, replyDateTime);

            // clean up by deleting the item
            deleteItem(threadId, replyDateTime);
        } catch (Exception e) {
            System.err.println("Error running the binary attribute type example: " + e);
            e.printStackTrace(System.err);
        }
    }

    public static void createItem(String threadId, String replyDateTime) throws IOException {

        Table table = dynamoDB.getTable(tableName);

        // Craft a long message
        String messageInput = "Long message to be compressed in a lengthy forum reply";

        // Compress the long message
        ByteBuffer compressedMessage = compressString(messageInput.toString());

        table.putItem(new Item().withPrimaryKey("Id", threadId).withString("ReplyDateTime", replyDateTime)
                .withString("Message", "Long message follows").withBinary("ExtendedMessage", compressedMessage)
                .withString("PostedBy", "User A"));
    }

    public static void retrieveItem(String threadId, String replyDateTime) throws IOException {

        Table table = dynamoDB.getTable(tableName);

        GetItemSpec spec = new GetItemSpec().withPrimaryKey("Id", threadId, "ReplyDateTime", replyDateTime)
                .withConsistentRead(true);

        Item item = table.getItem(spec);

        // Uncompress the reply message and print
        String uncompressed = uncompressString(ByteBuffer.wrap(item.getBinary("ExtendedMessage")));

        System.out.println("Reply message:\n" + " Id: " + item.getString("Id") + "\n" + " ReplyDateTime: "
                + item.getString("ReplyDateTime") + "\n" + " PostedBy: " + item.getString("PostedBy") + "\n"
                + " Message: "
                + item.getString("Message") + "\n" + " ExtendedMessage (uncompressed): " + uncompressed + "\n");
    }

    public static void deleteItem(String threadId, String replyDateTime) {

        Table table = dynamoDB.getTable(tableName);
        table.deleteItem("Id", threadId, "ReplyDateTime", replyDateTime);
    }

    private static ByteBuffer compressString(String input) throws IOException {
        // Compress the UTF-8 encoded String into a byte[]
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream os = new GZIPOutputStream(baos);
        os.write(input.getBytes("UTF-8"));
        os.close();
        baos.close();
        byte[] compressedBytes = baos.toByteArray();

        // The following code writes the compressed bytes to a ByteBuffer.
        // A simpler way to do this is by simply calling
        // ByteBuffer.wrap(compressedBytes);
        // However, the longer form below shows the importance of resetting the
        // position of the buffer
        // back to the beginning of the buffer if you are writing bytes directly
        // to it, since the SDK
        // will consider only the bytes after the current position when sending
        // data to DynamoDB.
        // Using the "wrap" method automatically resets the position to zero.
        ByteBuffer buffer = ByteBuffer.allocate(compressedBytes.length);
        buffer.put(compressedBytes, 0, compressedBytes.length);
        buffer.position(0); // Important: reset the position of the ByteBuffer
                            // to the beginning
        return buffer;
    }

    private static String uncompressString(ByteBuffer input) throws IOException {
        byte[] bytes = input.array();
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPInputStream is = new GZIPInputStream(bais);

        int chunkSize = 1024;
        byte[] buffer = new byte[chunkSize];
        int length = 0;
        while ((length = is.read(buffer, 0, chunkSize)) != -1) {
            baos.write(buffer, 0, length);
        }

        String result = new String(baos.toByteArray(), "UTF-8");

        is.close();
        baos.close();
        bais.close();

        return result;
    }
}
```

# Arbeiten mit Elementen: .NET
<a name="LowLevelDotNetItemCRUD"></a>

Sie können die AWS SDK für .NET Low-Level-API verwenden, um typische Erstellungs-, Lese-, Aktualisierungs- und Löschvorgänge (CRUD) für ein Element in einer Tabelle durchzuführen. Nachfolgend sind die üblichen Schritte zum Ausführen von CRUD-Operationen mit der .NET-Low-Level-API ausführen:

1. Erstellen einer Instance der `AmazonDynamoDBClient`-Klasse (Client).

1. Geben Sie die für die Operation spezifischen, erforderlichen Parameter in einem entsprechenden Anforderungsobjekt an.

   Verwenden Sie z. B. das `PutItemRequest`-Anforderungsobjekt zum Hochladen eines Elements und das `GetItemRequest`-Anforderungsobjekt, wenn Sie ein vorhandenes Element abrufen. 

   Mit dem Anforderungsobjekt können Sie sowohl die erforderlichen als auch die optionalen Parameter angeben. 

1. Führen Sie die vom Client bereitgestellte, geeignete Methode aus, indem Sie das Anforderungsobjekt, das Sie im vorhergehenden Schritt erstellt haben, übergeben. 

   Der `AmazonDynamoDBClient`-Client bietet die Methoden `PutItem`, `GetItem`, `UpdateItem` und `DeleteItem` für die CRUD-Operationen.

**Topics**
+ [Einfügen eines Elements](#PutItemLowLevelAPIDotNet)
+ [Abrufen eines Elements](#GetItemLowLevelDotNET)
+ [Aktualisieren eines Elements](#UpdateItemLowLevelDotNet)
+ [Unteilbarer Zähler](#AtomicCounterLowLevelDotNet)
+ [Löschen eines Elements](#DeleteMidLevelDotNet)
+ [Batch Write: Einfügen und Löschen mehrerer Elemente](#BatchWriteLowLevelDotNet)
+ [Batch Get: Abrufen mehrerer Elemente](#BatchGetLowLevelDotNet)
+ [Beispiel: CRUD-Operationen unter Verwendung der AWS SDK für .NET Low-Level-API](LowLevelDotNetItemsExample.md)
+ [Beispiel: Batch-Operationen mit der AWS SDK für .NET Low-Level-API](batch-operation-lowlevel-dotnet.md)
+ [Beispiel: Umgang mit binären Attributen mithilfe der AWS SDK für .NET Low-Level-API](LowLevelDotNetBinaryTypeExample.md)

## Einfügen eines Elements
<a name="PutItemLowLevelAPIDotNet"></a>

Mit der `PutItem`-Methode wird ein Element in eine Tabelle hochgeladen. Wenn das Element bereits vorhanden ist, wird das ganze Element ersetzt.

**Anmerkung**  
Anstatt das gesamte Element zu ersetzen und nur spezifische Attribute zu aktualisieren, können Sie die Methode `UpdateItem` verwenden. Weitere Informationen finden Sie unter [Aktualisieren eines Elements](#UpdateItemLowLevelDotNet).

Im Folgenden finden Sie die Schritte zum Hochladen eines Elements mithilfe der .NET SDK-API auf niedriger Ebene:

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie die erforderlichen Parameter bereit, in dem Sie eine Instance der `PutItemRequest`-Klasse erstellen.

   Um für ein Element eine PUT-Operation auszuführen, müssen Sie den Tabellennamen und das Element angeben. 

1. Führen Sie die `PutItem`-Methode aus, indem Sie das `PutItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Das Beispiel lädt ein Element in die `ProductCatalog`-Tabelle hoch.

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new PutItemRequest
{
   TableName = tableName,
   Item = new Dictionary<string, AttributeValue>()
      {
          { "Id", new AttributeValue { N = "201" }},
          { "Title", new AttributeValue { S = "Book 201 Title" }},
          { "ISBN", new AttributeValue { S = "11-11-11-11" }},
          { "Price", new AttributeValue { S = "20.00" }},
          {
            "Authors",
            new AttributeValue
            { SS = new List<string>{"Author1", "Author2"}   }
          }
      }
};
client.PutItem(request);
```

Im vorherigen Beispiel laden Sie ein Buchelement mit den Attributen `Id`, `Title`, `ISBN` und `Authors` hoch. Beachten Sie, dass `Id` ein Attribut vom Typ Zahl ist. Alle anderen Attribute sind vom Typ Zeichenfolge. Autoren ist eine `String`-Einstellung.

### Angeben eines optionalen Parameters
<a name="PutItemLowLevelAPIDotNetOptions"></a>

Sie können mit dem `PutItemRequest`-Objekt auch optionale Parameter angeben, wie im folgenden C\$1-Beispiel dargestellt. Das Beispiel gibt die folgenden optionalen Parameter an:
+ `ExpressionAttributeNames`, `ExpressionAttributeValues` und `ConditionExpression` geben an, dass das Element nur ersetzt werden kann, wenn das vorhandene Element das Attribut "ISBN" mit einem spezifischen Wert besitzt.
+ Mit dem Parameter `ReturnValues` wird das alte Element in der Antwort angefordert.

**Example**  

```
var request = new PutItemRequest
 {
   TableName = tableName,
   Item = new Dictionary<string, AttributeValue>()
               {
                   { "Id", new AttributeValue { N = "104" }},
                   { "Title", new AttributeValue { S = "Book 104  Title" }},
                   { "ISBN", new AttributeValue { S = "444-4444444444" }},
                   { "Authors",
                     new AttributeValue { SS = new List<string>{"Author3"}}}
               },
    // Optional parameters.
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#I", "ISBN"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":isbn",new AttributeValue {S = "444-4444444444"}}
    },
    ConditionExpression = "#I = :isbn"

};
var response = client.PutItem(request);
```

Weitere Informationen finden Sie unter [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html).

## Abrufen eines Elements
<a name="GetItemLowLevelDotNET"></a>

Die `GetItem`-Methode ruft ein Element ab.

**Anmerkung**  
Um mehrere Elemente abzurufen, können Sie die `BatchGetItem`-Methode verwenden. Weitere Informationen finden Sie unter [Batch Get: Abrufen mehrerer Elemente](#BatchGetLowLevelDotNet).

Im Folgenden werden die Schritte zum Abrufen eines vorhandenen Elements mithilfe des AWS SDK für .NET -Low-Level-API beschrieben.

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie die erforderlichen Parameter bereit, in dem Sie eine Instance der `GetItemRequest`-Klasse erstellen.

   Zum Abrufen eines Elements müssen Sie den Tabellennamen und den Primärschlüssel des Elements angeben. 

1. Führen Sie die `GetItem`-Methode aus, indem Sie das `GetItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Das Beispiel ruft ein Objekt aus der `ProductCatalog`-Tabelle ab.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new GetItemRequest
 {
   TableName = tableName,
   Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
 };
 var response = client.GetItem(request);

// Check the response.
var result = response.GetItemResult;
var attributeMap = result.Item; // Attribute list in the response.
```

### Angeben eines optionalen Parameters
<a name="GetItemLowLevelDotNETOptions"></a>

Sie können mit dem `GetItemRequest`-Objekt auch optionale Parameter angeben, wie im folgenden C\$1-Beispiel dargestellt. Das Beispiel gibt die folgenden optionalen Parameter an:
+ `ProjectionExpression` Parameter, um die abzurufenden Attribute anzugeben.
+ `ConsistentRead` Parameter zum Ausführen eines Strongly-Consistent-Lesevorgangs. Weitere Informationen zur Lesekonsistenz finden Sie unter [DynamoDB-Lesekonsistenz](HowItWorks.ReadConsistency.md).

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new GetItemRequest
 {
   TableName = tableName,
   Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
   // Optional parameters.
   ProjectionExpression = "Id, ISBN, Title, Authors",
   ConsistentRead = true
 };

 var response = client.GetItem(request);

// Check the response.
var result = response.GetItemResult;
var attributeMap = result.Item;
```

Weitere Informationen finden Sie unter [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html).

## Aktualisieren eines Elements
<a name="UpdateItemLowLevelDotNet"></a>

Mit der `UpdateItem`-Methode wird ein bestehendes Element aktualisiert, wenn es vorhanden ist. Sie können die `UpdateItem`-Operation verwenden, um vorhandene Attributwerte zu aktualisieren, der vorhandenen Sammlung neue Attribute hinzuzufügen oder Attribute aus der vorhandenen Sammlung zu löschen. Wenn das Element, das den bestimmten Primärschlüssel besitzt, nicht gefunden wird, wird ein neues Element hinzugefügt.

Die `UpdateItem`-Operation verwendet folgende Leitlinien:
+ Wenn das Element nicht vorhanden ist, fügt `UpdateItem` ein neues Element hinzu, indem der in der Eingabe angegebene Primärschlüssel genutzt wird.
+ Wenn das Element vorhanden ist, wendet `UpdateItem` die Aktualisierung wie folgt an:
  + Ersetzt die vorhandenen Attributwerte durch die Werte in der Aktualisierung.
  + Wenn das Attribut, das Sie in der Eingabe angegeben haben, nicht vorhanden ist, wird dem Element ein neues Attribut hinzugefügt.
  + Wenn das Eingabeattribut Null ist, wird das Attribut gelöscht, sofern es vorhanden ist. 
  + Wenn Sie `ADD` für die Aktion `Action` verwenden, können Sie einem vorhandenen Satz (Zeichenfolgen- oder Zahlensatz) Werte hinzufügen oder mathematisch addieren (unter Verwendung einer positiven Zahl) bzw. von dem vorhandenen numerischen Attributwert subtrahieren (unter Verwendung einer negativen Zahl).

**Anmerkung**  
Die `PutItem`-Operation kann auch eine Aktualisierung durchführen. Weitere Informationen finden Sie unter [Einfügen eines Elements](#PutItemLowLevelAPIDotNet). Wenn Sie z. B. `PutItem` aufrufen, um ein Element hochzuladen, und der Primärschlüssel vorhanden ist, ersetzt die `PutItem`-Operation das gesamte Element. Wenn das vorhandene Element Attribute entiert und diese Attribute nicht in der Eingabe angegeben sind, werden diese Attribute vom `PutItem`-Vorgang gelöscht. Jedoch aktualisiert `UpdateItem` lediglich die angegebenen Eingabeattribute. Alle anderen vorhandenen Attribute dieses Elements bleiben unverändert. 

Im Folgenden werden die Schritte zum Aktualisieren eines vorhandenen Elements mithilfe der Low-Level-.NET.SDK-API beschrieben.

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie die erforderlichen Parameter bereit, in dem Sie eine Instance der `UpdateItemRequest`-Klasse erstellen.

   Dies ist das Anforderungsobjekt, in dem Sie alle Aktualisierungen beschreiben, z. B. Attribute hinzufügen, vorhandene Attribute aktualisieren oder Attribute löschen. Um ein vorhandenes Attribut zu löschen, geben Sie den Attributnamen mit Nullwert an. 

1. Führen Sie die `UpdateItem`-Methode aus, indem Sie das `UpdateItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben. 

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Im Beispiel wird ein Buchelement in der `ProductCatalog`-Tabelle aktualisiert. Es fügt der `Authors`-Auflistung einen neuen Autor hinzu und löscht das vorhandene `ISBN`-Attribut. Darüber hinaus wird auch der Preis um eins gesenkt.



```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#A", "Authors"},
        {"#P", "Price"},
        {"#NA", "NewAttribute"},
        {"#I", "ISBN"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":auth",new AttributeValue { SS = {"Author YY","Author ZZ"}}},
        {":p",new AttributeValue {N = "1"}},
        {":newattr",new AttributeValue {S = "someValue"}},
    },

    // This expression does the following:
    // 1) Adds two new authors to the list
    // 2) Reduces the price
    // 3) Adds a new attribute to the item
    // 4) Removes the ISBN attribute from the item
    UpdateExpression = "ADD #A :auth SET #P = #P - :p, #NA = :newattr REMOVE #I"
};
var response = client.UpdateItem(request);
```

### Angeben eines optionalen Parameters
<a name="UpdateItemLowLevelDotNETOptions"></a>

Sie können auch optionale Parameter mithilfe des `UpdateItemRequest`-Objekts bereitstellen, wie im folgenden C\$1-Beispiel gezeigt. Folgende optionale Parameter werden angegeben:
+ `ExpressionAttributeValues` und `ConditionExpression`, um festzulegen, dass der Preis nur aktualisiert werden kann, wenn er momentan 20,00 beträgt.
+ Der Parameter `ReturnValues` zum Anfordern des aktualisierten Elements in der Antwort. 

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },

    // Update price only if the current price is 20.00.
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#P", "Price"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":newprice",new AttributeValue {N = "22"}},
        {":currprice",new AttributeValue {N = "20"}}
    },
    UpdateExpression = "SET #P = :newprice",
    ConditionExpression = "#P = :currprice",
    TableName = tableName,
    ReturnValues = "ALL_NEW" // Return all the attributes of the updated item.
};

var response = client.UpdateItem(request);
```

Weitere Informationen finden Sie unter [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html). 

## Unteilbarer Zähler
<a name="AtomicCounterLowLevelDotNet"></a>

Sie können `updateItem` verwenden, um einen unteilbaren Zähler zu implementieren, mit dem der Wert eines bestehenden Attributs erhöht oder verringert wird, ohne andere Schreibanforderungen zu beeinflussen. Um einen Atomzähler zu aktualisieren, verwenden Sie `updateItem` mit einem Attribut vom Typ `Number` im Parameter `UpdateExpression` und `ADD` als `Action`.

Das folgende Codebeispiel zeigt diesen Vorgang und erhöht das Attribut `Quantity` um eins.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "121" } } },
    ExpressionAttributeNames = new Dictionary<string, string>()
    {
        {"#Q", "Quantity"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":incr",new AttributeValue {N = "1"}}
    },
    UpdateExpression = "SET #Q = #Q + :incr",
    TableName = tableName
};

var response = client.UpdateItem(request);
```

## Löschen eines Elements
<a name="DeleteMidLevelDotNet"></a>

Die `DeleteItem`-Methode löscht ein Element aus einer Tabelle. 

Im Folgenden werden die Schritte zum Löschen eines Elements mithilfe der .NET SDK-Low-Level-API beschrieben. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie die erforderlichen Parameter bereit, in dem Sie eine Instance der `DeleteItemRequest`-Klasse erstellen.

    Zum Löschen eines Elements sind der Tabellenname und der Primärschlüssel des Elements erforderlich. 

1. Führen Sie die `DeleteItem`-Methode aus, indem Sie das `DeleteItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben. 

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new DeleteItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } },
};

var response = client.DeleteItem(request);
```

### Angeben eines optionalen Parameters
<a name="DeleteItemLowLevelDotNETOptions"></a>

Sie können mit dem `DeleteItemRequest`-Objekt auch optionale Parameter angeben, wie im folgenden C\$1-Beispiel dargestellt. Folgende optionale Parameter werden angegeben:
+ `ExpressionAttributeValues`und `ConditionExpression` um anzugeben, dass das Buchelement nur gelöscht werden kann, wenn es nicht mehr veröffentlicht wird (der InPublication Attributwert ist falsch). 
+ Der Parameter `ReturnValues` zum Anfordern des gelöschten Elements in der Antwort.

**Example**  

```
var request = new DeleteItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } },

    // Optional parameters.
    ReturnValues = "ALL_OLD",
    ExpressionAttributeNames = new Dictionary<string, string>()
    {
        {"#IP", "InPublication"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":inpub",new AttributeValue {BOOL = false}}
    },
    ConditionExpression = "#IP = :inpub"
};

var response = client.DeleteItem(request);
```

Weitere Informationen finden Sie unter [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html).

## Batch Write: Einfügen und Löschen mehrerer Elemente
<a name="BatchWriteLowLevelDotNet"></a>

*Batch Write* bezieht sich auf das Einfügen und Löschen mehrerer Elemente in einem Batch. Die `BatchWriteItem`-Methode ermöglicht Ihnen das Einfügen und Löschen von mehreren Elementen aus einer oder mehreren Tabellen anhand eines einzigen Aufrufs. Im Folgenden werden die Schritte zum Abrufen mehrerer Elemente mithilfe der .NET SDK-Low-Level-API beschrieben.

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Beschreiben Sie alle Put- und Delete-Operationen, indem Sie eine Instance der `BatchWriteItemRequest`-Klasse erstellen.

1. Führen Sie die `BatchWriteItem`-Methode aus, indem Sie das `BatchWriteItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben.

1. Verarbeiten Sie die Antwort. Überprüfen Sie, ob in der Antwort nicht verarbeitete Anforderungselemente zurückgegeben wurden. Dies kann der Fall sein, wenn Sie das Kontingent für den bereitgestellten Durchsatz erreichen oder ein anderer vorübergehender Fehler auftritt. Außerdem begrenzt DynamoDB die Anforderungsgröße und die Anzahl der Vorgänge, die Sie in einer Anforderung angeben können. Wenn Sie diese Limits überschreiten, wird die Anforderung von DynamoDB abgelehnt. Weitere Informationen finden Sie unter [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html). 

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Das Beispiel erstellt eine `BatchWriteItemRequest` zum Ausführen der folgenden Schreibvorgänge:
+ Einfügen eines Elements in die `Forum`-Tabelle
+ Einfügen und Löschen eines Elements in der `Thread`-Tabelle.

Der Code führt `BatchWriteItem` aus, um einen Batchvorgang auszuführen.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";
string table2Name = "Thread";

var request = new BatchWriteItemRequest
 {
   RequestItems = new Dictionary<string, List<WriteRequest>>
    {
      {
        table1Name, new List<WriteRequest>
        {
          new WriteRequest
          {
             PutRequest = new PutRequest
             {
                Item = new Dictionary<string,AttributeValue>
                {
                  { "Name", new AttributeValue { S = "Amazon S3 forum" } },
                  { "Threads", new AttributeValue { N = "0" }}
                }
             }
          }
        }
      } ,
      {
        table2Name, new List<WriteRequest>
        {
          new WriteRequest
          {
            PutRequest = new PutRequest
            {
               Item = new Dictionary<string,AttributeValue>
               {
                 { "ForumName", new AttributeValue { S = "Amazon S3 forum" } },
                 { "Subject", new AttributeValue { S = "My sample question" } },
                 { "Message", new AttributeValue { S = "Message Text." } },
                 { "KeywordTags", new AttributeValue { SS = new List<string> { "Amazon S3", "Bucket" }  } }
               }
            }
          },
          new WriteRequest
          {
             DeleteRequest = new DeleteRequest
             {
                Key = new Dictionary<string,AttributeValue>()
                {
                   { "ForumName", new AttributeValue { S = "Some forum name" } },
                   { "Subject", new AttributeValue { S = "Some subject" } }
                }
             }
          }
        }
      }
    }
 };
response = client.BatchWriteItem(request);
```

Ein funktionierendes Beispiel finden Sie unter [Beispiel: Batch-Operationen mit der AWS SDK für .NET Low-Level-API](batch-operation-lowlevel-dotnet.md). 

## Batch Get: Abrufen mehrerer Elemente
<a name="BatchGetLowLevelDotNet"></a>

Die `BatchGetItem`-Methode ermöglicht Ihnen das Abrufen mehrerer Elemente aus einer oder mehreren Tabellen. 

**Anmerkung**  
Um ein einzelnes Element abzurufen, können Sie die `GetItem`-Methode verwenden. 

Im Folgenden werden die Schritte zum Abrufen mehrerer Elemente mithilfe der AWS SDK für .NET -Low-Level-API beschrieben.

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie die erforderlichen Parameter bereit, in dem Sie eine Instance der `BatchGetItemRequest`-Klasse erstellen.

   Zum Abrufen mehrerer Elemente, sind der Tabellenname und eine Liste der Primärschlüsselwerte erforderlich. 

1. Führen Sie die `BatchGetItem`-Methode aus, indem Sie das `BatchGetItemRequest`-Objekt bereitstellen, das Sie im vorherigen Schritt erstellt haben.

1. Verarbeiten Sie die Antwort. Überprüfen Sie, ob nicht verarbeitete Schlüssel vorhanden sind. Dies kann der Fall sein, wenn Sie das Kontingent für den bereitgestellten Durchsatz erreichen oder ein anderer vorübergehender Fehler auftritt.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Das Beispiel ruft Elemente aus zwei Tabellen, `Forum` und `Thread`, ab. Die Anforderung gibt zwei Elemente in der Tabelle `Forum` und drei Elemente in der Tabelle `Thread` an. Die Antwort enthält Elemente aus beiden Tabellen. Der Code zeigt, wie Sie die Antwort verarbeiten können.



```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";
string table2Name = "Thread";

var request = new BatchGetItemRequest
{
  RequestItems = new Dictionary<string, KeysAndAttributes>()
  {
    { table1Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "DynamoDB" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "Amazon S3" } }
          }
        }
      }
    },
    {
      table2Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "DynamoDB" } },
            { "Subject", new AttributeValue { S = "DynamoDB Thread 1" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "DynamoDB" } },
            { "Subject", new AttributeValue { S = "DynamoDB Thread 2" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "Amazon S3" } },
            { "Subject", new AttributeValue { S = "Amazon S3 Thread 1" } }
          }
        }
      }
    }
  }
};

var response = client.BatchGetItem(request);

// Check the response.
var result = response.BatchGetItemResult;
var responses = result.Responses; // The attribute list in the response.

var table1Results = responses[table1Name];
Console.WriteLine("Items in table {0}" + table1Name);
foreach (var item1 in table1Results.Items)
{
  PrintItem(item1);
}

var table2Results = responses[table2Name];
Console.WriteLine("Items in table {1}" + table2Name);
foreach (var item2 in table2Results.Items)
{
  PrintItem(item2);
}
// Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error.
Dictionary<string, KeysAndAttributes> unprocessedKeys = result.UnprocessedKeys;
foreach (KeyValuePair<string, KeysAndAttributes> pair in unprocessedKeys)
{
    Console.WriteLine(pair.Key, pair.Value);
}
```



### Angeben eines optionalen Parameters
<a name="BatchGetItemLowLevelDotNETOptions"></a>

Sie können mit dem `BatchGetItemRequest`-Objekt auch optionale Parameter angeben, wie im folgenden C\$1-Beispiel dargestellt. Im Beispiel werden zwei Elemente aus der `Forum` Tabelle abgerufen. Folgende optionale Parameter werden angegeben:
+  `ProjectionExpression` Parameter, um die abzurufenden Attribute anzugeben.

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";

var request = new BatchGetItemRequest
{
  RequestItems = new Dictionary<string, KeysAndAttributes>()
  {
    { table1Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "DynamoDB" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "Amazon S3" } }
          }
        }
      },
      // Optional - name of an attribute to retrieve.
      ProjectionExpression = "Title"
    }
  }
};

var response = client.BatchGetItem(request);
```

Weitere Informationen finden Sie unter [BatchGetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html). 

# Beispiel: CRUD-Operationen unter Verwendung der AWS SDK für .NET Low-Level-API
<a name="LowLevelDotNetItemsExample"></a>

Das folgende C\$1-Codebeispiel veranschaulicht CRUD-Operationen für ein Amazon-DynamoDB-Element. Das Beispiel fügt der Tabelle `ProductCatalog` ein Element hinzu, ruft es ab, führt verschiedene Aktualisierungen aus und löscht schließlich das Element. Wenn Sie diese Tabelle nicht erstellt haben, können Sie sie auch programmgesteuert erstellen. Weitere Informationen finden Sie unter [Erstellen von Beispieltabellen und Hochladen von Daten mit dem AWS SDK für .NET](AppendixSampleDataCodeDotNET.md).

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter. [.NET-Codebeispiele](CodeSamples.DotNet.md) 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class LowLevelItemCRUDExample
    {
        private static string tableName = "ProductCatalog";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                CreateItem();
                RetrieveItem();

                // Perform various updates.
                UpdateMultipleAttributes();
                UpdateExistingAttributeConditionally();

                // Delete item.
                DeleteItem();
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
        }

        private static void CreateItem()
        {
            var request = new PutItemRequest
            {
                TableName = tableName,
                Item = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  }},
                { "Title", new AttributeValue {
                      S = "Book 201 Title"
                  }},
                { "ISBN", new AttributeValue {
                      S = "11-11-11-11"
                  }},
                { "Authors", new AttributeValue {
                      SS = new List<string>{"Author1", "Author2" }
                  }},
                { "Price", new AttributeValue {
                      N = "20.00"
                  }},
                { "Dimensions", new AttributeValue {
                      S = "8.5x11.0x.75"
                  }},
                { "InPublication", new AttributeValue {
                      BOOL = false
                  } }
            }
            };
            client.PutItem(request);
        }

        private static void RetrieveItem()
        {
            var request = new GetItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                ProjectionExpression = "Id, ISBN, Title, Authors",
                ConsistentRead = true
            };
            var response = client.GetItem(request);

            // Check the response.
            var attributeList = response.Item; // attribute list in the response.
            Console.WriteLine("\nPrinting item after retrieving it ............");
            PrintItem(attributeList);
        }

        private static void UpdateMultipleAttributes()
        {
            var request = new UpdateItemRequest
            {
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                // Perform the following updates:
                // 1) Add two new authors to the list
                // 1) Set a new attribute
                // 2) Remove the ISBN attribute
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#A","Authors"},
                {"#NA","NewAttribute"},
                {"#I","ISBN"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":auth",new AttributeValue {
                     SS = {"Author YY", "Author ZZ"}
                 }},
                {":new",new AttributeValue {
                     S = "New Value"
                 }}
            },

                UpdateExpression = "ADD #A :auth SET #NA = :new REMOVE #I",

                TableName = tableName,
                ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.
            };
            var response = client.UpdateItem(request);

            // Check the response.
            var attributeList = response.Attributes; // attribute list in the response.
                                                     // print attributeList.
            Console.WriteLine("\nPrinting item after multiple attribute update ............");
            PrintItem(attributeList);
        }

        private static void UpdateExistingAttributeConditionally()
        {
            var request = new UpdateItemRequest
            {
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#P", "Price"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":newprice",new AttributeValue {
                     N = "22.00"
                 }},
                {":currprice",new AttributeValue {
                     N = "20.00"
                 }}
            },
                // This updates price only if current price is 20.00.
                UpdateExpression = "SET #P = :newprice",
                ConditionExpression = "#P = :currprice",

                TableName = tableName,
                ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.
            };
            var response = client.UpdateItem(request);

            // Check the response.
            var attributeList = response.Attributes; // attribute list in the response.
            Console.WriteLine("\nPrinting item after updating price value conditionally ............");
            PrintItem(attributeList);
        }

        private static void DeleteItem()
        {
            var request = new DeleteItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },

                // Return the entire item as it appeared before the update.
                ReturnValues = "ALL_OLD",
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#IP", "InPublication"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":inpub",new AttributeValue {
                     BOOL = false
                 }}
            },
                ConditionExpression = "#IP = :inpub"
            };

            var response = client.DeleteItem(request);

            // Check the response.
            var attributeList = response.Attributes; // Attribute list in the response.
                                                     // Print item.
            Console.WriteLine("\nPrinting item that was just deleted ............");
            PrintItem(attributeList);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }
    }
}
```

# Beispiel: Batch-Operationen mit der AWS SDK für .NET Low-Level-API
<a name="batch-operation-lowlevel-dotnet"></a>

**Topics**
+ [Beispiel: Batch-Schreibvorgang mit der AWS SDK für .NET Low-Level-API](#batch-write-low-level-dotnet)
+ [Beispiel: Batch-Abruf-Vorgang mit der AWS SDK für .NET Low-Level-API](#LowLevelDotNetBatchGet)

Dieser Abschnitt enthält Beispiele für Batchvorgänge, *Batch-Schreibvorgänge* und *Batch-Get*, die Amazon DynamoDB unterstützt.

## Beispiel: Batch-Schreibvorgang mit der AWS SDK für .NET Low-Level-API
<a name="batch-write-low-level-dotnet"></a>

Das folgende C\$1-Codebeispiel verwendet die `BatchWriteItem`-Methode für die folgenden Operationen zum Einfügen und Löschen:
+ Einfügen eines Elements in die `Forum`-Tabelle
+ Einfügen und Löschen eines Elements aus der `Thread`-Tabelle 

Bei der Erstellung Ihrer BatchWrite-Anforderung können Sie eine beliebige Anzahl von Einfüge- und Lösch-Anforderungen angeben. DynamoDB `BatchWriteItem` begrenzt jedoch die Größe einer Batch-Schreibanforderung und die Anzahl der Put- und Delete-Vorgänge in einem einzelnen Batch-Schreibvorgang. Weitere Informationen finden Sie unter [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html). Wenn Ihre Anforderung diese Grenzwerte überschreitet, wird sie abgelehnt. Wenn die Tabelle nicht über ausreichend bereitgestellten Durchsatz für diese Anforderung verfügt, werden nicht verarbeitete Anforderungselemente in der Antwort zurückgegeben. 

Im folgenden Beispiel wird die Antwort auf unverarbeitete Anforderungselemente überprüft. Liegen unverarbeitete Elemente vor, wird der Vorgang wiederholt und die `BatchWriteItem`-Anforderung mit unverarbeiteten Elementen wird erneut gesendet. Sie können diese Beispieltabellen auch erstellen und Beispieldaten programmgesteuert hochladen. Weitere Informationen finden Sie unter [Erstellen von Beispieltabellen und Hochladen von Daten mit dem AWS SDK für .NET](AppendixSampleDataCodeDotNET.md).

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[.NET-Codebeispiele](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelBatchWrite
    {
        private static string table1Name = "Forum";
        private static string table2Name = "Thread";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                TestBatchWrite();
            }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }

            Console.WriteLine("To continue, press Enter");
            Console.ReadLine();
        }

        private static void TestBatchWrite()
        {
            var request = new BatchWriteItemRequest
            {
                ReturnConsumedCapacity = "TOTAL",
                RequestItems = new Dictionary<string, List<WriteRequest>>
            {
                {
                    table1Name, new List<WriteRequest>
                    {
                        new WriteRequest
                        {
                            PutRequest = new PutRequest
                            {
                                Item = new Dictionary<string, AttributeValue>
                                {
                                    { "Name", new AttributeValue {
                                          S = "S3 forum"
                                      } },
                                    { "Threads", new AttributeValue {
                                          N = "0"
                                      }}
                                }
                            }
                        }
                    }
                },
                {
                    table2Name, new List<WriteRequest>
                    {
                        new WriteRequest
                        {
                            PutRequest = new PutRequest
                            {
                                Item = new Dictionary<string, AttributeValue>
                                {
                                    { "ForumName", new AttributeValue {
                                          S = "S3 forum"
                                      } },
                                    { "Subject", new AttributeValue {
                                          S = "My sample question"
                                      } },
                                    { "Message", new AttributeValue {
                                          S = "Message Text."
                                      } },
                                    { "KeywordTags", new AttributeValue {
                                          SS = new List<string> { "S3", "Bucket" }
                                      } }
                                }
                            }
                        },
                        new WriteRequest
                        {
                            // For the operation to delete an item, if you provide a primary key value
                            // that does not exist in the table, there is no error, it is just a no-op.
                            DeleteRequest = new DeleteRequest
                            {
                                Key = new Dictionary<string, AttributeValue>()
                                {
                                    { "ForumName",  new AttributeValue {
                                          S = "Some partition key value"
                                      } },
                                    { "Subject", new AttributeValue {
                                          S = "Some sort key value"
                                      } }
                                }
                            }
                        }
                    }
                }
            }
            };

            CallBatchWriteTillCompletion(request);
        }

        private static void CallBatchWriteTillCompletion(BatchWriteItemRequest request)
        {
            BatchWriteItemResponse response;

            int callCount = 0;
            do
            {
                Console.WriteLine("Making request");
                response = client.BatchWriteItem(request);
                callCount++;

                // Check the response.

                var tableConsumedCapacities = response.ConsumedCapacity;
                var unprocessed = response.UnprocessedItems;

                Console.WriteLine("Per-table consumed capacity");
                foreach (var tableConsumedCapacity in tableConsumedCapacities)
                {
                    Console.WriteLine("{0} - {1}", tableConsumedCapacity.TableName, tableConsumedCapacity.CapacityUnits);
                }

                Console.WriteLine("Unprocessed");
                foreach (var unp in unprocessed)
                {
                    Console.WriteLine("{0} - {1}", unp.Key, unp.Value.Count);
                }
                Console.WriteLine();

                // For the next iteration, the request will have unprocessed items.
                request.RequestItems = unprocessed;
            } while (response.UnprocessedItems.Count > 0);

            Console.WriteLine("Total # of batch write API calls made: {0}", callCount);
        }
    }
}
```

## Beispiel: Batch-Abruf-Vorgang mit der AWS SDK für .NET Low-Level-API
<a name="LowLevelDotNetBatchGet"></a>

Im folgenden C\$1-Codebeispiel wird die `BatchGetItem` Methode zum Abrufen mehrerer Elemente aus den `Forum`- und `Thread`-Tabellen in Amazon DynamoDB verwendet. Die `BatchGetItemRequest` gibt die Tabellennamen sowie eine Liste der Primärschlüssel für jede Tabelle an. In dem Beispiel wird die Antwort durch Drucken der abgerufenen Elemente verarbeitet. 

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[.NET-Codebeispiele](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelBatchGet
    {
        private static string table1Name = "Forum";
        private static string table2Name = "Thread";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                RetrieveMultipleItemsBatchGet();

                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }

        private static void RetrieveMultipleItemsBatchGet()
        {
            var request = new BatchGetItemRequest
            {
                RequestItems = new Dictionary<string, KeysAndAttributes>()
            {
                { table1Name,
                  new KeysAndAttributes
                  {
                      Keys = new List<Dictionary<string, AttributeValue> >()
                      {
                          new Dictionary<string, AttributeValue>()
                          {
                              { "Name", new AttributeValue {
                            S = "Amazon DynamoDB"
                        } }
                          },
                          new Dictionary<string, AttributeValue>()
                          {
                              { "Name", new AttributeValue {
                            S = "Amazon S3"
                        } }
                          }
                      }
                  }},
                {
                    table2Name,
                    new KeysAndAttributes
                    {
                        Keys = new List<Dictionary<string, AttributeValue> >()
                        {
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon DynamoDB"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "DynamoDB Thread 1"
                                  } }
                            },
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon DynamoDB"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "DynamoDB Thread 2"
                                  } }
                            },
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon S3"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "S3 Thread 1"
                                  } }
                            }
                        }
                    }
                }
            }
            };

            BatchGetItemResponse response;
            do
            {
                Console.WriteLine("Making request");
                response = client.BatchGetItem(request);

                // Check the response.
                var responses = response.Responses; // Attribute list in the response.

                foreach (var tableResponse in responses)
                {
                    var tableResults = tableResponse.Value;
                    Console.WriteLine("Items retrieved from table {0}", tableResponse.Key);
                    foreach (var item1 in tableResults)
                    {
                        PrintItem(item1);
                    }
                }

                // Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error.
                Dictionary<string, KeysAndAttributes> unprocessedKeys = response.UnprocessedKeys;
                foreach (var unprocessedTableKeys in unprocessedKeys)
                {
                    // Print table name.
                    Console.WriteLine(unprocessedTableKeys.Key);
                    // Print unprocessed primary keys.
                    foreach (var key in unprocessedTableKeys.Value.Keys)
                    {
                        PrintItem(key);
                    }
                }

                request.RequestItems = unprocessedKeys;
            } while (response.UnprocessedKeys.Count > 0);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }
    }
}
```

# Beispiel: Umgang mit binären Attributen mithilfe der AWS SDK für .NET Low-Level-API
<a name="LowLevelDotNetBinaryTypeExample"></a>

Das folgende C\$1-Codebeispiel veranschaulicht den Umgang mit Attributen des Typs Binärwert. Bei dem Beispiel wird der `Reply`-Tabelle ein Element hinzugefügt. Das Element enthält ein Binärtypattribut (`ExtendedMessage`), in dem komprimierte Daten gespeichert sind. Daraufhin wird das Element abgerufen und es werden alle Attributwerte gedruckt. Zur Veranschaulichung verwendet das Beispiel die `GZipStream`-Klasse, um einen Beispiel-Stream zu komprimieren und ihn dem Attribut `ExtendedMessage` hinzuzufügen, und dekomprimiert den Stream beim Drucken des Attributwerts. 

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[.NET-Codebeispiele](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelItemBinaryExample
    {
        private static string tableName = "Reply";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            // Reply table primary key.
            string replyIdPartitionKey = "Amazon DynamoDB#DynamoDB Thread 1";
            string replyDateTimeSortKey = Convert.ToString(DateTime.UtcNow);

            try
            {
                CreateItem(replyIdPartitionKey, replyDateTimeSortKey);
                RetrieveItem(replyIdPartitionKey, replyDateTimeSortKey);
                // Delete item.
                DeleteItem(replyIdPartitionKey, replyDateTimeSortKey);
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }

        private static void CreateItem(string partitionKey, string sortKey)
        {
            MemoryStream compressedMessage = ToGzipMemoryStream("Some long extended message to compress.");
            var request = new PutItemRequest
            {
                TableName = tableName,
                Item = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  }},
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  }},
                { "Subject", new AttributeValue {
                      S = "Binary type "
                  }},
                { "Message", new AttributeValue {
                      S = "Some message about the binary type"
                  }},
                { "ExtendedMessage", new AttributeValue {
                      B = compressedMessage
                  }}
            }
            };
            client.PutItem(request);
        }

        private static void RetrieveItem(string partitionKey, string sortKey)
        {
            var request = new GetItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  } },
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  } }
            },
                ConsistentRead = true
            };
            var response = client.GetItem(request);

            // Check the response.
            var attributeList = response.Item; // attribute list in the response.
            Console.WriteLine("\nPrinting item after retrieving it ............");

            PrintItem(attributeList);
        }

        private static void DeleteItem(string partitionKey, string sortKey)
        {
            var request = new DeleteItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  } },
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  } }
            }
            };
            var response = client.DeleteItem(request);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]") +
                    (value.B == null ? "" : "B=[" + FromGzipMemoryStream(value.B) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }

        private static MemoryStream ToGzipMemoryStream(string value)
        {
            MemoryStream output = new MemoryStream();
            using (GZipStream zipStream = new GZipStream(output, CompressionMode.Compress, true))
            using (StreamWriter writer = new StreamWriter(zipStream))
            {
                writer.Write(value);
            }
            return output;
        }

        private static string FromGzipMemoryStream(MemoryStream stream)
        {
            using (GZipStream zipStream = new GZipStream(stream, CompressionMode.Decompress))
            using (StreamReader reader = new StreamReader(zipStream))
            {
                return reader.ReadToEnd();
            }
        }
    }
}
```

# Verbessern des Datenzugriffs mit sekundären Indizes in DynamoDB
<a name="SecondaryIndexes"></a>

Amazon DynamoDB bietet einen schnellen Zugriff auf Elemente in einer Tabelle durch Angeben von Primärschlüsselwerten. Viele Anwendungen können jedoch davon profitieren, wenn ein oder mehrere Sekundärschlüssel (oder alternative Schlüssel) verfügbar sind, um effizienten Zugriff auf Daten mit anderen Attributen als dem Primärschlüssel zu erlauben. Dazu können Sie einen oder mehrere sekundäre Indizes für eine Tabelle erstellen und `Query`- oder `Scan`-Anforderungen für diese Indizes ausgeben.

Ein *sekundärer Index* ist eine Datenstruktur, die eine Teilmenge der Attribute aus einer Tabelle zusammen mit einem alternativen Schlüssel zur Unterstützung von `Query`-Operationen enthält. Sie können Daten aus dem Index mit einer `Query`-Operation ähnlich wie `Query` für eine Tabelle abrufen. Eine Tabelle kann mehrere sekundäre Indizes enthalten, die Ihren Anwendungen Zugriff auf viele verschiedene Abfragemuster bieten.

**Anmerkung**  
Sie können außerdem eine `Scan`-Operation für einen Index ähnlich wie `Scan` für eine Tabelle ausführen.   
Kontoübergreifender Zugriff für sekundäre Indexscanvorgänge wird derzeit nicht für [ressourcenbasierte Richtlinien](access-control-resource-based.md) unterstützt.

Jeder sekundäre Index ist genau einer Tabelle zugeordnet, von der er seine Daten erhält. Diese Tabelle wird als *Basistabelle* für den Index bezeichnet. Beim Erstellen eines Indexes definieren Sie einen alternativen Schlüssel für den Index (Partitionsschlüssel und Sortierschlüssel). Außerdem definieren Sie die Attribute, die von der Basistabelle in den Index *projiziert* oder kopiert werden sollen. DynamoDB kopiert diese Attribute in den Index zusammen mit den Primärschlüsselattributen für die Basistabelle. Sie können den Index dann genauso abfragen oder scannen wie eine Tabelle. 

Jeder sekundäre Index wird von DynamoDB verwaltet. Wenn Sie der Basistabelle Elemente hinzufügen, ändern oder löschen, werden alle Indizes dieser Tabelle ebenfalls aktualisiert, um diese Änderungen zu berücksichtigen.

DynamoDB unterstützt zwei Arten sekundärer Indizes:
+ **[Globaler sekundärer Index](GSI.html) – ** Dieser Index verfügt über einen Partitionsschlüssel und einen Sortierschlüssel, die nicht mit denen der Basistabelle übereinstimmen müssen. Ein globaler sekundärer Index wird als „global“ betrachtet, da Indexabfragen partitionsübergreifend alle Daten in der Basistabelle umfassen können. Ein globaler sekundärer Index wird in einem eigenen Partitionsbereich abseits der Basistabelle gespeichert und von der Basistabelle getrennt skaliert.
+ **[Lokaler sekundärer Index](LSI.html)  – **Dieser Index weist denselben Partitionsschlüssel wie die Basistabelle auf, hat aber einen anderen Sortierschlüssel. Ein lokaler sekundärer Index wird als „lokal“ betrachtet, da jede Partition eines lokalen sekundären Index auf die Basistabellenpartition bezogen ist, die denselben Partitionsschlüsselwert besitzt.

Einen Vergleich der globalen Sekundärindizes und der lokalen Sekundärindizes finden Sie in diesem Video.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/BkEu7zBWge8/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/BkEu7zBWge8)


**Topics**
+ [Verwenden globaler sekundärer Indizes in DynamoDB](GSI.md)
+ [Lokale sekundäre Indizes](LSI.md)

Berücksichtigen Sie die Anforderungen Ihrer Anwendung, wenn Sie sich für einen Indextyp entscheiden. In der folgenden Tabelle werden die Hauptunterschiede zwischen einem globalen sekundären Index und einem lokalen sekundären Index dargelegt.


****  

| Merkmal | Globaler sekundärer Index | Lokaler sekundärer Index | 
| --- | --- | --- | 
| Schlüsselschema | Der Primärschlüssel eines globalen sekundärer Indizes kann entweder einfach (Partitionsschlüssel) oder zusammengesetzt sein (Partitions- und Sortierschlüssel). | Der Primärschlüssel eines lokalen sekundären Indizes muss zusammengesetzt sein (Partitions- und Sortierschlüssel). | 
| Schlüsselattribute | Der Indexpartitions- und Sortierschlüssel (sofern vorhanden) kann ein beliebiges Basistabellenattribut vom Typ Zeichenfolge, Zahl oder Binärwert sein. | Der Partitionsschlüssel des Indexes ist dasselbe Attribut wie der Partitionsschlüssel der Basistabelle. Der Sortierschlüssel kann ein beliebiges Basistabellenattribut vom Typ Zeichenfolge, Zahl oder Binärwert sein. | 
| Größenbeschränkungen pro Partitionsschlüsselwert | Für globale sekundäre Indizes gibt es keine Größenbeschränkungen. | Für jeden Partitionsschlüsselwert darf die Gesamtgröße aller indizierten Elemente höchstens 10 GB betragen. | 
| Online-Indizierungsoperationen | Globale sekundäre Indizes können gleichzeitig mit der Tabelle erstellt werden. Sie können einer vorhandenen Tabelle auch einen neuen globalen sekundären Index hinzufügen oder einen vorhandenen globalen sekundären Index löschen. Weitere Informationen finden Sie unter [Verwalten globaler sekundärer Indizes in DynamoDB](GSI.OnlineOps.md).  | Globale sekundäre Indizes werden zur selben Zeit wie die Tabelle erstellt. Sie können einer vorhandenen Tabelle keinen lokalen sekundären Index hinzufügen oder vorhandene lokale sekundäre Indizes löschen. | 
| Abfragen und Partitionen | Mit einem globalen sekundären Index können Sie die gesamte Tabelle partitionsübergreifend abfragen.  | Ein lokaler sekundärer Index ermöglicht das Abfragen über eine einzelne Partition, wie vom Partitionsschlüsselwert in der Abfrage angegeben. | 
| Lesekonsistenz | Abfragen zu globalen sekundären Indizes unterstützen nur Eventual Consistency. | Wenn Sie einen lokalen sekundären Index abfragen, können Sie entweder Eventually Consistent oder Strongly Consistent auswählen. | 
| Verbrauch der bereitgestellten Durchsatzkapazität | Jeder globaler sekundärer Index verfügt über eigene Einstellungen für den bereitgestellten Durchsatz für Lese- und Schreibaktivitäten. Abfragen oder Scans für einen globalen sekundären Index verbrauchen Kapazitätseinheiten des Indexes und nicht der Basistabelle. Dasselbe gilt für globale sekundäre Index-Aktualisierungen aufgrund von Tabellenschreibvorgängen. Ein globaler sekundärer Index, der globalen Tabellen zugeordnet ist, verbraucht Schreibkapazitätseinheiten.  | Abfragen oder Scans für einen lokalen sekundären Index verbrauchen Lesekapazitätseinheiten der Basistabelle. Wenn Sie Daten in eine Tabelle schreiben, werden die zugehörigen lokalen sekundären Indizes ebenfalls aktualisiert. Diese Aktualisierungen verbrauchen Schreibkapazitätseinheiten aus der Basistabelle. Ein lokaler sekundärer Index, der globalen Tabellen zugeordnet ist, verbraucht replizierte Schreibkapazitätseinheiten. | 
| Projizierte Attribute | Mit globalen sekundären Index-Abfragen oder -Scans können Sie nur die Attribute anfordern, die in den Index projiziert sind. DynamoDB ruft keine Attribute aus der Tabelle ab. | Wenn Sie einen lokalen sekundären Index abfragen oder scannen können Sie Attribute anfordern, die nicht in den Index projiziert sind. DynamoDB ruft diese Attribute automatisch aus der Tabelle ab. | 

Wenn Sie mehr als eine Tabelle mit sekundären Indizes erstellen möchten, müssen Sie diesen Vorgang sequenziell ausführen. Beispielsweise erstellen Sie die erste Tabelle und warten, bis sie `ACTIVE` wird. Dann erstellen Sie die nächste Tabelle und warten bis sie `ACTIVE` wird und so weiter. Wenn Sie versuchen, gleichzeitig mehr als eine Tabelle mit einem sekundären Index zu erstellen, gibt DynamoDB eine `LimitExceededException` zurück.

Jeder sekundäre Index verwendet dieselbe [Tabellenklasse](HowItWorks.TableClasses.html) und denselben [Kapazitätsmodus](capacity-mode.md) wie die Basistabelle, der er zugeordnet ist. Geben Sie für jeden sekundären Index Folgendes an:
+ Der Typ des zu erstellenden Indexes – entweder ein globaler sekundärer Index oder ein lokaler sekundärer Index.
+ Einen Namen für den Index. Die Namenskonventionen für Indizes sind mit den Konventionen für Tabellen identisch, wie in [Kontingente in Amazon DynamoDB](ServiceQuotas.md) aufgelistet. Der Name muss für die Basistabelle, der er zugeordnet ist, eindeutig sein. Sie können allerdings denselben Namen für Indizes verwenden, die verschiedenen Basistabellen zugeordnet sind.
+ Das Schlüsselschema für den Index. Jedes Attribut im Indexschlüsselschema muss ein Attribut auf oberster Ebene vom Typ `String`, `Number` oder `Binary` sein. Andere Datentypen, einschließlich Dokumenten und Sätzen, sind nicht zulässig. Andere Anforderungen für das Schlüsselschema hängen vom Indextyp ab: 
  + Für einen globalen sekundären Index kann der Partitionsschlüssel ein beliebiges skalares Attribut der Basistabelle sein. Ein Sortierschlüssel ist optional und kann ebenfalls ein beliebiges skalares Attribut der Basistabelle sein.
  + Für einen lokalen sekundären Index muss der Partitionsschlüssel mit dem Partitionsschlüssel der Basistabelle übereinstimmen und der Sortierschlüssel muss ein Nicht-Schlüssel-Basistabellenattribut sein.
+ Zusätzliche Attribute, sofern vorhanden, werden von der Basistabelle in den Index projiziert. Diese Attribute ergänzen die Schlüsselattribute der Tabelle, die automatisch in jeden Index projiziert werden. Sie können Attribute jedes Datentyps, einschließlich Skalaren, Dokumenten und Sätzen, projizieren.
+ Die Einstellungen des für den Index bereitgestellten Durchsatzes, falls erforderlich:
  + Für einen globalen sekundären Index müssen Sie Einstellungen für Lese- und Schreibkapazitätseinheiten angeben. Diese Einstellungen für den bereitgestellten Durchsatz sind von den Einstellungen der Basistabelle unabhängig.
  + Für einen lokalen sekundären Index müssen Sie keine Einstellungen für Lese- und Schreibkapazitätseinheiten angeben. Alle Lese- und Schreibvorgänge für einen lokalen sekundären Index nutzen die Einstellungen des bereitgestellten Durchsatzes der entsprechenden Basistabelle.

Für maximale Abfrageflexibilität können Sie bis zu 20 globale sekundäre Indizes (Standardkontingent) und bis zu 5 lokale sekundäre Indizes pro Tabelle erstellen.

Um eine detaillierte Liste der sekundären Indizes in einer Tabelle abzurufen, verwenden Sie die `DescribeTable`-Operation. `DescribeTable` gibt den Namen, die Speichergröße und die Elementanzahl für jeden sekundären Index in der Tabelle zurück. Diese Werte werden nicht in Echtzeit, sondern etwa alle sechs Stunden aktualisiert.

Sie können auf die Daten in einem sekundären Index entweder mit der `Query`- oder der `Scan`-Operation zugreifen. Sie müssen den Namen der Basistabelle und den Namen des Indexes, den Sie verwenden möchten, die Attribute, die in den Abfrageergebnissen zurückgegeben werden sollen, und etwaige Bedingungsausdrücke oder Filter, die Sie anwenden möchten, angeben. DynamoDB kann Ergebnisse in auf- oder absteigender Reihenfolge liefern.

Beim Löschen einer Tabelle werden alle dieser Tabelle zugeordneten Indizes ebenfalls gelöscht.

Bewährte Methoden finden Sie unter [Bewährte Methoden für die Verwendung sekundärer Indexe in DynamoDB](bp-indexes.md).

# Verwenden globaler sekundärer Indizes in DynamoDB
<a name="GSI"></a>

Einige Anwendungen müssen u. U. viele Arten von Abfragen ausführen und verwenden dabei eine Vielzahl von verschiedenen Attributen als Abfragekriterien. Um diese Anforderungen zu unterstützen, können Sie eine oder mehrere *globale sekundäre Indizes* erstellen und `Query`-Anforderungen für diese Indizes in Amazon DynamoDB generieren.

**Topics**
+ [Schritt 6: Verwenden eines globalen sekundären Indexes](#GSI.scenario)
+ [Attributprojektionen](#GSI.Projections)
+ [Schlüsselschema mit mehreren Attributen](#GSI.MultiAttributeKeys)
+ [Lesen von Daten aus einem globalen sekundären Index](#GSI.Reading)
+ [Datensynchronisierung zwischen Tabellen und globalen sekundären Indizes](#GSI.Writes)
+ [Tabellenklassen mit globalen sekundären Indizes](#GSI.tableclasses)
+ [Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für globale sekundäre Indizes](#GSI.ThroughputConsiderations)
+ [Speicherüberlegungen für globale sekundäre Indizes](#GSI.StorageConsiderations)
+ [Muster entwerfen](GSI.DesignPatterns.md)
+ [Verwalten globaler sekundärer Indizes in DynamoDB](GSI.OnlineOps.md)
+ [Erkennen und Korrigieren von Indexschlüsselverstößen in DynamoDB](GSI.OnlineOps.ViolationDetection.md)
+ [Arbeiten mit globalen sekundären Indizes: Java](GSIJavaDocumentAPI.md)
+ [Arbeiten mit globalen sekundären Indizes: .NET](GSILowLevelDotNet.md)
+ [Arbeiten mit globalen sekundären Indizes in DynamoDB mithilfe der AWS CLI](GCICli.md)

## Schritt 6: Verwenden eines globalen sekundären Indexes
<a name="GSI.scenario"></a>

Betrachten wir ein Beispiel zur Veranschaulichung. Eine Tabelle mit dem Namen `GameScores` erfasst die Benutzer und Punktzahlen für eine mobile Gaming-Anwendung. Jedes Element in `GameScores` wird anhand eines Partitionsschlüssels (`UserId`) und eines Sortierschlüssels (`GameTitle`) identifiziert. Das folgende Diagramm zeigt, wie die Elemente in der Tabelle organisiert wären. (Es werden nicht alle Attribute angezeigt.)

![\[GameScores Tabelle mit einer Liste von Benutzer-ID, Titel, Punktzahl, Datum und Gewinnen/Niederlagen.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_01.png)


Angenommen, Sie möchten eine Bestenlisten-Anwendung für die Anzeige der höchsten Punktzahlen für jedes Spiel entwickeln. Eine Abfrage, die die Schlüsselattribute (`UserId` und `GameTitle`) angibt, wäre äußerst effizient. Wenn die Anwendung Daten aus `GameScores` nur basierend auf `GameTitle` abrufen muss, muss sie eine `Scan`-Operation verwenden. Wenn immer mehr Elemente der Tabelle hinzugefügt werden, werden die Scans aller Daten langsam und ineffizient. Dadurch wird die Beantwortung von folgenden Fragen erschwert:
+ Was ist die höchste Punktzahl, die für das Spiel Meteor Blaster jemals erfasst wurde?
+ Welche Benutzer hatte die höchste Punktzahl für Galaxy Invaders?
+ Wie war das höchste Verhältnis zwischen gewonnen und verlorenen Spielen?

Zum Beschleunigen von Abfragen auf der Basis von Nicht-Schlüsselattributen können Sie einen globalen sekundären Index erstellen. Ein globaler sekundärer Index enthält eine Auswahl von Attributen aus der Basistabelle. Diese sind jedoch nach einem Primärschlüssel organisiert, der sich von dem Schlüssel der Tabelle unterscheidet. Der Indexschlüssel benötigt keinen der Schlüsselattribute aus der Tabelle. Er muss nicht einmal über dasselbe Schlüsselschema verfügen wie eine Tabelle.

Sie können beispielsweise einen globalen sekundären Index mit dem Namen `GameTitleIndex` mit einem Partitionsschlüssel `GameTitle` und einem Sortierschlüssel `TopScore` erstellen. Da die Primärschlüsselattribute der Basistabelle immer in einen Index projiziert werden, ist das Attribut `UserId` ebenfalls vorhanden. Das folgende Diagramm veranschaulicht, wie der Index `GameTitleIndex` aussehen würde.

![\[GameTitleIndex Tabelle mit einer Liste von Titeln, Ergebnissen und Benutzer-IDs.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_02.png)


Jetzt können Sie `GameTitleIndex` abfragen und die Punktzahlen für Meteor Blasters einfach erhalten. Die Ergebnisse werden nach den Sortierschlüsselwerten `TopScore` sortiert. Wenn Sie den Parameter `ScanIndexForward` auf False festlegen, werden die Ergebnisse in der absteigender Reihenfolge mit der höchsten Punktzahl zuerst zurückgegeben.

Jeder globale sekundäre Index muss über einen Partitionsschlüssel verfügen und kann einen optionalen Sortierschlüssel besitzen. Das Indexschlüsselschema kann sich vom Basistabellenschema unterscheiden. Sie können eine Tabelle mit einem einfachen Primärschlüssel (Partitionsschlüssel) vorliegen haben und einen globalen sekundären Index mit einem zusammengesetzten Primärschlüssel (Partitions- und Sortierschlüssel) erstellen oder umgekehrt. Die Indexschlüsselattribute können aus beliebigen Top-Level-Attributen vom Typ `String`, `Number` oder `Binary` der Basistabelle bestehen. Andere Skalar-, Dokument- und Satztypen sind nicht zulässig.

Sie können andere Basistabellenattribute in den Index projizieren, wenn Sie möchten. Wenn Sie den Index abfragen, kann DynamoDB diese projizierten Attribute effizient abrufen. Globale sekundäre Index-Abfragen können jedoch keine Attribute aus der Basistabelle abrufen. Wenn Sie beispielsweise `GameTitleIndex` wie im Diagramm oben veranschaulicht abgefragt haben, kann die Abfrage nicht auf Nicht-Schlüsselattribute außer `TopScore` zugreifen (die Schlüsselattribute `GameTitle` und `UserId` werden allerdings automatisch projiziert).

In einer DynamoDB-Tabelle, muss jeder Schlüsselwert eindeutig sein. Die Schlüsselwerte in einem globalen sekundären Index müssen jedoch nicht eindeutig sein. Beispiel: Angenommen, ein Spiel mit dem Namen Comet Quest ist besonders schwierig. Viele neue Benutzer probieren es aus, schaffen es aber nicht, eine Punktzahl über Null zu erreichen. Im Folgenden finden Sie einige der Daten, die dies veranschaulichen.


****  

| UserId | GameTitle | TopScore | 
| --- | --- | --- | 
| 123 | Comet Quest | 0 | 
| 201 | Comet Quest | 0 | 
| 301 | Comet Quest | 0 | 

Wenn diese Daten der Tabelle `GameScores` hinzugefügt werden, verteilt DynamoDB sie auf `GameTitleIndex`. Wenn wir dann den Index mit Comet Quest für `GameTitle` und mit 0 für `TopScore` abfragen, werden die folgenden Daten zurückgegeben.

![\[Tabelle mit einer Liste mit Titeln, Höchstpunktzahlen und Benutzer-IDs.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_05.png)


Es werden nur die Elemente mit den angegebenen Schlüsselwerten in der Antwort angezeigt. Innerhalb dieser Datengruppe werden die Elemente nicht in einer bestimmten Reihenfolge angezeigt. 

Ein globaler sekundärer Index verfolgt nur Datenelemente, bei denen die Schlüsselattribute tatsächlich vorhanden sind. Angenommen, Sie haben der Tabelle `GameScores` ein neues Element hinzugefügt, jedoch nur die erforderlichen Primärschlüsselattribute bereitgestellt.


****  

| UserId | GameTitle | 
| --- | --- | 
| 400 | Comet Quest | 

Da Sie das Attribut `TopScore` nicht angegeben haben, verteilt DynamoDB dieses Element nicht über `GameTitleIndex`. Wenn Sie `GameScores` für alle Comet Quest-Elemente abfragen, erhalten Sie die folgenden vier Elemente:

![\[Tabelle mit einer Liste mit vier Titeln, Höchstpunktzahlen und Benutzer-IDs.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_04.png)


Eine ähnliche Abfrage für `GameTitleIndex` gibt drei Elemente statt vier zurück. Der Grund hierfür ist, dass das Element mit dem nicht vorhandenen `TopScore` nicht an den Index verteilt wird.

![\[Tabelle mit einer Liste mit drei Titeln, Höchstpunktzahlen und Benutzer-IDs.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_05.png)


## Attributprojektionen
<a name="GSI.Projections"></a>

Eine *Projektion* ist der Satz von Attributen, die aus einer Tabelle in einen sekundären Index kopiert werden. Der Partitionsschlüssel und der Sortierschlüssel der Tabelle werden immer in den Index projiziert. Sie können andere Attribute projizieren, um die Abfrageanforderungen Ihrer Anwendung zu unterstützen. Wenn Sie einen Index abfragen, kann Amazon DynamoDB auf jedes Attribut in der Projektion zugreifen, als ob sich diese Attribute in einer eigenen Tabelle befinden.

Wenn Sie einen sekundären Index erstellen, müssen Sie die Attribute angeben, die in den Index projiziert werden. DynamoDB bietet hierfür drei verschiedene Optionen:
+ *KEYS\$1ONLY* – Jeder Eintrag im Index besteht nur aus dem Tabellenpartitionsschlüssel und Sortierschlüsselwerten, sowie den Indexschlüsselwerten. Die Option `KEYS_ONLY` führt zu dem kleinstmöglichen sekundären Index.
+ *INCLUDE* – Zusätzlich zu den in `KEYS_ONLY` beschriebenen Attributen, enthält der sekundäre Index andere Nicht-Schlüsselattribute, die Sie angeben.
+ *ALL* – Der sekundäre Index enthält alle Attribute der Quelltabelle. Da alle Tabellendaten im Index dupliziert werden, wird ein `ALL`-Projektion führt zu dem größtmöglichen sekundären Index.

Im vorherigen Diagramm verfügt `GameTitleIndex` nur über ein projiziertes Attribut: `UserId`. Obwohl eine Anwendung die `UserId` der besten Ergebnisse für jedes Spiel mit `GameTitle` und `TopScore` effizient in Abfragen bestimmen kann, ist es nicht möglich, effizient die höchste Punktzahl für ein bestimmtes Spiel oder das höchste Verhältnis gewonnener und verlorener Spiele bei den besten Ergebnissen zu bestimmen. Dazu müsste die Anwendung eine zusätzliche Abfrage in der Basistabelle durchführen, um die Siege und Niederlagen für jeden der besten Torschützen abzurufen. Abfragen für diese Daten lassen sich effizienter unterstützen, indem diese Attribute aus der Basistabelle in den globalen sekundären Index projiziert werden, wie in folgendem Diagramm dargestellt. 

![\[Darstellung der Projektion von Nicht-Schlüsselattributen in einem globalen sekundären Index zur Unterstützung effizienter Abfragen.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/GSI_06.png)


Da die Nicht-Schlüsselattribute `Wins` und `Losses` in den Index projiziert werden, kann eine Anwendung das Verhältnis zwischen Siegen und Niederlagen für jedes Spiel oder für eine beliebige Kombination aus Spiel und Benutzer-ID bestimmen.

Wenn Sie die Attribute zum Projizieren in einen globalen sekundären Index auswählen, müssen Sie die Differenz der Kosten des bereitgestellten Durchsatzes und der Speicherkosten berücksichtigen:
+ Wenn Sie nur auf wenige Attribute mit möglichst niedriger Latenz zugreifen müssen, erwägen Sie, nur diese Attribute in einen globalen sekundären Index zu projizieren. Je kleiner der Index, desto geringer die Speicher- und somit die Schreibkosten.
+ Greift Ihre Anwendung häufig auf einige Nicht-Schlüsselattribute zu, sollten Sie erwägen, diese Attribute in einen globalen sekundären Index zu projizieren. Die zusätzlichen Speicherkosten für den globalen sekundären Index wiegen die Kosten für die Durchführung häufiger Tabellen-Scans auf.
+ Wenn Sie auf die meisten Nicht-Schlüsselattribute in regelmäßigen Abständen zugreifen müssen, können Sie diese Attribute – oder sogar die gesamte Basistabelle – in einen globalen sekundären Index projizieren. Dadurch erhalten Sie maximale Flexibilität. Ihre Speicherkosten würden allerdings steigen oder sich sogar verdoppeln.
+ Wenn Ihre Anwendung eine Tabelle selten abfragen, jedoch viele Schreibvorgänge oder Updates für die Daten in der Tabelle durchführen muss, erwägen Sie das Projizieren von `KEYS_ONLY`. Der globale sekundäre Index wäre nur klein, stünde aber weiterhin bei Bedarf für Abfrageaktivitäten zur Verfügung. 

## Schlüsselschema mit mehreren Attributen
<a name="GSI.MultiAttributeKeys"></a>

Globale Sekundärindizes unterstützen Schlüssel mit mehreren Attributen, sodass Sie Partitionsschlüssel zusammenstellen und Schlüssel aus mehreren Attributen sortieren können. Mit Schlüsseln mit mehreren Attributen können Sie einen Partitionsschlüssel aus bis zu vier Attributen und einen Sortierschlüssel aus bis zu vier Attributen erstellen, sodass insgesamt bis zu acht Attribute pro Schlüsselschema vorhanden sind.

Schlüssel mit mehreren Attributen vereinfachen Ihr Datenmodell, indem sie das manuelle Verketten von Attributen zu synthetischen Schlüsseln überflüssig machen. Anstatt zusammengesetzte Zeichenketten zu erstellen`TOURNAMENT#WINTER2024#REGION#NA-EAST`, können Sie die natürlichen Attribute aus Ihrem Domänenmodell direkt verwenden. DynamoDB verarbeitet die zusammengesetzte Schlüssellogik automatisch, indem es mehrere Partitionsschlüsselattribute für die Datenverteilung zusammenfasst und die hierarchische Sortierreihenfolge für mehrere Sortierschlüsselattribute beibehält.

Stellen Sie sich beispielsweise ein Spieleturniersystem vor, bei dem Sie Spiele nach Turnieren und Regionen organisieren möchten. Bei Schlüsseln mit mehreren Attributen können Sie Ihren Partitionsschlüssel als zwei separate Attribute definieren: `tournamentId` und`region`. In ähnlicher Weise können Sie Ihren Sortierschlüssel mit mehreren Attributen wie`round`, und definieren`bracket`, `matchId` um eine natürliche Hierarchie zu erstellen. Dieser Ansatz sorgt dafür, dass Ihre Daten eingegeben und Ihr Code sauber bleibt, ohne dass Zeichenketten manipuliert oder analysiert werden müssen.

Wenn Sie einen globalen sekundären Index mit Schlüsseln mit mehreren Attributen abfragen, müssen Sie alle Partitionsschlüsselattribute unter Verwendung von Gleichheitsbedingungen angeben. Bei Sortierschlüsselattributen können Sie sie left-to-right in der Reihenfolge abfragen, in der sie im Schlüsselschema definiert sind. Das bedeutet, dass Sie das erste Sortierschlüsselattribut allein, die ersten beiden Attribute zusammen oder alle Attribute zusammen abfragen können, aber Sie können keine Attribute in der Mitte überspringen. Ungleichheitsbedingungen wie`>`, `<``BETWEEN`, oder `begins_with()` müssen die letzte Bedingung in Ihrer Abfrage sein.

Schlüssel mit mehreren Attributen eignen sich besonders gut, wenn globale Sekundärindizes für bestehende Tabellen erstellt werden. Sie können Attribute verwenden, die bereits in Ihrer Tabelle vorhanden sind, ohne synthetische Schlüssel in Ihren Daten aufzufüllen. Auf diese Weise können Sie Ihrer Anwendung ganz einfach neue Abfragemuster hinzufügen, indem Sie Indizes erstellen, die Ihre Daten mithilfe verschiedener Attributkombinationen neu organisieren.

Jedes Attribut in einem Schlüssel mit mehreren Attributen kann seinen eigenen Datentyp haben: `String` (S), `Number` (N) oder `Binary` (B). Beachten Sie bei der Auswahl von Datentypen, dass `Number` Attribute numerisch sortiert werden, ohne dass Nullen aufgefüllt werden müssen, während Attribute lexikografisch sortiert werden. `String` Wenn Sie beispielsweise einen `Number` Typ für ein Bewertungsattribut verwenden, werden die Werte 5, 50, 500 und 1000 in natürlicher numerischer Reihenfolge sortiert. Dieselben Werte wie `String` Typ würden nach „1000", „5", „50", „500" sortiert, sofern Sie sie nicht mit führenden Nullen auffüllen.

Ordnen Sie beim Entwerfen von Schlüsseln mit mehreren Attributen die Attribute von den allgemeinsten bis hin zu den spezifischsten. Kombinieren Sie bei Partitionsschlüsseln Attribute, die immer zusammen abgefragt werden und für eine gute Datenverteilung sorgen. Platzieren Sie bei Sortierschlüsseln häufig abgefragte Attribute an erster Stelle in der Hierarchie, um die Flexibilität bei der Abfrage zu maximieren. Diese Reihenfolge ermöglicht es Ihnen, Abfragen auf jeder Granularitätsebene durchzuführen, die Ihren Zugriffsmustern entspricht.

Implementierungsbeispiele finden Sie unter. [Schlüssel mit mehreren Attributen](GSI.DesignPattern.MultiAttributeKeys.md)

## Lesen von Daten aus einem globalen sekundären Index
<a name="GSI.Reading"></a>

Sie können Elemente aus einem globalen sekundären Index mithilfe von `Query` und `Scan` verwenden. Die `GetItem` und `BatchGetItem`-Operationen können für einen globalen sekundären Index nicht verwendet werden.

### Abfragen eines globalen sekundären Index
<a name="GSI.Querying"></a>

Sie können die `Query`-Operation für den Zugriff auf ein oder mehrere Elemente in einem globalen sekundären Index verwenden. Die Abfrage muss den Namen der Basistabelle und den Namen des Index, den Sie verwenden möchten, die Attribute, die in den Abfrageergebnissen zurückgegeben werden sollen, und etwaige Abfragebedingungen, die Sie anwenden möchten, angeben. DynamoDB kann Ergebnisse in auf- oder absteigender Reihenfolge liefern.

Sehen Sie sich die folgenden Daten an, die von einer `Query` zurückgegeben wurden, die Spieledaten für eine Bestenlisten-Anwendung abfragt.

```
{
    "TableName": "GameScores",
    "IndexName": "GameTitleIndex",
    "KeyConditionExpression": "GameTitle = :v_title",
    "ExpressionAttributeValues": {
        ":v_title": {"S": "Meteor Blasters"}
    },
    "ProjectionExpression": "UserId, TopScore",
    "ScanIndexForward": false
}
```

Vorgänge in dieser Abfrage:
+ DynamoDB greift zu und verwendet den *GameTitle*Partitionsschlüssel *GameTitleIndex*, um die Indexelemente für Meteor Blasters zu finden. Alle Indexelemente mit diesem Schlüssel werden nebeneinander gespeichert, um ein schnelles Abrufen zu ermöglichen.
+ In diesem Spiel verwendet DynamoDB den Index, um auf alle Benutzer IDs - und Top-Scores für dieses Spiel zuzugreifen.
+ Die Ergebnisse werden in absteigender Reihenfolge sortiert zurückgegeben, da der Parameter `ScanIndexForward` auf False festgelegt ist.

### Scannen eines globalen sekundären Index
<a name="GSI.Scanning"></a>

Sie können die `Scan`-Operation zum Abrufen aller Daten aus einem globalen sekundären Index verwenden. Geben Sie dazu den Namen der Basistabelle sowie den Indexnamen in der Abfrage an. Mit einer `Scan`-Operation liest DynamoDB alle Daten im Index und gibt sie an die Anwendung zurück. Sie können auch anfordern, dass nur einige der Daten zurückgegeben und die verbleibenden Daten verworfen werden. Verwenden Sie dazu den Parameter `FilterExpression` der `Scan`-Operation. Weitere Informationen finden Sie unter [Filterausdrücke für Scan](Scan.md#Scan.FilterExpression).

## Datensynchronisierung zwischen Tabellen und globalen sekundären Indizes
<a name="GSI.Writes"></a>

DynamoDB synchronisiert automatisch jeden globalen sekundären Index mit der Basistabelle. Wenn eine Anwendung Elemente in eine Tabelle schreibt oder daraus löscht, werden globale sekundäre Indizes in dieser Tabelle mit einem Eventually-Consistent-Modell asynchron aktualisiert. Anwendungen schreiben niemals direkt in einen Index. Allerdings ist es wichtig, zu wissen, welche Auswirkungen es hat, wie DynamoDB diese Indizes verwaltet.

 Globale sekundäre Indizes erben den read/write Kapazitätsmodus aus der Basistabelle. Weitere Informationen finden Sie unter [Überlegungen beim Umstellen der Kapazitätsmodi in DynamoDB](bp-switching-capacity-modes.md). 

Wenn Sie einen globalen sekundären Index erstellen, geben Sie ein oder mehrere Indexschlüsselattribute und deren Datentypen an. Das bedeutet, dass wenn Sie ein Element in die Basistabelle schreiben, die Datentypen für diese Attribute den Datentypen des Indexschlüsselschemas entsprechen müssen. Im Fall von `GameTitleIndex` wird der Partitionsschlüssel `GameTitle` im Index als Datentyp `String` definiert. Der Sortierschlüssel `TopScore` im Index ist vom Typ `Number`. Wenn Sie versuchen, der Tabelle `GameScores` ein Element hinzuzufügen und einen anderen Datentyp entweder für `GameTitle` oder `TopScore` anzugeben, gibt DynamoDB eine `ValidationException` aufgrund der fehlenden Übereinstimmung des Datentyps zurück.

Wenn Sie Elemente in eine Tabelle schreiben oder daraus löschen, werden die globalen sekundären Indizes in dieser Tabelle in Eventually Consistent-Form aktualisiert. Änderungen an den Tabellendaten werden unter normalen Bedingungen im Bruchteil einer Sekunde auf die globalen sekundären Indizes verteilt. In einigen seltenen Fehlerszenarien können längere Verzögerungen bei der Verteilung auftreten. Ihre Anwendungen sollten daher Situationen abhelfen können, in denen eine Abfrage für einen globalen sekundären Index Ergebnisse zurückgibt, die nicht auf dem neuesten Stand sind.

Wenn Sie ein Element in eine Tabelle schreiben, müssen Sie keine Attribute für globale sekundäre Index-Sortierschlüssel angeben. Bei `GameTitleIndex` müssen Sie z. B. keinen Wert für das Attribut `TopScore` angeben, um ein neues Element in die Tabelle `GameScores` zu schreiben. In diesem Fall schreibt DynamoDB keine Daten in den Index für dieses bestimmte Element.

Eine Tabelle mit vielen globalen sekundären Indizes verursacht höhere Kosten für Schreibaktivitäten als Tabellen mit weniger Indizes. Weitere Informationen finden Sie unter [Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für globale sekundäre Indizes](#GSI.ThroughputConsiderations).

## Tabellenklassen mit globalen sekundären Indizes
<a name="GSI.tableclasses"></a>

Ein globaler sekundärer Index verwendet immer dieselbe Tabellenklasse wie seine Basistabelle. Jedes Mal, wenn ein neuer globaler sekundärer Index für eine Tabelle hinzugefügt wird, verwendet der neue Index dieselbe Tabellenklasse wie seine Basistabelle. Wenn die Tabellenklasse einer Tabelle aktualisiert wird, werden auch alle zugehörigen globalen sekundären Indizes aktualisiert.

## Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für globale sekundäre Indizes
<a name="GSI.ThroughputConsiderations"></a>

Wenn Sie einen globalen sekundären Index für eine Tabelle mit dem Modus bereitgestellter Kapazität erstellen, müssen Sie Lese- und Schreibkapazitätseinheiten für den erwarteten Workload dieses Indexes angeben. Die Einstellungen für den bereitgestellten Durchsatz eines globalen sekundären Indizes sind getrennt von denen der Basistabelle. Eine `Query`-Operation auf einem globalen sekundären Index verbraucht Lesekapazitätseinheiten des Index und nicht der Basistabelle. Wenn Sie Elemente in eine Tabelle schreiben, sie aktualisieren oder aus der Tabelle löschen, werden die globalen sekundären Indizes in dieser Tabelle in Eventually Consistent-Form aktualisiert. Diese Indexaktualisierungen verbrauchen Kapazitätseinheiten des Indexes und nicht der Basistabelle.

Wenn Sie beispielsweise eine `Query`-Operation für einen ausführen und die bereitgestellte Lesekapazität überschreiten, wird die Anforderung gedrosselt. Wenn Sie viele Schreibaktivitäten für die Tabelle ausführen, ein globaler sekundärer Index dieser Tabelle jedoch über nicht genügend Schreibkapazität verfügt, dann wird die Schreibaktivität der Tabelle gedrosselt.

**Wichtig**  
 Damit es zu keiner Ablehnung kommt, sollte die bereitgestellte Kapazität für Schreibvorgänge bei einem globalen sekundären Index gleich oder größer als die Kapazität für Schreibvorgänge der Basistabelle sein, da neue Aktualisierungen in die Basistabelle und den globalen sekundären Index geschrieben werden. 

Verwenden Sie zum Anzeigen der Einstellungen des bereitgestellten Durchsatzes für einen globalen sekundären Index die `DescribeTable`-Operation. Es werden detaillierte Informationen zu globalen sekundären Indizes für die Tabelle zurückgegeben.

### Lesekapazitätseinheiten
<a name="GSI.ThroughputConsiderations.Reads"></a>

Globale sekundäre Indizes unterstützen Eventually Consistent-Lesevorgänge, die jeweils eine halbe Lesekapazitätseinheit verbrauchen. Das bedeutet, dass eine einzelne globale sekundäre Index-Abfrage bis zu 2 × 4 KB = 8 KB pro Lesekapazitätseinheit abrufen kann.

Für globale sekundäre Index-Abfragen berechnet DynamoDB die bereitgestellten Lesevorgänge auf die gleiche Weise wie für Abfragen der Tabellen. Der einzige Unterschied besteht darin, dass die Berechnung auf der Größe der Indexeinträge und nicht auf der Größe des Elements in der Basistabelle beruht. Die Anzahl der Lesekapazitätseinheiten ist die Summe aller projizierten Attributgrößen sämtlicher zurückgegebener Elemente. Das Ergebnis wird dann auf den nächsten 4 KB-Grenzwert aufgerundet. Weitere Informationen darüber, wie DynamoDB die bereitgestellte Durchsatznutzung berechnet, finden Sie unter [DynamoDB – Modus mit bereitgestellter Kapazität](provisioned-capacity-mode.md).

Die maximale Größe der von einer `Query`-Operation zurückgegebenen Ergebnisse beträgt 1MB. Diese umfasst die Größen aller Attributnamen und Werte sämtlicher zurückgegebenen Elemente.

Nehmen wir als Beispiel einen globalen sekundären Index bei dem jedes Element 2 000 Byte Daten enthält. Angenommen, Sie führen eine `Query`-Operation für diesen Index aus, bei der `KeyConditionExpression` 8 Elemente zurückgegeben werden. Die Gesamtgröße der übereinstimmenden Elemente beträgt: 2 000 Byte x 8 Elemente = 16 000 Byte. Das Ergebnis wird dann auf den nächsten 4-KB-Grenzwert aufgerundet. Da globale sekundäre Index-Abfragen Eventually Consistent ausgeführt werden, belaufen sich die Gesamtkosten auf 0,5  (16 KB/ 4 KB) oder 2 Lesekapazitätseinheiten.

### Schreibkapazitätseinheiten
<a name="GSI.ThroughputConsiderations.Writes"></a>

Wenn ein Element in einer Tabelle hinzugefügt, aktualisiert oder gelöscht wird und ein globaler sekundärer Index davon betroffen ist, dann belegt der globale sekundäre Index bereitgestellte Schreibkapazitätseinheiten für die Operation. Die Gesamtkosten für den bereitgestellten Durchsatz ergeben sich aus der Summe der Schreibkapazitätseinheiten, die durch Schreiben in die Basistabelle verbraucht wurden, und der durch Aktualisieren der globalen sekundären Indizes belegten Einheiten. Hinweis: Wenn ein Schreibvorgang in eine Tabelle keine globale sekundäre Index-Aktualisierung erfordert, wird keine Schreibkapazität vom Index verbraucht.

Damit ein Tabellenschreibvorgang erfolgreich ausgeführt wird, muss der für die Tabelle und alle zugehörigen globalen sekundären Indizes bereitgestellte Durchsatz genügend Kapazität aufweisen. Andernfalls wird der Schreibvorgang in die Tabelle gedrosselt. 

**Wichtig**  
Bei der Erstellung eines globalen sekundären Index (GSI) können Schreibvorgänge in die Basistabelle gedrosselt werden, wenn die GSI-Aktivität, die sich aus Schreibvorgängen in die Basistabelle ergibt, die bereitgestellte Schreibkapazität der GSI überschreitet. Diese Drosselung wirkt sich auf alle Schreibvorgänge aus, vom Indizierungsprozess bis hin zur möglichen Unterbrechung Ihrer Produktions-Workloads. Weitere Informationen finden Sie unter [Beheben von Drosselungsereignissen in Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TroubleshootingThrottling.html).

Die Kosten für das Schreiben eines Elements in einen globalen sekundären Index hängen von mehreren Faktoren ab:
+ Wenn Sie ein neues Element in die Tabelle schreiben, die ein indiziertes Attribut definiert, oder ein vorhandenes Element zum Definieren eines zuvor nicht definierten indizierten Attributs aktualisieren, ist ein Schreibvorgang erforderlich, um das Element in den Index einzufügen.
+ Wenn eine Aktualisierung der Tabelle den Wert eines indizierten Schlüsselattributs (von A in B) ändert, sind zwei Schreibvorgänge erforderlich, und zwar einer zum Löschen des vorherigen Elements aus dem Index und einer zum Schreiben des neuen Elements in den Index.  
+ Wenn ein Element im Index vorhanden war, ein Schreibvorgang in der Tabelle jedoch dazu führte, dass das indizierte Attribut gelöscht wurde, ist ein Schreibvorgang erforderlich, um die alte Elementprojektion im Index zu löschen.
+ Wenn ein Element nicht im Index vorhanden ist, bevor oder nachdem das Element aktualisiert wird, fallen keine zusätzlichen Kosten für das Schreiben in den Index an.
+ Wenn durch eine Aktualisierung der Tabelle nur der Wert von projizierten Attributen im Indexschlüsselschema, nicht aber der Wert von indizierten Schlüsselattributen geändert wird, ist ein Schreibvorgang erforderlich, um die Werte der projizierten Attribute im Index zu aktualisieren.

Alle diese Faktoren setzen voraus, dass die Größe der einzelnen Elemente im Index kleiner oder gleich der 1-KB- Elementgröße für das Berechnen der Schreibkapazitätseinheiten ist. Größere Indexeinträge erfordern zusätzliche Schreibkapazitätseinheiten. Sie können Ihre Kosten für Schreibvorgänge minimieren, indem Sie überlegen, welche Attribute Ihre Abfragen zurückgeben müssen, und nur diese Attribute in den Index projizieren.

## Speicherüberlegungen für globale sekundäre Indizes
<a name="GSI.StorageConsiderations"></a>

Wenn eine Anwendung ein Element in eine Tabelle schreibt, kopiert DynamoDB automatisch die richtige Teilmenge der Attribute in den globalen sekundären Index, in dem diese Attribute angezeigt werden sollen. Ihrem AWS Konto werden sowohl die Speicherung des Elements in der Basistabelle als auch die Speicherung von Attributen in allen globalen Sekundärindizes dieser Tabelle in Rechnung gestellt.

Der Speicherplatz, der von einem Indexelement belegt wird, ergibt sich aus der Summe von folgenden Werten:
+ Die Größe in Byte des Primärschlüssels der Basistabelle (Partitionsschlüssel und Sortierschlüssel)
+ Die Größe in Byte des Indexschlüsselattributs
+ Die Größe in Byte der projizierten Attribute (sofern vorhanden)
+ 100 Bytes des Overheads pro Indexelement

Zur Schätzung der Speicheranforderungen für einen globalen sekundären Index können Sie die durchschnittliche Größe eines Elements im Index schätzen und diesen Wert mit der Anzahl der Elemente in der Basistabelle multiplizieren, die die globalen sekundären Index-Schlüsselattribute besitzen.

Wenn eine Tabelle ein Element enthält, für das ein oder mehrere bestimmte Attribute nicht definiert sind, dieses Attribut jedoch als Indexpartitionsschlüssel oder Sortierschlüssel definiert ist, schreibt DynamoDB keine Daten für dieses Element in den Index.

# Muster entwerfen
<a name="GSI.DesignPatterns"></a>

Entwurfsmuster bieten bewährte Lösungen für häufig auftretende Herausforderungen bei der Arbeit mit globalen Sekundärindizes. Diese Muster helfen Ihnen bei der Entwicklung effizienter, skalierbarer Anwendungen, indem sie Ihnen zeigen, wie Sie Ihre Indizes für bestimmte Anwendungsfälle strukturieren.

Jedes Muster enthält einen vollständigen Implementierungsleitfaden mit Codebeispielen, bewährten Methoden und realen Anwendungsfällen, die Ihnen helfen, das Muster auf Ihre eigenen Anwendungen anzuwenden.

**Topics**
+ [Schlüssel mit mehreren Attributen](GSI.DesignPattern.MultiAttributeKeys.md)

# Schlüsselmuster mit mehreren Attributen
<a name="GSI.DesignPattern.MultiAttributeKeys"></a>

## Übersicht
<a name="GSI.DesignPattern.MultiAttributeKeys.Overview"></a>

Mit Schlüsseln mit mehreren Attributen können Sie eine GSI-Partition (Global Secondary Index) erstellen und Schlüssel sortieren, die jeweils aus bis zu vier Attributen bestehen. Dadurch wird der clientseitige Code reduziert und es ist einfacher, Daten zunächst zu modellieren und später neue Zugriffsmuster hinzuzufügen.

Stellen Sie sich ein gängiges Szenario vor: Um einen globalen Index zu erstellen, der Elemente anhand mehrerer hierarchischer Attribute abfragt, müssten Sie üblicherweise synthetische Schlüssel erstellen, indem Sie Werte verketten. Um beispielsweise in einer Gaming-App Turnierspiele nach Turnier, Region und Runde abzufragen, könnten Sie einen synthetischen GSI-Partitionsschlüssel wie TOURNAMENT\$1 WINTER2 024 \$1REGION \$1NA -EAST und einen synthetischen Sortierschlüssel wie ROUND \$1SEMIFINALS \$1BRACKET \$1UPPER erstellen. Dieser Ansatz funktioniert, erfordert jedoch die Verkettung von Zeichenketten beim Schreiben von Daten, das Parsen beim Lesen und das Auffüllen synthetischer Schlüssel für alle vorhandenen Elemente, wenn Sie den GSI zu einer vorhandenen Tabelle hinzufügen. Dadurch wird der Code unübersichtlicher und es ist schwierig, die Typsicherheit einzelner Schlüsselkomponenten aufrechtzuerhalten.

Schlüssel mit mehreren Attributen lösen dieses Problem für. GSIs Sie definieren Ihren GSI-Partitionsschlüssel mithilfe mehrerer vorhandener Attribute wie TournamentID und Region. DynamoDB verarbeitet die Logik der zusammengesetzten Schlüssel automatisch und hasht sie für die Datenverteilung zusammen. Sie schreiben Elemente mit natürlichen Attributen aus Ihrem Domänenmodell, und die GSI indexiert sie automatisch. Keine Verkettung, kein Parsen, kein Hinterfüllen. Ihr Code bleibt sauber, Ihre Daten bleiben eingegeben und Ihre Abfragen bleiben einfach. Dieser Ansatz ist besonders nützlich, wenn Sie über hierarchische Daten mit natürlichen Attributgruppierungen verfügen (wie Turnier → Region → Runde oder Organisation → Abteilung → Team).

## Beispiel für eine Anwendung
<a name="GSI.DesignPattern.MultiAttributeKeys.ApplicationExample"></a>

In diesem Leitfaden wird der Aufbau eines Systems zur Nachverfolgung von Turnierspielen für eine Esports-Plattform beschrieben. Die Plattform muss Spiele effizient über mehrere Dimensionen hinweg abfragen können: nach Turnier und Region für die Gruppenverwaltung, nach Spielern für den Spielverlauf und nach Datum für die Planung.

## Datenmodell
<a name="GSI.DesignPattern.MultiAttributeKeys.DataModel"></a>

In dieser exemplarischen Vorgehensweise unterstützt das System zur Nachverfolgung von Turnierspielen drei primäre Zugriffsmuster, für die jeweils eine andere Schlüsselstruktur erforderlich ist:

**Zugriffsmuster 1:** Suchen Sie ein bestimmtes Spiel anhand seiner eindeutigen ID
+ **Lösung:** Basistabelle mit einem `matchId` Partitionsschlüssel

**Zugriffsmuster 2:** Alle Spiele für ein bestimmtes Turnier und eine bestimmte Region abfragen und optional nach Runde, Bracket oder Spiel filtern
+ **Lösung:** Globaler sekundärer Index mit Partitionsschlüssel (`tournamentId`\$1`region`) mit mehreren Attributen und Sortierschlüssel mit mehreren Attributen (`round`\$1 \$1`bracket`) `matchId`
+ **Beispielabfragen:** „Alle WINTER2 024 Spiele in der Region NA-OST“ oder „Alle HALBFINALSPIELE in OBERER Klammer für 024/NA-EAST“ WINTER2

**Zugriffsmuster 3:** Fragen Sie den Spielverlauf eines Spielers ab und filtern Sie optional nach Zeitraum oder Turnierrunde
+ **Lösung:** Globaler sekundärer Index mit einem einzigen Partitionsschlüssel (`player1Id`) und einem Sortierschlüssel mit mehreren Attributen (`matchDate`\$1`round`)
+ **Beispielabfragen:** „Alle Spiele für Spieler 101“ oder „Spiele von Spieler 101 im Januar 2024“

Der entscheidende Unterschied zwischen traditionellen Ansätzen und Methoden mit mehreren Attributen wird deutlich, wenn man sich die Artikelstruktur ansieht:

**Traditioneller Ansatz für globale Sekundärindizes (verkettete Schlüssel):**

```
// Manual concatenation required for GSI keys
const item = {
    matchId: 'match-001',                                          // Base table PK
    tournamentId: 'WINTER2024',
    region: 'NA-EAST',
    round: 'SEMIFINALS',
    bracket: 'UPPER',
    player1Id: '101',
    // Synthetic keys needed for GSI
    GSI_PK: `TOURNAMENT#${tournamentId}#REGION#${region}`,       // Must concatenate
    GSI_SK: `${round}#${bracket}#${matchId}`,                    // Must concatenate
    // ... other attributes
};
```

**Globaler Sekundärindex-Ansatz mit mehreren Attributen (systemeigene Schlüssel):**

```
// Use existing attributes directly - no concatenation needed
const item = {
    matchId: 'match-001',                                          // Base table PK
    tournamentId: 'WINTER2024',
    region: 'NA-EAST',
    round: 'SEMIFINALS',
    bracket: 'UPPER',
    player1Id: '101',
    matchDate: '2024-01-18',
    // No synthetic keys needed - GSI uses existing attributes directly
    // ... other attributes
};
```

Bei Schlüsseln mit mehreren Attributen schreiben Sie Elemente einmal mit natürlichen Domänenattributen. DynamoDB indexiert sie automatisch über mehrere, GSIs ohne dass synthetische verkettete Schlüssel erforderlich sind.

**Schema der Basistabelle:**
+ Partitionsschlüssel: `matchId` (1 Attribut)

**Globales sekundäres Indexschema (TournamentRegionIndex mit Schlüsseln mit mehreren Attributen):**
+ Partitionsschlüssel:`tournamentId`, `region` (2 Attribute)
+ Sortierschlüssel:`round`,`bracket`, `matchId` (3 Attribute)

**Globales sekundäres Indexschema (PlayerMatchHistoryIndex mit Schlüsseln mit mehreren Attributen):**
+ Partitionsschlüssel: `player1Id` (1 Attribut)
+ Sortierschlüssel:`matchDate`, `round` (2 Attribute)

### Basistabelle: TournamentMatches
<a name="GSI.DesignPattern.MultiAttributeKeys.BaseTable"></a>


| MatchID (PK) | Turnier-ID | Region | round | Halterung | Spieler1-ID | Spieler2-ID | Datum des Spiels | Gewinner | Bewertung | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| Match-001 | WINTER2024 | IM OSTEN | ENDSPIELE | MEISTERSCHAFT | 101 | 103 | 20.01.2024-01 | 101 | 3-1 | 
| Spiel-002 | WINTER2024 | IM OSTEN | HALBFINALE | UPPER | 101 | 105 | 2024-01-18 | 101 | 3-2 | 
| Spiel-003 | WINTER2024 | IM OSTEN | HALBFINALE | UPPER | 103 | 107 | 2024-01-18 | 103 | 3-0 | 
| Spiel-004 | WINTER2024 | IM OSTEN | VIERTELFINALE | UPPER | 101 | 109 | 2024-01-15 | 101 | 3-1 | 
| Spiel-005 | WINTER2024 | IM WESTEN | ENDSPIELE | MEISTERSCHAFT | 102 | 104 | 20.01.2024-01 | 102 | 3-2 | 
| Spiel-006 | WINTER2024 | IM WESTEN | HALBFINALE | UPPER | 102 | 106 | 2024-01-18 | 102 | 3-1 | 
| Spiel 007 | SPRING2024 | IM OSTEN | VIERTELFINALE | UPPER | 101 | 108 | 2024-03-15 | 101 | 3-0 | 
| Spiel-008 | SPRING2024 | IM OSTEN | VIERTELFINALE | LOWER | 103 | 110 | 2024-03-15 | 103 | 3-2 | 

### GSI: TournamentRegionIndex (Schlüssel mit mehreren Attributen)
<a name="GSI.DesignPattern.MultiAttributeKeys.TournamentRegionIndexTable"></a>


| Turnier-ID (PK) | Region (PK) | rund (SK) | Klammer (SK) | Spiel-ID (SK) | Spieler1-ID | Spieler2-ID | Datum des Spiels | Gewinner | Bewertung | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| WINTER2024 | IM OSTEN | ENDSPIELE | MEISTERSCHAFT | Spiel-001 | 101 | 103 | 20.01.2024 | 101 | 3-1 | 
| WINTER2024 | IM OSTEN | VIERTELFINALE | UPPER | Spiel-004 | 101 | 109 | 15.01.2024 | 101 | 3-1 | 
| WINTER2024 | IM OSTEN | HALBFINALE | UPPER | Spiel-002 | 101 | 105 | 18.01.2024 | 101 | 3-2 | 
| WINTER2024 | IM OSTEN | HALBFINALE | UPPER | Spiel-003 | 103 | 107 | 18.01.2024 | 103 | 3-0 | 
| WINTER2024 | IM WESTEN | ENDSPIELE | MEISTERSCHAFT | Spiel-005 | 102 | 104 | 20.01.2024 | 102 | 3-2 | 
| WINTER2024 | IM WESTEN | HALBFINALE | UPPER | Spiel-006 | 102 | 106 | 18.01.2024 | 102 | 3-1 | 
| SPRING2024 | IM OSTEN | VIERTELFINALE | LOWER | Spiel-008 | 103 | 110 | 15.03.2024 | 103 | 3-2 | 
| SPRING2024 | IM OSTEN | VIERTELFINALE | UPPER | Spiel-007 | 101 | 108 | 15.03.2024 | 101 | 3-0 | 

### GSI: PlayerMatchHistoryIndex (Schlüssel mit mehreren Attributen)
<a name="GSI.DesignPattern.MultiAttributeKeys.PlayerMatchHistoryIndexTable"></a>


| Spieler1-ID (PK) | Spieldatum (SK) | Runde (SK) | ID des Turniers | Region | Halterung | ID abgleichen | Spieler2-ID | Gewinner | Bewertung | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 101 | 2024-01-15 | VIERTELFINALE | WINTER2024 | IM OSTEN | UPPER | Spiel-004 | 109 | 101 | 3-1 | 
| 101 | 18.01.2024 | HALBFINALE | WINTER2024 | IM OSTEN | UPPER | Spiel-002 | 105 | 101 | 3-2 | 
| 101 | 20.01.2024 | ENDSPIELE | WINTER2024 | IM OSTEN | MEISTERSCHAFT | Spiel-001 | 103 | 101 | 3-1 | 
| 101 | 15.03.2024 | VIERTELFINALE | SPRING2024 | IM OSTEN | UPPER | Spiel 007 | 108 | 101 | 3-0 | 
| 102 | 18.01.2024 | HALBFINALE | WINTER2024 | IM WESTEN | UPPER | Spiel-006 | 106 | 102 | 3-1 | 
| 102 | 20.01.2024 | ENDSPIELE | WINTER2024 | IM WESTEN | MEISTERSCHAFT | Spiel-005 | 104 | 102 | 3-2 | 
| 103 | 18.01.2024 | HALBFINALE | WINTER2024 | IM OSTEN | UPPER | Spiel-003 | 107 | 103 | 3-0 | 
| 103 | 2024-03-15 | VIERTELFINALE | SPRING2024 | IM OSTEN | LOWER | Spiel-008 | 110 | 103 | 3-2 | 

## Voraussetzungen
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites"></a>

Stellen Sie vor Beginn sicher, dass Sie über Folgendes verfügen:

### Konto und Berechtigungen
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.AWSAccount"></a>
+ Ein aktives AWS Konto ([erstellen Sie hier bei Bedarf eines](https://aws.amazon.com/free/))
+ IAM-Berechtigungen für DynamoDB-Operationen:
  + `dynamodb:CreateTable`
  + `dynamodb:DeleteTable`
  + `dynamodb:DescribeTable`
  + `dynamodb:PutItem`
  + `dynamodb:Query`
  + `dynamodb:BatchWriteItem`

**Anmerkung**  
**Sicherheitshinweis:** Erstellen Sie für Produktionszwecke eine benutzerdefinierte IAM-Richtlinie mit nur den Berechtigungen, die Sie benötigen. Für dieses Tutorial können Sie die AWS verwaltete Richtlinie `AmazonDynamoDBFullAccessV2` verwenden.

### Entwicklungsumgebung
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.DevEnvironment"></a>
+ Node.js ist auf Ihrem Computer installiert
+ AWS Anmeldeinformationen, die mit einer der folgenden Methoden konfiguriert wurden:

**Option 1: AWS CLI**

```
aws configure
```

**Option 2: Umgebungsvariablen**

```
export AWS_ACCESS_KEY_ID=your_access_key_here
export AWS_SECRET_ACCESS_KEY=your_secret_key_here
export AWS_DEFAULT_REGION=us-east-1
```

### Installieren erforderlicher Pakete
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.InstallPackages"></a>

```
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
```

## Implementierung
<a name="GSI.DesignPattern.MultiAttributeKeys.Implementation"></a>

### Schritt 1: Erstellen Sie eine Tabelle mit Schlüsseln GSIs mit mehreren Attributen
<a name="GSI.DesignPattern.MultiAttributeKeys.CreateTable"></a>

Erstellen Sie eine Tabelle mit einer einfachen Basisschlüsselstruktur GSIs , die Schlüssel mit mehreren Attributen verwendet.

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11b3b5b1"></a>

```
import { DynamoDBClient, CreateTableCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });

const response = await client.send(new CreateTableCommand({
    TableName: 'TournamentMatches',
    
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'matchId', KeyType: 'HASH' }              // Simple PK
    ],
    
    AttributeDefinitions: [
        { AttributeName: 'matchId', AttributeType: 'S' },
        { AttributeName: 'tournamentId', AttributeType: 'S' },
        { AttributeName: 'region', AttributeType: 'S' },
        { AttributeName: 'round', AttributeType: 'S' },
        { AttributeName: 'bracket', AttributeType: 'S' },
        { AttributeName: 'player1Id', AttributeType: 'S' },
        { AttributeName: 'matchDate', AttributeType: 'S' }
    ],
    
    // GSIs with multi-attribute keys
    GlobalSecondaryIndexes: [
        {
            IndexName: 'TournamentRegionIndex',
            KeySchema: [
                { AttributeName: 'tournamentId', KeyType: 'HASH' },    // GSI PK attribute 1
                { AttributeName: 'region', KeyType: 'HASH' },          // GSI PK attribute 2
                { AttributeName: 'round', KeyType: 'RANGE' },          // GSI SK attribute 1
                { AttributeName: 'bracket', KeyType: 'RANGE' },        // GSI SK attribute 2
                { AttributeName: 'matchId', KeyType: 'RANGE' }         // GSI SK attribute 3
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'PlayerMatchHistoryIndex',
            KeySchema: [
                { AttributeName: 'player1Id', KeyType: 'HASH' },       // GSI PK
                { AttributeName: 'matchDate', KeyType: 'RANGE' },      // GSI SK attribute 1
                { AttributeName: 'round', KeyType: 'RANGE' }           // GSI SK attribute 2
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    
    BillingMode: 'PAY_PER_REQUEST'
}));

console.log("Table with multi-attribute GSI keys created successfully");
```

**Wichtige Designentscheidungen:**

**Basistabelle:** Die Basistabelle verwendet einen einfachen `matchId` Partitionsschlüssel für direkte Suchabfragen, wodurch die Struktur der Basistabelle übersichtlich bleibt und gleichzeitig die komplexen Abfragemuster GSIs bereitgestellt werden.

**TournamentRegionIndex Globaler Sekundärindex:** Der `TournamentRegionIndex` globale Sekundärindex verwendet `tournamentId` \$1 `region` als Partitionsschlüssel mit mehreren Attributen, wodurch eine Isolierung der Turnierregion erreicht wird, bei der die Daten durch den Hash beider Attribute zusammen verteilt werden, was effiziente Abfragen innerhalb eines bestimmten Turnierregionskontextes ermöglicht. Der Sortierschlüssel mit mehreren Attributen (`round`\$1 `bracket` \$1`matchId`) ermöglicht eine hierarchische Sortierung, die Abfragen auf jeder Hierarchieebene mit natürlicher Reihenfolge von allgemein (rund) bis spezifisch (Match-ID) unterstützt.

**PlayerMatchHistoryIndex Globaler Sekundärindex:** Der `PlayerMatchHistoryIndex` globale sekundäre Index reorganisiert Daten nach Spielern, die `player1Id` als Partitionsschlüssel verwendet werden, und ermöglicht so turnierübergreifende Abfragen für einen bestimmten Spieler. Der Sortierschlüssel mit mehreren Attributen (`matchDate`\$1`round`) bietet eine chronologische Reihenfolge mit der Möglichkeit, nach Datumsbereichen oder bestimmten Turnierrunden zu filtern.

### Schritt 2: Fügen Sie Daten mit systemeigenen Attributen ein
<a name="GSI.DesignPattern.MultiAttributeKeys.InsertData"></a>

Fügen Sie Turnierspieldaten mit natürlichen Attributen hinzu. Die GSI indexiert diese Attribute automatisch, ohne dass synthetische Schlüssel erforderlich sind.

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11b5b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Tournament match data - no synthetic keys needed for GSIs
const matches = [
    // Winter 2024 Tournament, NA-EAST region
    {
        matchId: 'match-001',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'FINALS',
        bracket: 'CHAMPIONSHIP',
        player1Id: '101',
        player2Id: '103',
        matchDate: '2024-01-20',
        winner: '101',
        score: '3-1'
    },
    {
        matchId: 'match-002',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '105',
        matchDate: '2024-01-18',
        winner: '101',
        score: '3-2'
    },
    {
        matchId: 'match-003',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '103',
        player2Id: '107',
        matchDate: '2024-01-18',
        winner: '103',
        score: '3-0'
    },
    {
        matchId: 'match-004',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '109',
        matchDate: '2024-01-15',
        winner: '101',
        score: '3-1'
    },
    
    // Winter 2024 Tournament, NA-WEST region
    {
        matchId: 'match-005',
        tournamentId: 'WINTER2024',
        region: 'NA-WEST',
        round: 'FINALS',
        bracket: 'CHAMPIONSHIP',
        player1Id: '102',
        player2Id: '104',
        matchDate: '2024-01-20',
        winner: '102',
        score: '3-2'
    },
    {
        matchId: 'match-006',
        tournamentId: 'WINTER2024',
        region: 'NA-WEST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '102',
        player2Id: '106',
        matchDate: '2024-01-18',
        winner: '102',
        score: '3-1'
    },
    
    // Spring 2024 Tournament, NA-EAST region
    {
        matchId: 'match-007',
        tournamentId: 'SPRING2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '108',
        matchDate: '2024-03-15',
        winner: '101',
        score: '3-0'
    },
    {
        matchId: 'match-008',
        tournamentId: 'SPRING2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'LOWER',
        player1Id: '103',
        player2Id: '110',
        matchDate: '2024-03-15',
        winner: '103',
        score: '3-2'
    }
];

// Insert all matches
for (const match of matches) {
    await docClient.send(new PutCommand({
        TableName: 'TournamentMatches',
        Item: match
    }));
    
    console.log(`Added: ${match.matchId} - ${match.tournamentId}/${match.region} - ${match.round} ${match.bracket}`);
}

console.log(`\nInserted ${matches.length} tournament matches`);
console.log("No synthetic keys created - GSIs use native attributes automatically");
```

**Datenstruktur erklärt:**

**Natürliche Verwendung von Attributen:** Jedes Attribut steht für ein echtes Turnierkonzept, bei dem keine Verkettung oder Analyse von Zeichenketten erforderlich ist, sodass eine direkte Zuordnung zum Domänenmodell möglich ist.

**Automatische Indizierung des globalen sekundären Indexes:** Die Indexierung von Elementen GSIs erfolgt automatisch unter Verwendung der vorhandenen Attribute (`tournamentId`,,,`region`, `matchId` für TournamentRegionIndex und `round``bracket`, `round` für PlayerMatchHistoryIndex), ohne dass `player1Id` synthetische `matchDate` verkettete Schlüssel erforderlich sind.

**Kein Backfilling erforderlich:** Wenn Sie einer vorhandenen Tabelle einen neuen globalen sekundären Index mit Schlüsseln mit mehreren Attributen hinzufügen, indexiert DynamoDB automatisch alle vorhandenen Elemente anhand ihrer natürlichen Attribute — es ist nicht erforderlich, Elemente mit synthetischen Schlüsseln zu aktualisieren.

### Schritt 3: Fragen Sie den globalen sekundären Index mit allen Partitionsschlüsselattributen ab TournamentRegionIndex
<a name="GSI.DesignPattern.MultiAttributeKeys.QueryAllPartitionKeys"></a>

In diesem Beispiel wird der TournamentRegionIndex globale sekundäre Index abgefragt, der über einen Partitionsschlüssel mit mehreren Attributen (`tournamentId`\$1`region`) verfügt. Alle Partitionsschlüsselattribute müssen in Abfragen mit Gleichheitsbedingungen angegeben werden. Es ist nicht möglich, Abfragen nur `tournamentId` allein oder Ungleichheitsoperatoren für Partitionsschlüsselattribute zu verwenden.

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11b7b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query GSI: All matches for WINTER2024 tournament in NA-EAST region
const response = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region',
    ExpressionAttributeNames: {
        '#region': 'region',  // 'region' is a reserved keyword
        '#tournament': 'tournament'
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST'
    }
}));

console.log(`Found ${response.Items.length} matches for WINTER2024/NA-EAST:\n`);
response.Items.forEach(match => {
    console.log(`  ${match.round} | ${match.bracket} | ${match.matchId}`);
    console.log(`    Players: ${match.player1Id} vs ${match.player2Id}`);
    console.log(`    Winner: ${match.winner}, Score: ${match.score}\n`);
});
```

**Erwartete Ausgabe:**

```
Found 4 matches for WINTER2024/NA-EAST:

  FINALS | CHAMPIONSHIP | match-001
    Players: 101 vs 103
    Winner: 101, Score: 3-1

  QUARTERFINALS | UPPER | match-004
    Players: 101 vs 109
    Winner: 101, Score: 3-1

  SEMIFINALS | UPPER | match-002
    Players: 101 vs 105
    Winner: 101, Score: 3-2

  SEMIFINALS | UPPER | match-003
    Players: 103 vs 107
    Winner: 103, Score: 3-0
```

**Ungültige Abfragen:**

```
// Missing region attribute
KeyConditionExpression: 'tournamentId = :tournament'

// Using inequality on partition key attribute
KeyConditionExpression: 'tournamentId = :tournament AND #region > :region'
```

**Leistung:** Partitionsschlüssel mit mehreren Attributen werden zusammen gehasht und bieten so dieselbe O (1) -Suchleistung wie Schlüssel mit einem Attribut.

### Schritt 4: Sortierschlüssel für den globalen sekundären Index abfragen left-to-right
<a name="GSI.DesignPattern.MultiAttributeKeys.QuerySortKeysLeftToRight"></a>

Sortierschlüsselattribute müssen left-to-right in der Reihenfolge abgefragt werden, in der sie im globalen sekundären Index definiert sind. Dieses Beispiel zeigt die Abfrage von TournamentRegionIndex auf verschiedenen Hierarchieebenen: das Filtern nur nach`round`, nach `round` \$1 `bracket` oder nach allen drei Sortierschlüsselattributen. Sie können keine Attribute in der Mitte überspringen. Sie können beispielsweise keine Abfragen nach und nach `round` dem Überspringen durchführen. `matchId` `bracket`

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11b9b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: Filter by first sort key attribute (round)
console.log("Query 1: All SEMIFINALS matches");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS'
    }
}));
console.log(`  Found ${query1.Items.length} matches\n`);

// Query 2: Filter by first two sort key attributes (round + bracket)
console.log("Query 2: SEMIFINALS UPPER bracket matches");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND bracket = :bracket',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':bracket': 'UPPER'
    }
}));
console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Filter by all three sort key attributes (round + bracket + matchId)
console.log("Query 3: Specific match in SEMIFINALS UPPER bracket");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND bracket = :bracket AND matchId = :matchId',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':bracket': 'UPPER',
        ':matchId': 'match-002'
    }
}));
console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: INVALID - skipping round
console.log("Query 4: Attempting to skip first sort key attribute (WILL FAIL)");
try {
    const query4 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND bracket = :bracket',
        ExpressionAttributeNames: {
            '#region': 'region'  // 'region' is a reserved keyword
        },
        ExpressionAttributeValues: {
            ':tournament': 'WINTER2024',
            ':region': 'NA-EAST',
            ':bracket': 'UPPER'
        }
    }));
} catch (error) {
    console.log(`  Error: ${error.message}`);
    console.log(`  Cannot skip sort key attributes - must query left-to-right\n`);
}
```

**Erwartete Ausgabe:**

```
Query 1: All SEMIFINALS matches
  Found 2 matches

Query 2: SEMIFINALS UPPER bracket matches
  Found 2 matches

Query 3: Specific match in SEMIFINALS UPPER bracket
  Found 1 matches

Query 4: Attempting to skip first sort key attribute (WILL FAIL)
  Error: Query key condition not supported
  Cannot skip sort key attributes - must query left-to-right
```

**Left-to-right Abfrageregeln:** Sie müssen Attribute in der Reihenfolge von links nach rechts abfragen, ohne irgendwelche zu überspringen.

**Gültige Muster:**
+ Nur erstes Attribut: `round = 'SEMIFINALS'`
+ Die ersten beiden Attribute: `round = 'SEMIFINALS' AND bracket = 'UPPER'`
+ Alle drei Attribute: `round = 'SEMIFINALS' AND bracket = 'UPPER' AND matchId = 'match-002'`

**Ungültige Muster:**
+ Das erste Attribut wird übersprungen: `bracket = 'UPPER'` (überspringt die Runde)
+ Die Abfrage ist nicht in der richtigen Reihenfolge: `matchId = 'match-002' AND round = 'SEMIFINALS'`
+ Lücken hinterlassen: `round = 'SEMIFINALS' AND matchId = 'match-002'` (überspringt die Klammer)

**Anmerkung**  
**Design-Tipp:** Sortieren Sie die Schlüsselattribute von den allgemeinsten bis hin zu den spezifischsten, um die Flexibilität bei der Abfrage zu maximieren.

### Schritt 5: Verwenden Sie Ungleichheitsbedingungen für Sortierschlüssel im globalen sekundären Index
<a name="GSI.DesignPattern.MultiAttributeKeys.InequalityConditions"></a>

Ungleichheitsbedingungen müssen die letzte Bedingung in Ihrer Abfrage sein. Dieses Beispiel zeigt die Verwendung von Vergleichsoperatoren (`>=`,`BETWEEN`) und Präfixabgleich (`begins_with()`) für Sortierschlüsselattribute. Sobald Sie einen Ungleichheitsoperator verwendet haben, können Sie danach keine weiteren Sortierschlüsselbedingungen hinzufügen — die Ungleichheit muss die letzte Bedingung in Ihrem Schlüsselbedingungsausdruck sein.

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11c11b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: Round comparison (inequality on first sort key attribute)
console.log("Query 1: Matches from QUARTERFINALS onwards");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round >= :round',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'QUARTERFINALS'
    }
}));
console.log(`  Found ${query1.Items.length} matches\n`);

// Query 2: Round range with BETWEEN
console.log("Query 2: Matches between QUARTERFINALS and SEMIFINALS");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round BETWEEN :start AND :end',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':start': 'QUARTERFINALS',
        ':end': 'SEMIFINALS'
    }
}));
console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Prefix matching with begins_with (treated as inequality)
console.log("Query 3: Matches in brackets starting with 'U'");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND begins_with(bracket, :prefix)',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':prefix': 'U'
    }
}));
console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: INVALID - condition after inequality
console.log("Query 4: Attempting condition after inequality (WILL FAIL)");
try {
    const query4 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round > :round AND bracket = :bracket',
        ExpressionAttributeNames: {
            '#region': 'region'  // 'region' is a reserved keyword
        },
        ExpressionAttributeValues: {
            ':tournament': 'WINTER2024',
            ':region': 'NA-EAST',
            ':round': 'QUARTERFINALS',
            ':bracket': 'UPPER'
        }
    }));
} catch (error) {
    console.log(`  Error: ${error.message}`);
    console.log(`  Cannot add conditions after inequality - it must be last\n`);
}
```

**Regeln für Ungleichheitsoperatoren:** Sie können Vergleichsoperatoren (`>`, `>=``<`,`<=`) `BETWEEN` für Bereichsabfragen und `begins_with()` für den Präfixabgleich verwenden. Die Ungleichheit muss die letzte Bedingung in Ihrer Abfrage sein.

**Gültige Muster:**
+ Gleichheitsbedingungen, gefolgt von Ungleichheit: `round = 'SEMIFINALS' AND bracket = 'UPPER' AND matchId > 'match-001'`
+ Ungleichheit beim ersten Merkmal: `round BETWEEN 'QUARTERFINALS' AND 'SEMIFINALS'`
+ Präfixübereinstimmung als letzte Bedingung: `round = 'SEMIFINALS' AND begins_with(bracket, 'U')`

**Ungültige Muster:**
+ Hinzufügen von Bedingungen nach einer Ungleichung: `round > 'QUARTERFINALS' AND bracket = 'UPPER'`
+ Verwendung mehrerer Ungleichungen: `round > 'QUARTERFINALS' AND bracket > 'L'`

**Wichtig**  
`begins_with()`wird als Ungleichheitsbedingung behandelt, sodass ihr keine weiteren Sortierschlüsselbedingungen folgen können.

### Schritt 6: Fragen Sie den PlayerMatchHistoryIndex globalen sekundären Index mit einem Sortierschlüssel mit mehreren Attributen ab
<a name="GSI.DesignPattern.MultiAttributeKeys.QueryPlayerHistory"></a>

In diesem Beispiel wird abgefragt PlayerMatchHistoryIndex , welcher einen einzelnen Partitionsschlüssel (`player1Id`) und einen Sortierschlüssel mit mehreren Attributen (`matchDate`\$1`round`) hat. Dies ermöglicht eine turnierübergreifende Analyse, indem alle Spiele eines bestimmten Spielers abgefragt werden, ohne das Turnier IDs zu kennen. In der Basistabelle wären für jede Kombination aus Turnier und Region separate Abfragen erforderlich.

#### Codebeispiel
<a name="w2aac19c13c45c23b9c11c13b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: All matches for Player 101 across all tournaments
console.log("Query 1: All matches for Player 101");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player',
    ExpressionAttributeValues: {
        ':player': '101'
    }
}));

console.log(`  Found ${query1.Items.length} matches for Player 101:`);
query1.Items.forEach(match => {
    console.log(`    ${match.tournamentId}/${match.region} - ${match.matchDate} - ${match.round}`);
});
console.log();

// Query 2: Player 101 matches on specific date
console.log("Query 2: Player 101 matches on 2024-01-18");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate = :date',
    ExpressionAttributeValues: {
        ':player': '101',
        ':date': '2024-01-18'
    }
}));

console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Player 101 SEMIFINALS matches on specific date
console.log("Query 3: Player 101 SEMIFINALS matches on 2024-01-18");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate = :date AND round = :round',
    ExpressionAttributeValues: {
        ':player': '101',
        ':date': '2024-01-18',
        ':round': 'SEMIFINALS'
    }
}));

console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: Player 101 matches in date range
console.log("Query 4: Player 101 matches in January 2024");
const query4 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate BETWEEN :start AND :end',
    ExpressionAttributeValues: {
        ':player': '101',
        ':start': '2024-01-01',
        ':end': '2024-01-31'
    }
}));

console.log(`  Found ${query4.Items.length} matches\n`);
```

## Variationen des Musters
<a name="GSI.DesignPattern.MultiAttributeKeys.PatternVariations"></a>

### Zeitreihendaten mit Schlüsseln mit mehreren Attributen
<a name="GSI.DesignPattern.MultiAttributeKeys.TimeSeries"></a>

Optimieren Sie für Zeitreihenabfragen mit hierarchischen Zeitattributen

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13b3b5b1"></a>

```
{
    TableName: 'IoTReadings',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'readingId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'readingId', AttributeType: 'S' },
        { AttributeName: 'deviceId', AttributeType: 'S' },
        { AttributeName: 'locationId', AttributeType: 'S' },
        { AttributeName: 'year', AttributeType: 'S' },
        { AttributeName: 'month', AttributeType: 'S' },
        { AttributeName: 'day', AttributeType: 'S' },
        { AttributeName: 'timestamp', AttributeType: 'S' }
    ],
    // GSI with multi-attribute keys for time-series queries
    GlobalSecondaryIndexes: [{
        IndexName: 'DeviceLocationTimeIndex',
        KeySchema: [
            { AttributeName: 'deviceId', KeyType: 'HASH' },
            { AttributeName: 'locationId', KeyType: 'HASH' },
            { AttributeName: 'year', KeyType: 'RANGE' },
            { AttributeName: 'month', KeyType: 'RANGE' },
            { AttributeName: 'day', KeyType: 'RANGE' },
            { AttributeName: 'timestamp', KeyType: 'RANGE' }
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query patterns enabled via GSI:
// - All readings for device in location
// - Readings for specific year
// - Readings for specific month in year
// - Readings for specific day
// - Readings in time range
```

**Vorteile: Die** natürliche Zeithierarchie (Jahr → Monat → Tag → Zeitstempel) ermöglicht effiziente Abfragen mit beliebiger Granularität, ohne dass das Datum analysiert oder manipuliert werden muss. Der globale Sekundärindex indexiert automatisch alle Messwerte anhand ihrer natürlichen Zeitattribute.

### E-Commerce-Bestellungen mit Schlüsseln mit mehreren Attributen
<a name="GSI.DesignPattern.MultiAttributeKeys.ECommerce"></a>

Verfolgen Sie Bestellungen mit mehreren Dimensionen

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13b5b5b1"></a>

```
{
    TableName: 'Orders',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'orderId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'orderId', AttributeType: 'S' },
        { AttributeName: 'sellerId', AttributeType: 'S' },
        { AttributeName: 'region', AttributeType: 'S' },
        { AttributeName: 'orderDate', AttributeType: 'S' },
        { AttributeName: 'category', AttributeType: 'S' },
        { AttributeName: 'customerId', AttributeType: 'S' },
        { AttributeName: 'orderStatus', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'SellerRegionIndex',
            KeySchema: [
                { AttributeName: 'sellerId', KeyType: 'HASH' },
                { AttributeName: 'region', KeyType: 'HASH' },
                { AttributeName: 'orderDate', KeyType: 'RANGE' },
                { AttributeName: 'category', KeyType: 'RANGE' },
                { AttributeName: 'orderId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'CustomerOrdersIndex',
            KeySchema: [
                { AttributeName: 'customerId', KeyType: 'HASH' },
                { AttributeName: 'orderDate', KeyType: 'RANGE' },
                { AttributeName: 'orderStatus', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// SellerRegionIndex GSI queries:
// - Orders by seller and region
// - Orders by seller, region, and date
// - Orders by seller, region, date, and category

// CustomerOrdersIndex GSI queries:
// - Customer's orders
// - Customer's orders by date
// - Customer's orders by date and status
```

### Hierarchische Organisationsdaten
<a name="GSI.DesignPattern.MultiAttributeKeys.Hierarchical"></a>

Modellieren Sie Organisationshierarchien

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13b7b5b1"></a>

```
{
    TableName: 'Employees',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'employeeId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'employeeId', AttributeType: 'S' },
        { AttributeName: 'companyId', AttributeType: 'S' },
        { AttributeName: 'divisionId', AttributeType: 'S' },
        { AttributeName: 'departmentId', AttributeType: 'S' },
        { AttributeName: 'teamId', AttributeType: 'S' },
        { AttributeName: 'skillCategory', AttributeType: 'S' },
        { AttributeName: 'skillLevel', AttributeType: 'S' },
        { AttributeName: 'yearsExperience', AttributeType: 'N' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'OrganizationIndex',
            KeySchema: [
                { AttributeName: 'companyId', KeyType: 'HASH' },
                { AttributeName: 'divisionId', KeyType: 'HASH' },
                { AttributeName: 'departmentId', KeyType: 'RANGE' },
                { AttributeName: 'teamId', KeyType: 'RANGE' },
                { AttributeName: 'employeeId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'SkillsIndex',
            KeySchema: [
                { AttributeName: 'skillCategory', KeyType: 'HASH' },
                { AttributeName: 'skillLevel', KeyType: 'RANGE' },
                { AttributeName: 'yearsExperience', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'INCLUDE', NonKeyAttributes: ['employeeId', 'name'] }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// OrganizationIndex GSI query patterns:
// - All employees in company/division
// - Employees in specific department
// - Employees in specific team

// SkillsIndex GSI query patterns:
// - Employees by skill and experience level
```

### Wenige Schlüssel mit mehreren Attributen
<a name="GSI.DesignPattern.MultiAttributeKeys.Sparse"></a>

Kombinieren Sie Schlüssel mit mehreren Attributen, um einen globalen Index mit geringer Dichte zu erstellen

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13b9b5b1"></a>

```
{
    TableName: 'Products',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'productId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'productId', AttributeType: 'S' },
        { AttributeName: 'categoryId', AttributeType: 'S' },
        { AttributeName: 'subcategoryId', AttributeType: 'S' },
        { AttributeName: 'averageRating', AttributeType: 'N' },
        { AttributeName: 'reviewCount', AttributeType: 'N' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'CategoryIndex',
            KeySchema: [
                { AttributeName: 'categoryId', KeyType: 'HASH' },
                { AttributeName: 'subcategoryId', KeyType: 'HASH' },
                { AttributeName: 'productId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'ReviewedProductsIndex',
            KeySchema: [
                { AttributeName: 'categoryId', KeyType: 'HASH' },
                { AttributeName: 'averageRating', KeyType: 'RANGE' },  // Optional attribute
                { AttributeName: 'reviewCount', KeyType: 'RANGE' }     // Optional attribute
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// Only products with reviews appear in ReviewedProductsIndex GSI
// Automatic filtering without application logic
// Multi-attribute sort key enables rating and count queries
```

### SaaS für mehrere Mandanten
<a name="GSI.DesignPattern.MultiAttributeKeys.SaaS"></a>

Mehrinstanzenfähige SaaS-Plattform mit Kundenisolierung

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13c11b5b1"></a>

```
// Table design
{
    TableName: 'SaasData',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'resourceId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'resourceId', AttributeType: 'S' },
        { AttributeName: 'tenantId', AttributeType: 'S' },
        { AttributeName: 'customerId', AttributeType: 'S' },
        { AttributeName: 'resourceType', AttributeType: 'S' }
    ],
    // GSI with multi-attribute keys for tenant-customer isolation
    GlobalSecondaryIndexes: [{
        IndexName: 'TenantCustomerIndex',
        KeySchema: [
            { AttributeName: 'tenantId', KeyType: 'HASH' },
            { AttributeName: 'customerId', KeyType: 'HASH' },
            { AttributeName: 'resourceType', KeyType: 'RANGE' },
            { AttributeName: 'resourceId', KeyType: 'RANGE' }
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query GSI: All resources for tenant T001, customer C001
const resources = await docClient.send(new QueryCommand({
    TableName: 'SaasData',
    IndexName: 'TenantCustomerIndex',
    KeyConditionExpression: 'tenantId = :tenant AND customerId = :customer',
    ExpressionAttributeValues: {
        ':tenant': 'T001',
        ':customer': 'C001'
    }
}));

// Query GSI: Specific resource type for tenant/customer
const documents = await docClient.send(new QueryCommand({
    TableName: 'SaasData',
    IndexName: 'TenantCustomerIndex',
    KeyConditionExpression: 'tenantId = :tenant AND customerId = :customer AND resourceType = :type',
    ExpressionAttributeValues: {
        ':tenant': 'T001',
        ':customer': 'C001',
        ':type': 'document'
    }
}));
```

**Vorteile:** Effiziente Abfragen im Mandanten-Kunden-Kontext und natürliche Datenorganisation.

### Finanztransaktionen
<a name="GSI.DesignPattern.MultiAttributeKeys.Financial"></a>

Banksystem zur Verfolgung von Kontotransaktionen mithilfe von GSIs

#### Codebeispiel
<a name="w2aac19c13c45c23b9c13c13b5b1"></a>

```
// Table design
{
    TableName: 'BankTransactions',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'transactionId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'transactionId', AttributeType: 'S' },
        { AttributeName: 'accountId', AttributeType: 'S' },
        { AttributeName: 'year', AttributeType: 'S' },
        { AttributeName: 'month', AttributeType: 'S' },
        { AttributeName: 'day', AttributeType: 'S' },
        { AttributeName: 'transactionType', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'AccountTimeIndex',
            KeySchema: [
                { AttributeName: 'accountId', KeyType: 'HASH' },
                { AttributeName: 'year', KeyType: 'RANGE' },
                { AttributeName: 'month', KeyType: 'RANGE' },
                { AttributeName: 'day', KeyType: 'RANGE' },
                { AttributeName: 'transactionId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'TransactionTypeIndex',
            KeySchema: [
                { AttributeName: 'accountId', KeyType: 'HASH' },
                { AttributeName: 'transactionType', KeyType: 'RANGE' },
                { AttributeName: 'year', KeyType: 'RANGE' },
                { AttributeName: 'month', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query AccountTimeIndex GSI: All transactions for account in 2023
const yearTransactions = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'AccountTimeIndex',
    KeyConditionExpression: 'accountId = :account AND #year = :year',
    ExpressionAttributeNames: { '#year': 'year' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':year': '2023'
    }
}));

// Query AccountTimeIndex GSI: Transactions in specific month
const monthTransactions = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'AccountTimeIndex',
    KeyConditionExpression: 'accountId = :account AND #year = :year AND #month = :month',
    ExpressionAttributeNames: { '#year': 'year', '#month': 'month' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':year': '2023',
        ':month': '11'
    }
}));

// Query TransactionTypeIndex GSI: Deposits in 2023
const deposits = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'TransactionTypeIndex',
    KeyConditionExpression: 'accountId = :account AND transactionType = :type AND #year = :year',
    ExpressionAttributeNames: { '#year': 'year' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':type': 'deposit',
        ':year': '2023'
    }
}));
```

## Vollständiges Beispiel
<a name="GSI.DesignPattern.MultiAttributeKeys.CompleteExample"></a>

Das folgende Beispiel zeigt Schlüssel mit mehreren Attributen von der Einrichtung bis zur Bereinigung:

### Codebeispiel
<a name="w2aac19c13c45c23b9c15b5b1"></a>

```
import { 
    DynamoDBClient, 
    CreateTableCommand, 
    DeleteTableCommand, 
    waitUntilTableExists 
} from "@aws-sdk/client-dynamodb";
import { 
    DynamoDBDocumentClient, 
    PutCommand, 
    QueryCommand 
} from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

async function multiAttributeKeysDemo() {
    console.log("Starting Multi-Attribute GSI Keys Demo\n");
    
    // Step 1: Create table with GSIs using multi-attribute keys
    console.log("1. Creating table with multi-attribute GSI keys...");
    await client.send(new CreateTableCommand({
        TableName: 'TournamentMatches',
        KeySchema: [
            { AttributeName: 'matchId', KeyType: 'HASH' }
        ],
        AttributeDefinitions: [
            { AttributeName: 'matchId', AttributeType: 'S' },
            { AttributeName: 'tournamentId', AttributeType: 'S' },
            { AttributeName: 'region', AttributeType: 'S' },
            { AttributeName: 'round', AttributeType: 'S' },
            { AttributeName: 'bracket', AttributeType: 'S' },
            { AttributeName: 'player1Id', AttributeType: 'S' },
            { AttributeName: 'matchDate', AttributeType: 'S' }
        ],
        GlobalSecondaryIndexes: [
            {
                IndexName: 'TournamentRegionIndex',
                KeySchema: [
                    { AttributeName: 'tournamentId', KeyType: 'HASH' },
                    { AttributeName: 'region', KeyType: 'HASH' },
                    { AttributeName: 'round', KeyType: 'RANGE' },
                    { AttributeName: 'bracket', KeyType: 'RANGE' },
                    { AttributeName: 'matchId', KeyType: 'RANGE' }
                ],
                Projection: { ProjectionType: 'ALL' }
            },
            {
                IndexName: 'PlayerMatchHistoryIndex',
                KeySchema: [
                    { AttributeName: 'player1Id', KeyType: 'HASH' },
                    { AttributeName: 'matchDate', KeyType: 'RANGE' },
                    { AttributeName: 'round', KeyType: 'RANGE' }
                ],
                Projection: { ProjectionType: 'ALL' }
            }
        ],
        BillingMode: 'PAY_PER_REQUEST'
    }));
    
    await waitUntilTableExists({ client, maxWaitTime: 120 }, { TableName: 'TournamentMatches' });
    console.log("Table created\n");
    
    // Step 2: Insert tournament matches
    console.log("2. Inserting tournament matches...");
    const matches = [
        { matchId: 'match-001', tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'FINALS', bracket: 'CHAMPIONSHIP', player1Id: '101', player2Id: '103', matchDate: '2024-01-20', winner: '101', score: '3-1' },
        { matchId: 'match-002', tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'SEMIFINALS', bracket: 'UPPER', player1Id: '101', player2Id: '105', matchDate: '2024-01-18', winner: '101', score: '3-2' },
        { matchId: 'match-003', tournamentId: 'WINTER2024', region: 'NA-WEST', round: 'FINALS', bracket: 'CHAMPIONSHIP', player1Id: '102', player2Id: '104', matchDate: '2024-01-20', winner: '102', score: '3-2' },
        { matchId: 'match-004', tournamentId: 'SPRING2024', region: 'NA-EAST', round: 'QUARTERFINALS', bracket: 'UPPER', player1Id: '101', player2Id: '108', matchDate: '2024-03-15', winner: '101', score: '3-0' }
    ];
    
    for (const match of matches) {
        await docClient.send(new PutCommand({ TableName: 'TournamentMatches', Item: match }));
    }
    console.log(`Inserted ${matches.length} tournament matches\n`);
    
    // Step 3: Query GSI with multi-attribute partition key
    console.log("3. Query TournamentRegionIndex GSI: WINTER2024/NA-EAST matches");
    const gsiQuery1 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region',
        ExpressionAttributeNames: { '#region': 'region' },
        ExpressionAttributeValues: { ':tournament': 'WINTER2024', ':region': 'NA-EAST' }
    }));
    
    console.log(`  Found ${gsiQuery1.Items.length} matches:`);
    gsiQuery1.Items.forEach(match => {
        console.log(`    ${match.round} - ${match.bracket} - ${match.winner} won`);
    });
    
    // Step 4: Query GSI with multi-attribute sort key
    console.log("\n4. Query PlayerMatchHistoryIndex GSI: All matches for Player 101");
    const gsiQuery2 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'PlayerMatchHistoryIndex',
        KeyConditionExpression: 'player1Id = :player',
        ExpressionAttributeValues: { ':player': '101' }
    }));
    
    console.log(`  Found ${gsiQuery2.Items.length} matches for Player 101:`);
    gsiQuery2.Items.forEach(match => {
        console.log(`    ${match.tournamentId}/${match.region} - ${match.matchDate} - ${match.round}`);
    });
    
    console.log("\nDemo complete");
    console.log("No synthetic keys needed - GSIs use native attributes automatically");
}

async function cleanup() {
    console.log("Deleting table...");
    await client.send(new DeleteTableCommand({ TableName: 'TournamentMatches' }));
    console.log("Table deleted");
}

// Run demo
multiAttributeKeysDemo().catch(console.error);

// Uncomment to cleanup:
// cleanup().catch(console.error);
```

**Minimales Codegerüst**

### Codebeispiel
<a name="w2aac19c13c45c23b9c15b9b1"></a>

```
// 1. Create table with GSI using multi-attribute keys
await client.send(new CreateTableCommand({
    TableName: 'MyTable',
    KeySchema: [
        { AttributeName: 'id', KeyType: 'HASH' }        // Simple base table PK
    ],
    AttributeDefinitions: [
        { AttributeName: 'id', AttributeType: 'S' },
        { AttributeName: 'attr1', AttributeType: 'S' },
        { AttributeName: 'attr2', AttributeType: 'S' },
        { AttributeName: 'attr3', AttributeType: 'S' },
        { AttributeName: 'attr4', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [{
        IndexName: 'MyGSI',
        KeySchema: [
            { AttributeName: 'attr1', KeyType: 'HASH' },    // GSI PK attribute 1
            { AttributeName: 'attr2', KeyType: 'HASH' },    // GSI PK attribute 2
            { AttributeName: 'attr3', KeyType: 'RANGE' },   // GSI SK attribute 1
            { AttributeName: 'attr4', KeyType: 'RANGE' }    // GSI SK attribute 2
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}));

// 2. Insert items with native attributes (no concatenation needed for GSI)
await docClient.send(new PutCommand({
    TableName: 'MyTable',
    Item: {
        id: 'item-001',
        attr1: 'value1',
        attr2: 'value2',
        attr3: 'value3',
        attr4: 'value4',
        // ... other attributes
    }
}));

// 3. Query GSI with all partition key attributes
await docClient.send(new QueryCommand({
    TableName: 'MyTable',
    IndexName: 'MyGSI',
    KeyConditionExpression: 'attr1 = :v1 AND attr2 = :v2',
    ExpressionAttributeValues: {
        ':v1': 'value1',
        ':v2': 'value2'
    }
}));

// 4. Query GSI with sort key attributes (left-to-right)
await docClient.send(new QueryCommand({
    TableName: 'MyTable',
    IndexName: 'MyGSI',
    KeyConditionExpression: 'attr1 = :v1 AND attr2 = :v2 AND attr3 = :v3',
    ExpressionAttributeValues: {
        ':v1': 'value1',
        ':v2': 'value2',
        ':v3': 'value3'
    }
}));

// Note: If any attribute name is a DynamoDB reserved keyword, use ExpressionAttributeNames:
// KeyConditionExpression: 'attr1 = :v1 AND #attr2 = :v2'
// ExpressionAttributeNames: { '#attr2': 'attr2' }
```

## Weitere Ressourcen
<a name="GSI.DesignPattern.MultiAttributeKeys.AdditionalResources"></a>
+ [Bewährte Methoden für DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/best-practices.html)
+ [Arbeiten mit Tabellen und Daten](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html)
+ [Globale Sekundärindizes](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html)
+ [Abfrage- und Scanvorgänge](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html)

# Verwalten globaler sekundärer Indizes in DynamoDB
<a name="GSI.OnlineOps"></a>

Dieser Abschnitt beschreibt, wie Sie globale sekundäre Indizes in Amazon DynamoDB erstellen, ändern und löschen.

**Topics**
+ [Erstellen einer Tabelle mit globalen sekundären Indizes](#GSI.Creating)
+ [Beschreiben globaler sekundären Indizes in einer Tabelle](#GSI.Describing)
+ [Hinzufügen eines globalen sekundären Index zu einer vorhandenen Tabelle](#GSI.OnlineOps.Creating)
+ [Löschen eines globalen sekundären Index](#GSI.OnlineOps.Deleting)
+ [Ändern eines globalen sekundären Indexes während der Erstellung](#GSI.OnlineOps.Creating.Modify)

## Erstellen einer Tabelle mit globalen sekundären Indizes
<a name="GSI.Creating"></a>

Um eine Tabelle mit einem oder mehreren globalen sekundären Indizes zu erstellen, verwenden Sie `CreateTable` mit dem Parameter `GlobalSecondaryIndexes`. Für maximale Abfrageflexibilität können Sie bis zu 20 globale sekundäre Indizes pro Tabelle (Standardkontingent) erstellen. 

Sie müssen ein Attribut angeben, das als Partitionsschlüssel des Index fungieren soll. Sie können optional ein weiteres Attribut für den Sortierschlüssel des Index festlegen. Diese beiden Schlüsselattribute müssen nicht mit den Schlüsselattributen in der Tabelle übereinstimmen. Beispielsweise sind in der *GameScores*Tabelle (siehe[Verwenden globaler sekundärer Indizes in DynamoDB](GSI.md)) `TopScore` weder Schlüsselattribute `TopScoreDateTime` noch Schlüsselattribute enthalten. Sie könnten einen globalen sekundären Index mit einem Partitionsschlüssel von `TopScore` und einem Sortierschlüssel von `TopScoreDateTime` erstellen. Sie könnten einen solchen Index verwenden, um festzustellen, ob eine Verbindung zwischen den Highscores und der Uhrzeit, an der ein Spiel stattfindet, besteht.

Jedes Schlüsselattribut eines Indexes muss ein Skalar des `String`, `Number` oder `Binary` sein. (Es kann kein Dokument oder Satz sein.) Sie können Attribute jeden Datentyps in einen globalen sekundären Index projizieren. Dazu zählen skalare Werte, Dokumente und Sätze. Eine vollständige Liste der Datentypen finden Sie unter [Datentypen](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes).

Wenn Sie den bereitgestellten Modus verwenden, müssen Sie die `ProvisionedThroughput`-Einstellungen für den Index, die aus `ReadCapacityUnits` und `WriteCapacityUnits` bestehen, bereitstellen. Diese Einstellungen des bereitgestellten Durchsatzes sind getrennt von denen der Tabelle, aber verhalten sich auf ähnliche Weise. Weitere Informationen finden Sie unter [Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für globale sekundäre Indizes](GSI.md#GSI.ThroughputConsiderations).

 Globale Sekundärindizes erben den read/write Kapazitätsmodus aus der Basistabelle. Weitere Informationen finden Sie unter [Überlegungen beim Umstellen der Kapazitätsmodi in DynamoDB](bp-switching-capacity-modes.md). 

**Anmerkung**  
 Beim Erstellen eines neuen GSI kann es wichtig sein zu prüfen, ob Ihre Wahl des Partitionsschlüssels eine ungleichmäßige oder eingeschränkte Verteilung von Daten oder Datenverkehr über die Partitionsschlüssel-Werte des neuen Index erzeugt. In diesem Fall werden möglicherweise Backfill- und Schreibvorgänge gleichzeitig auftreten und Schreibvorgänge in die Basistabelle drosseln. Der Service ergreift Maßnahmen, um das Potenzial für dieses Szenario zu minimieren, hat jedoch keinen Einblick in die Form von Kundendaten in Bezug auf den Indexpartitionsschlüssel, die gewählte Projektion oder die Spärlichkeit des Index-Primärschlüssels.  
Wenn Sie vermuten, dass Ihr neuer globaler Sekundärindex möglicherweise enge oder verzerrte Daten oder Datenverkehrsverteilung über Partitionsschlüsselwerte hinweg aufweisen könnte, sollten Sie Folgendes berücksichtigen, bevor Sie betrieblich wichtigen Tabellen neue Indizes hinzufügen.  
Es ist möglicherweise am sichersten, den Index zu einem Zeitpunkt hinzuzufügen, zu dem Ihre Anwendung den geringsten Datenverkehr steuert.
Erwägen Sie, CloudWatch Contributor Insights für Ihre Basistabelle und Indizes zu aktivieren. Dies gibt Ihnen wertvolle Einblicke in Ihre Verkehrsverteilung.
 Beobachten Sie `WriteThrottleEvents` den gesamten Prozess und `OnlineIndexPercentageProgress` CloudWatch geben Sie Kennzahlen an. `ThrottledRequests` Passen Sie die bereitgestellte Schreibkapazität nach Bedarf an, um das Backfill innerhalb einer angemessenen Zeit abzuschließen, ohne dass Ihr laufender Betrieb nennenswert beeinträchtigt wird. `OnlineIndexConsumedWriteCapacity`und `OnlineThrottleEvents` es wird erwartet, dass sie beim Auffüllen des Index 0 anzeigen.
Seien Sie bereit, die Indexerstellung abzubrechen, falls Sie aufgrund der Schreibdrosselung betriebliche Auswirkungen haben.

## Beschreiben globaler sekundären Indizes in einer Tabelle
<a name="GSI.Describing"></a>

Um den Status aller globalen sekundären Indizes in einer Tabelle anzuzeigen, verwenden Sie die `DescribeTable`-Operation. Der `GlobalSecondaryIndexes`-Teil der Antwort zeigt alle Indizes der Tabelle, zusammen mit deren jeweiligem aktuellen Status ( `IndexStatus`).

`IndexStatus` für einen globalen sekundären Index ist einer der folgenden:
+ `CREATING` – Der Index wird derzeit erstellt und ist noch nicht verfügbar.
+ `ACTIVE` — Der Index ist betriebsbereit und Anwendungen können in diesem `Query`-Operationen durchführen
+ `UPDATING` — Die Einstellungen des bereitgestellten Durchsatzes des Index werden geändert.
+ `DELETING` – Der Index wird derzeit gelöscht und kann nicht länger verwendet werden.

Wenn DynamoDB einen globalen sekundären Index fertiggestellt hat, ändert sich der Indexstatus von `CREATING` in `ACTIVE`.

## Hinzufügen eines globalen sekundären Index zu einer vorhandenen Tabelle
<a name="GSI.OnlineOps.Creating"></a>

Um einen globalen sekundären Index einer vorhandenen Tabelle hinzuzufügen, verwenden Sie die `UpdateTable`-Operation mit dem Parameter `GlobalSecondaryIndexUpdates`. Geben Sie die folgenden Informationen ein:
+ Ein Indexname. Der Name muss innerhalb der Indizes der Tabelle eindeutig sein.
+ Das Schlüsselschema des Index. Sie müssen ein Attribut für den Partitionsschlüssel des Index angeben. Sie können optional ein weiteres Attribut für den Sortierschlüssel des Index festlegen. Diese beiden Schlüsselattribute müssen nicht mit den Schlüsselattributen in der Tabelle übereinstimmen. Die Datentypen für jedes Schemaattribut müssen skalar sein: `String`, `Number` oder `Binary`.
+ Die Attribute, die von der Tabelle in den Index projiziert werden:
  + `KEYS_ONLY` — Jeder Eintrag im Index besteht nur aus dem Tabellenpartitionsschlüssel und Sortierschlüsselwerten, sowie den Indexschlüsselwerten. 
  + `INCLUDE` — Zusätzlich zu den in `KEYS_ONLY` beschriebenen Attributen, enthält der sekundäre Index andere Nicht-Schlüsselattribute, die Sie angeben.
  + `ALL` — Der Index enthält alle Attribute der Quelltabelle.
+ Die Einstellungen für den bereitgestellten Durchsatz für den Index bestehen aus `ReadCapacityUnits` und `WriteCapacityUnits`. Diese Einstellungen für den bereitgestellten Durchsatz sind getrennt von denen der Tabelle.

Sie können nur einen globalen sekundären Index pro `UpdateTable`-Operation verwenden.

### Phasen der Index-Erstellung
<a name="GSI.OnlineOps.Creating.Phases"></a>

Wenn Sie einen neuen globalen sekundären Index einer vorhandenen Tabelle hinzufügen, ist die Tabelle weiterhin verfügbar, während der Index erstellt wird. Jedoch ist der neue Index für Abfrageoperationen nicht verfügbar bis sein Status sich von `CREATING` in `ACTIVE` ändert.

**Anmerkung**  
Bei der Erstellung des globalen sekundären Index wird Application Auto Scaling nicht verwendet. Wenn die `MIN`-Kapazität für Application Auto Scaling erhöht wird, verkürzt sich die Erstellungszeit für den globalen sekundären Index nicht.

Im Hintergrund erstellt DynamoDB den Index in zwei Phasen:

**Ressourcenzuweisung**  
DynamoDB weist die erforderlichen Rechen- und Speicherressourcen zu, um den Index zu erstellen.  
Während der Ressourcenzuordnungsphase ist das `IndexStatus`-Attribut `CREATING` und das `Backfilling`-Attribut ist False. Um den Status einer Tabelle und all ihre sekundären Indizes abzurufen, verwenden Sie die `DescribeTable`-Operation.  
Während sich der Index in der Ressourcenzuweisungsphase befindet, können Sie weder den Index noch seine übergeordnete Tabelle löschen. Sie können auch den bereitgestellten Durchsatz des Index oder der Tabelle nicht ändern. Sie in der Tabelle keine anderen Indizes hinzufügen oder löschen. Sie können jedoch den bereitgestellten Durchsatz dieser anderen Indizes ändern.

**Abgleichen**  
Für jedes Element in der Tabelle bestimmt DynamoDB, welche Reihe von Attributen auf Basis seiner Projektion (`KEYS_ONLY`, `INCLUDE`, oder `ALL`) in den Index geschrieben werden. Es schreibt dann diese Attribute in den Index. Während der Abgleichphase verfolgt DynamoDB Elemente, die in der Tabelle hinzugefügt, gelöscht oder aktualisiert werden. Die Attribute dieser Elemente werden, soweit erforderlich, auch in dem Index hinzugefügt, gelöscht oder aktualisiert.  
Während der Abgleichphase ist das `IndexStatus`-Attribut auf `CREATING` gesetzt und das `Backfilling`-Attribut ist True. Um den Status einer Tabelle und all ihrer es abzurufen, verwenden Sie die `DescribeTable`-Operation.  
Während der Index abgleicht, können Sie seine übergeordnete Tabelle nicht löschen. Sie können jedoch weiterhin den den Index löschen oder den bereitgestellten Durchsatz der Tabelle und dessen sekundäre Indizes ändern.  
Während der Abgleichphase können einige Schreibvorgänge regelwidriger Elemente erfolgreich sein, während andere abgelehnt werden. Nach dem Abgleich werden alle Schreibvorgänge für Elemente, die gegen das neue Schlüsselschema des Index verstoßen, abgelehnt. Wir empfehlen, dass Sie das Tool Violation Detector ausführen, nachdem die Abgleichphase abgeschlossen ist, um alle Schlüsselverstöße, die gegebenenfalls aufgetreten sind, zu erkennen und zu beheben. Weitere Informationen finden Sie unter [Erkennen und Korrigieren von Indexschlüsselverstößen in DynamoDB](GSI.OnlineOps.ViolationDetection.md).

Während der laufenden Ressourcenzuordnung und Abgleichphasen ist der Index im Status `CREATING`. Während dieser Zeit führt DynamoDB Leseoperationen für die Tabelle durch. Lesevorgänge aus der Basistabelle zum Auffüllen des globalen sekundären Indexes werden Ihnen nicht in Rechnung gestellt.

Sobald die Erstellung des Index abgeschlossen ist, ändert sich sein Status in `ACTIVE`. Sie können den Index nicht `Query` oder `Scan` bis er `ACTIVE` ist.

**Anmerkung**  
In einigen Fällen kann DynamoDB aufgrund von Indexschlüsselverstößen keine Daten aus der Tabelle in den Index schreiben. Dies kann in folgenden Fällen passieren:  
Der Datentyp eines Attributwerts stimmt nicht mit dem Datentyp eines Indexschlüssel-Schema-Datentyps überein.
Die Größe eines Attributs überschreitet die maximale Länge für ein Indexschlüsselattribut.
Ein Indexschlüsselattribut hat eine leere Zeichenfolge oder einen leeren Binärattributwert.
Indexschlüsselverstöße beeinträchtigen die Erstellung des globalen sekundären Indexes nicht. Wenn der Index jedoch `ACTIVE` wird, sind die verstoßenden Schlüssel nicht im Index vorhanden.  
DynamoDB bietet ein eigenständiges Tool für das Erkennen und Lösen dieser Probleme. Weitere Informationen finden Sie unter [Erkennen und Korrigieren von Indexschlüsselverstößen in DynamoDB](GSI.OnlineOps.ViolationDetection.md).

### Hinzufügen eines globalen sekundären Index zu einer großen Tabelle
<a name="GSI.OnlineOps.Creating.LargeTable"></a>

Die erforderliche Zeit für das Erstellen eines globalen sekundären Indizes hängt von mehreren Faktoren ab, z. B.:
+ Die Tabellengröße
+ Die Anzahl der Elemente in der Tabelle, die sich für eine Aufnahme in den Index eignen
+ Die Reihe von Attributen, die in den Index projiziert werden
+ Schreibaktivität der Haupttabelle, während der Index erstellt wird

Wenn Sie einen globalen sekundären Index einer sehr große Tabelle hinzufügen, kann es sehr lang dauern, bis der Erstellungsvorgang abgeschlossen ist. Um den Fortschritt zu überwachen und festzustellen, ob der Index über ausreichende Schreibkapazität verfügt, ziehen Sie die folgenden CloudWatch Amazon-Metriken zu Rate:
+ `OnlineIndexPercentageProgress`

Weitere Informationen zu CloudWatch Metriken im Zusammenhang mit DynamoDB finden Sie unter. [DynamoDB-Metriken](metrics-dimensions.md#dynamodb-metrics)

**Wichtig**  
Möglicherweise müssen Sie sehr große Tabellen auf eine Zulassungsliste setzen, bevor Sie einen globalen sekundären Index erstellen oder aktualisieren können. Bitte wenden Sie sich an den AWS Support, um Ihre Tische auf die Zulassungsliste zu setzen.

Während ein Index abgeglichen wird, verwendet DynamoDB interne Systemkapazität um aus der Tabelle zu lesen. Dies soll die Auswirkung der Indexerstellung minimieren und vermeiden, dass der Tabelle nicht genügend Schreibkapazität zur Verfügung steht.

## Löschen eines globalen sekundären Index
<a name="GSI.OnlineOps.Deleting"></a>

Wenn Sie keinen globalen sekundären Index mehr benötigen, können Sie ihn mithilfe von `UpdateTable` verwenden.

Sie können nur einen globalen sekundären Index pro `UpdateTable`verwenden.

Während der globale sekundäre Index gelöscht wird, hat dies keine Auswirkung auf jegliche Lese- oder Schreibaktivität in der übergeordneten Tabelle. Während die Löschung ausgeführt wird, können Sie weiterhin den bereitgestellten Durchsatz anderer Indizes ändern

**Anmerkung**  
Beim Löschen einer Tabelle mithilfe der `DeleteTable`-Aktion, werden alle es in dieser Tabelle ebenfalls gelöscht.
Die Löschung des globalen sekundären Index wird Ihrem Konto nicht berechnet.

## Ändern eines globalen sekundären Indexes während der Erstellung
<a name="GSI.OnlineOps.Creating.Modify"></a>

Während ein Index erstellt wird, können Sie die `DescribeTable`-Operation verwenden, um zu bestimmen, in welcher Phase er sich befindet. Die Beschreibung für den Index enthält ein Boolesches Attribut, `Backfilling`, um anzugeben, ob DynamoDB derzeit den Index mit Elementen aus der Tabelle lädt. Wenn `Backfilling` True ist, dann ist die Phase der Ressourcenzuordnung abgeschlossen und der Index ist dabei, abzugleichen. 

Während des Abgleichens können Sie den erstellten Index löschen. Während der Phase können Sie in der Tabelle keine anderen Indizes hinzufügen oder löschen.

**Anmerkung**  
Bei Indizes, die als Teil einer `CreateTable`-Operation erstellt wurden, wird das `Backfilling`-Attribut in der `DescribeTable`-Ausgabe nicht angezeigt. Weitere Informationen finden Sie unter [Phasen der Index-Erstellung](#GSI.OnlineOps.Creating.Phases).

# Erkennen und Korrigieren von Indexschlüsselverstößen in DynamoDB
<a name="GSI.OnlineOps.ViolationDetection"></a>

Während der Abgleichphase der globalen sekundären Index-Erstellung untersucht Amazon DynamoDB jedes Element in der Tabelle, um zu ermitteln, ob es in den Index aufgenommen werden kann. Einige Elemente können möglicherweise nicht in den Index aufgenommen werden, da sie zu Indexschlüsselverstößen führen würden. In diesem Fall verbleiben die Elemente in der Tabelle, der Index verfügt dann jedoch über keinen entsprechenden Eintrag für dieses Element.

*Verstoß des Indexschlüssels* tritt in folgenden Situationen auf:
+ Die Datentypen zwischen einem Attributwert und dem Indexschlüsselschema stimmen nicht überein. Angenommen, eines der Elemente in der Tabelle `GameScores` verfügt über den Wert `TopScore` des Typs `String`. Wenn Sie dann einen globalen sekundären Index mit dem Partitionsschlüssel `TopScore` vom Typ `Number` hinzufügen, verstößt das Element aus der Tabelle gegen den Index.
+ Ein Attributwert aus der Tabelle überschreitet die maximale Länge für ein Indexschlüsselattribut. Die maximale Länge des Partitionsschlüssels beträgt 2048 bytes und die maximale Länge des Sortierschlüssels 1024 bytes. Wenn einer der entsprechenden Attributwerte in der Tabelle diese Grenzwerte überschreitet, würde das Element aus der Tabelle gegen den Index verstoßen.

**Anmerkung**  
Wenn ein Zeichenfolgen- oder Binär-Attributwert für ein Attribut festgelegt ist, das als Indexschlüssel verwendet wird, muss der Attributwert eine Länge größer als Null haben. Andernfalls würde das Element aus der Tabelle gegen den Indexschlüssel verstoßen.  
Dieses Tool kennzeichnet diesen Indexschlüsselverstoß derzeit nicht.

Wenn ein Indexschlüsselverstoß auftritt, wird die Auffüllphase ohne Unterbrechung fortgesetzt. Verstoßende Elemente sind jedoch nicht im Index enthalten. Nach Abschluss der Abgleichphase werden alle Schreibvorgänge für Elemente, die gegen das neue Schlüsselschema des Indexes verstoßen, abgelehnt.

Um die Attributwerte in einer Tabelle, die gegen einen Indexschlüssel verstoßen, zu identifizieren und zu korrigieren, verwenden Sie das Tool Violation Detector. Um Violation Detector auszuführen, erstellen Sie eine Konfigurationsdatei, die den Namen einer zu scannenden Tabelle sowie die Datentypen des Partitions- und Sortierschlüssels des globalen sekundären Indizes enthält und angibt, welche Aktionen unternommen werden, sollten Verstöße gegen den Indexschlüssel gefunden werden. Violation Detector kann in einem der beiden folgenden Modi ausgeführt werden:
+ **Erkennungsmodus** — Erkennt Indexschlüsselverstöße. Verwenden Sie den Erkennungsmodus, um die Elemente in der Tabelle zu ermitteln, die in einem globalen sekundären Index zu Schlüsselverstößen führen. (Sie können optional angeben, dass die den Verstoß verursachenden Tabellenelemente sofort gelöscht werden, nachdem sie gefunden wurden.) Die Ausgabe des Erkennungsmodus wird eine Datei geschrieben, die Sie für weitere Analysen verwenden können.
+ **Korrekturmodus** — Korrigiert Indexschlüsselverstöße. Im Korrekturmodus liest Violation Detector eine Eingabedatei im gleichen Format wie die Ausgabedatei des Erkennungsmodus. Der Korrekturmodus liest die Datensätze aus der Eingabedatei und löscht zu jedem Datensatz die entsprechenden Elemente in der Tabelle bzw. aktualisiert diese. (Wenn Sie beschließen, die Elemente zu aktualisieren, müssen Sie die Eingabedatei bearbeiten und für diese Aktualisierungen entsprechende Werte festlegen.)

## Herunterladen und Ausführen von Violation Detector
<a name="GSI.OnlineOps.ViolationDetection.Running"></a>

Violation Detector steht als ausführbares Java-Archiv (`.jar`-Datei) zur Verfügung und kann auf Windows-, MacOS- oder Linux-Computern ausgeführt werden. Der Violation Detector erfordert Java 1.7 (oder höher) und Apache Maven.
+ [Laden Sie den Verletzungsdetektor herunter von GitHub](https://github.com/awslabs/dynamodb-online-index-violation-detector)

Um Violation Detector mit Maven herunterzuladen und zu installieren, befolgen Sie die Anweisungen in der `README.md`-Datei.

Um Violation Detector zu starten, gehen Sie zu dem Verzeichnis, in dem Sie `ViolationDetector.java` erstellt haben, und geben Sie den folgenden Befehl ein:

```
java -jar ViolationDetector.jar [options]
```

Die Violation-Detector-Befehlszeile akzeptiert die folgenden Optionen:
+ `-h | --help` – Druckt eine Nutzungszusammenfassung und die Optionen für Violation Detector.
+ `-p | --configFilePath` `value` – Der vollständig qualifizierte Namen einer Violation Detector Konfigurationsdatei. Weitere Informationen finden Sie unter [Die Konfigurationsdatei für den Violation Detector](#GSI.OnlineOps.ViolationDetection.ConfigFile).
+ `-t | --detect`  `value`– Erkennt Indexschlüsselverstöße in der Tabelle und schreibt sie in die Ausgabedatei von Violation Detector. Wenn der Wert für diesen Parameter auf `keep` festgelegt ist, werden Elemente mit Schlüsselverstößen nicht geändert. Wenn der Wert auf `delete` festgelegt ist, werden Elemente mit Schlüsselverstößen aus der Tabelle gelöscht.
+ `-c | --correct` `value` — Liest Indexschlüsselverstöße aus einer Eingabedatei und nimmt entsprechende Korrekturen an den Elementen in der Tabelle vor. Wenn der Wert für diesen Parameter auf `update` festgelegt ist, werden Elemente mit Schlüsselverstößen mit neuen, konformen Werten aktualisiert. Wenn der Wert auf `delete` festgelegt ist, werden Elemente mit Schlüsselverstößen aus der Tabelle gelöscht.

## Die Konfigurationsdatei für den Violation Detector
<a name="GSI.OnlineOps.ViolationDetection.ConfigFile"></a>

Zur Laufzeit erfordert das Tool Violation Detector eine Konfigurationsdatei. Die Parameter in dieser Datei bestimmen, auf welche DynamoDB-Ressourcen Violation Detector zugreifen kann und wie viel bereitgestellten Durchsatz es verbrauchen darf. In der Tabelle unten werden diese Parameter beschrieben.


****  

| Parametername | Description | Erforderlich? | 
| --- | --- | --- | 
|  `awsCredentialsFile`  |  Der vollständig qualifizierte Namen einer Datei, die Ihre AWS -Anmeldeinformationen enthält. Die Datei mit den Anmeldeinformationen muss das folgende Format aufweisen: <pre>accessKey = access_key_id_goes_here<br />secretKey = secret_key_goes_here </pre>  |  Ja  | 
|  `dynamoDBRegion`  |  Die AWS Region, in der sich die Tabelle befindet. Beispiel: `us-west-2`.  |  Ja  | 
|  `tableName`  | Der Name der zu scannenden DynamoDB-Tabelle. |  Ja  | 
|  `gsiHashKeyName`  |  Der Name des Partitionsschlüssels des Index.  |  Ja  | 
|  `gsiHashKeyType`  |  Der Datentyp des Partitionsschlüssels des Index – `String`, `Number` oder `Binary`: `S \| N \| B`  |  Ja  | 
|  `gsiRangeKeyName`  |  Der Name des Sortierschlüssels des Index. Geben Sie diesen Parameter nicht an, wenn der Index nur über einen einfachen Primärschlüssel (Partitionsschlüssel) verfügt.  |  Nein  | 
|  `gsiRangeKeyType`  |  Der Datentyp des Sortierschlüssels–`String`,`Number`, oder`Binary`: `S \| N \| B`  Geben Sie diesen Parameter nicht an, wenn der Index nur über einen einfachen Primärschlüssel (Partitionsschlüssel) verfügt.  |  Nein  | 
|  `recordDetails`  |  Gibt an, ob alle Details der Indexschlüsselverstöße in die Ausgabedatei geschrieben werden sollen. Ist dieser Parameter auf `true` (Standardwert) gesetzt, werden alle Informationen zu den Verstoß-Elementen aufgezeichnet. Wenn er auf `false` festgelegt ist, wird nur die Anzahl der Verstöße erfasst.  |  Nein  | 
|  `recordGsiValueInViolationRecord`  |  Gibt an, ob die Werte der verursachenden Indexschlüssel in die Ausgabedatei geschrieben werden sollen. Ist dieser Parameter auf `true` (Standardwert) gesetzt, werden die Schlüsselwerte aufgezeichnet. Ist dieser Parameter auf `false` festgelegt, werden die Schlüsselwerte nicht aufgezeichnet.  |  Nein  | 
|  `detectionOutputPath`  |  Der vollständige Pfad der Violation-Detector-Ausgabedatei. Dieser Parameter unterstützt das Schreiben in ein lokales Verzeichnis oder in Amazon Simple Storage Service (Amazon S3). Im Folgenden sind einige Beispiele aufgeführt: `detectionOutputPath = ``//local/path/filename.csv` `detectionOutputPath = ``s3://bucket/filename.csv` Die Informationen in der Ausgabedatei werden im komma-separierten Werte (CSV)-Format angezeigt. Wenn Sie `detectionOutputPath` nicht festlegen, wird die Ausgabedatei `violation_detection.csv` genannt und in das aktuelle Arbeitsverzeichnis geschrieben.  |  Nein  | 
|  `numOfSegments`  | Die Anzahl der Segmente des parallelen Scans, die verwendet werden sollen, wenn Violation Detector die Tabelle scannt. Der Standardwert ist 1. Dies bedeutet, dass die Tabelle sequenziell gescannt wird. Wenn der Wert 2 oder höher lautet, unterteilt Violation Detector die Tabelle in diese Anzahl logischer Segmente und eine gleichmäßigen Anzahl von Scan-Threads. Die maximale Einstellung für `numOfSegments` lautet 4.096 Tage.Bei größeren Tabellen ist ein paralleler Scan in der Regel schneller als ein sequenzieller Scan. Wenn die Tabelle außerdem groß genug ist, um sich über mehrere Partitionen zu erstrecken, verteilt ein paralleler Scan die Lesevorgänge gleichmäßig auf mehrere Partitionen.Weitere Informationen zu parallelen Scans in DynamoDB finden Sie im Abschnitt [Parallele Scans](Scan.md#Scan.ParallelScan). |  Nein  | 
|  `numOfViolations`  |  Der obere Grenzwert für Indexschlüsselverstöße, die in die Ausgabedatei geschrieben werden sollen. Ist dieser Parameter auf `-1` (Standardwert) gesetzt, wird die gesamte Tabelle gescannt. Ist eine positive Ganzzahl festgelegt, beendet Violation Detector den Vorgang nach Erreichen dieser Anzahl von Verstößen.  |  Nein  | 
|  `numOfRecords`  |  Die Anzahl der Elemente in der Tabelle, die gescannt werden sollen. Ist dieser Parameter auf -1 (Standardwert) gesetzt, wird die gesamte Tabelle gescannt. Ist eine positive Ganzzahl festgelegt, beendet Violation Detector den Vorgang, nachdem es diese Anzahl von Elementen in der Tabelle gescannt hat.  |  Nein  | 
|  `readWriteIOPSPercent`  |  Regelt den Prozentsatz der bereitgestellten Lesekapazitätseinheiten, die während des Tabellen-Scans verbraucht werden. Der Bereich gültiger Werte lautet `1` bis `100`. Der Standardwert (`25`) bedeutet, dass Violation Detector nicht mehr als 25 % des bereitgestellten Lesedurchsatzes der Tabelle verbraucht.  |  Nein  | 
|  `correctionInputPath`  |  Der vollständige Pfad der Violation-Detector-Korrektureingabedatei. Wenn Sie Violation Detector im Korrekturmodus ausführen, wird der Inhalt dieser Datei herangezogen, um die Datenelemente in der Tabelle, die gegen den verstoßen, zu ändern oder zu löschen. Das Format der `correctionInputPath`-Datei ist identisch mit der `detectionOutputPath`-Datei. So können Sie die Ausgabe des Erkennungsmodus als Eingabe für den Korrekturmodus verarbeiten.  |  Nein  | 
|  `correctionOutputPath`  |  Der vollständige Pfad der Violation-Detector-Korrekturausgabedatei. Diese Datei wird nur erstellt, wenn bei der Aktualisierung Fehler aufgetreten sind. Dieser Parameter unterstützt das Schreiben in ein lokales Verzeichnis oder in Amazon S3. Im Folgenden sind einige Beispiele aufgeführt: `correctionOutputPath = ``//local/path/filename.csv` `correctionOutputPath = ``s3://bucket/filename.csv` Die Informationen in der Ausgabedatei werden im CSV-Format angezeigt. Wenn Sie `correctionOutputPath` nicht festlegen, wird die Ausgabedatei `violation_update_errors.csv` genannt und in das aktuelle Arbeitsverzeichnis geschrieben.  |  Nein  | 

## Erkennung
<a name="GSI.OnlineOps.ViolationDetection.Detection"></a>

Um Verstöße gegen den Indexschlüssel zu erkennen, verwenden Sie Violation Detector mit der Befehlszeilenoption `--detect`. Um zu verstehen, wie diese Option funktioniert, sollten Sie die Tabelle `ProductCatalog` zurate ziehen. Im Folgenden finden Sie eine Liste der Elemente in der Tabelle. Nur der Primärschlüssel (`Id`) und das `Price`-Attribut werden angezeigt.


****  

| ID (Primärschlüssel) | Preis | 
| --- | --- | 
| 101 |  5  | 
| 102 |  20  | 
| 103 | 200  | 
| 201 |  100  | 
| 202 |  200  | 
| 203 |  300  | 
| 204 |  400  | 
| 205 |  500  | 

Alle Werte für `Price` sind vom Typ `Number`. Da DynamoDB jedoch schemalos ist, können Sie ein Element mit einem nicht numerischen `Price` hinzufügen. Angenommen, wir fügen ein anderes Element zur Tabelle `ProductCatalog` hinzu.


****  

| ID (Primärschlüssel) | Preis | 
| --- | --- | 
| 999 | "Hello" | 

Die Tabelle verfügt jetzt über insgesamt neun Elemente.

Nun fügen Sie der Tabelle einen neuen globalen sekundären Index hinzu: `PriceIndex`. Der Primärschlüssel für diesen Index ist ein Partitionsschlüssel, `Price`, vom Typ `Number`. Nachdem der Index erstellt wurde, enthält er acht Elemente—aber die `ProductCatalog`-Tabelle verfügt aber über neun Elemente. Der Grund für diese Abweichung ist, dass der Wert `"Hello"` vom Typ `String` ist, `PriceIndex` aber über einen Primärschlüssel vom Typ `Number` verfügt. Der `String`-Wert verstößt gegen den Schlüssel des globalen sekundären Indizes, also ist er im Index nicht vorhanden.

Um Violation Detector in diesem Szenario zu verwenden, erstellen Sie zuerst eine Konfigurationsdatei, wie z. B. folgende:

```
# Properties file for violation detection tool configuration.
# Parameters that are not specified will use default values.

awsCredentialsFile = /home/alice/credentials.txt
dynamoDBRegion = us-west-2
tableName = ProductCatalog
gsiHashKeyName = Price
gsiHashKeyType = N
recordDetails = true
recordGsiValueInViolationRecord = true
detectionOutputPath = ./gsi_violation_check.csv
correctionInputPath = ./gsi_violation_check.csv
numOfSegments = 1
readWriteIOPSPercent = 40
```

Als Nächstes führen Sie den Violation Detector aus, wie im folgenden Beispiel gezeigt.

```
$  java -jar ViolationDetector.jar --configFilePath config.txt --detect keep

Violation detection started: sequential scan, Table name: ProductCatalog, GSI name: PriceIndex
Progress: Items scanned in total: 9,    Items scanned by this thread: 9,    Violations found by this thread: 1, Violations deleted by this thread: 0
Violation detection finished: Records scanned: 9, Violations found: 1, Violations deleted: 0, see results at: ./gsi_violation_check.csv
```

Wenn der Konfigurationsparameter `recordDetails` auf `true` gesetzt ist, schreibt Violation Detector die Details jedes Verstoßes in die Ausgabedatei, wie im folgenden Beispiel:

```
Table Hash Key,GSI Hash Key Value,GSI Hash Key Violation Type,GSI Hash Key Violation Description,GSI Hash Key Update Value(FOR USER),Delete Blank Attributes When Updating?(Y/N) 

999,"{""S"":""Hello""}",Type Violation,Expected: N Found: S,,
```

Die Ausgabedatei ist im CSV-Format. Die erste Zeile in der Datei ist eine Überschrift, gefolgt von einem Datensatz für jedes Element, das gegen den Indexschlüssel verstößt. Die Felder dieser die Verletzung verursachenden Datensätze sind folgende:
+ **Hash-Schlüssel der Tabelle** — Der Partitionsschlüsselwert des Elements in der Tabelle.
+ **Tabellenbereichsschlüssel** — Der Sortierschlüsselwert des Elements in der Tabelle.
+ **GSI-Hash-Schlüsselwert** – Partitionsschlüsselwert des globalen sekundären Indizes.
+ **Art des GSI-Hash-Schlüsselverstoßes** — Entweder `Type Violation` oder `Size Violation`.
+ **Beschreibung des GSI-Hash-Schlüsselverstoßes** — Die Ursache des Verstoßes.
+ **Aktualisierungswert des GSI-Hash-Schlüssels (FÜR BENUTZER)** — Im Korrekturmodus ein neuer, vom Benutzer angegebener Wert für das Attribut.
+ **Schlüsselwert des GSI-Bereichs** – Der Sortierschlüsselwert des globalen sekundären Indexes.
+ **Art des GSI-Bereichsschlüsselverstoßes** — Entweder `Type Violation` oder `Size Violation`.
+ **Beschreibung des GSI-Bereichsschlüsselverstoßes** — Die Ursache des Verstoßes.
+ **Aktualisierungswert des GSI-Bereichsschlüssels (FÜR BENUTZER)** — Im Korrekturmodus ein neuer, vom Benutzer angegebener Wert für das Attribut.
+ **Leeres Attribut bei Aktualisierung löschen (J/N)** — Bestimmt im Korrekturmodus, ob das den Verstoß verursachende Element in der Tabelle gelöscht (J) oder beibehalten (N) werden soll; jedoch nur, wenn eines der folgenden Felder leer ist:
  + `GSI Hash Key Update Value(FOR USER)`
  + `GSI Range Key Update Value(FOR USER)`

  Wenn eines dieser Felder nicht leer ist, hat `Delete Blank Attribute When Updating(Y/N)` keine Auswirkungen.

**Anmerkung**  
Das Ausgabeformat kann abhängig von der Konfigurationsdatei und den Befehlszeilenoptionen variieren. Wenn die Tabelle z. B. über einen einfachen Primärschlüssel (ohne Sortierschlüssel) verfügt, sind in der Ausgabe keine Sortierschlüsselfelder vorhanden.  
Die den Verstoß verursachenden Datensätze in der Datei sind möglicherweise nicht sortiert.

## Korrektur
<a name="GSI.OnlineOps.ViolationDetection.Correction"></a>

Um Verstöße gegen den Indexschlüssel zu korrigieren, verwenden Sie Violation Detector mit der Befehlszeilenoption `--correct`. Im Korrekturmodus liest Violation Detector die Eingabedatei, die im Parameter `correctionInputPath` angegeben ist. Diese Datei hat das gleiche Format wie die Datei `detectionOutputPath`. Sie können also die Ausgabe der Erkennung als Eingabe für die Korrektur verwenden.

Violation Detector bietet zwei verschiedene Möglichkeiten zur Korrektur von Indexschlüsselverstößen:
+ **Verstöße löschen** – Löscht die Tabellenelemente, die über Verstoß-Attributwerte verfügen.
+ **Verstöße aktualisieren** – Aktualisiert die Tabellenelemente durch Ersetzen der Verstoß-Attribute durch konforme Werte.

In beiden Fällen können Sie die Ausgabedatei aus dem Erkennungsmodus als Eingabe für den Korrekturmodus verwenden.

Setzen wir unser Beispiel `ProductCatalog` fort: Angenommen, wir möchten das Verstoß-Element aus der Tabelle löschen. Zu diesem Zweck verwenden Sie die folgenden Befehlszeile:

```
$  java -jar ViolationDetector.jar --configFilePath config.txt --correct delete
```

An diesem Punkt werden Sie gebeten zu bestätigen, ob die verletzenden Elemente gelöscht werden sollen.

```
Are you sure to delete all violations on the table?y/n
y
Confirmed, will delete violations on the table...
Violation correction from file started: Reading records from file: ./gsi_violation_check.csv, will delete these records from table.
Violation correction from file finished: Violations delete: 1, Violations Update: 0
```

Nun verfügen `ProductCatalog` und `PriceIndex` über dieselbe Anzahl Elemente.

# Arbeiten mit globalen sekundären Indizes: Java
<a name="GSIJavaDocumentAPI"></a>

Sie können die AWS SDK für Java Document API verwenden, um eine Amazon DynamoDB-Tabelle mit einem oder mehreren globalen Sekundärindizes zu erstellen, die Indizes in der Tabelle zu beschreiben und Abfragen mithilfe der Indizes durchzuführen. 

Nachfolgend sind die allgemeinen Schritte für Tabellenoperationen aufgeführt. 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Stellen Sie den erforderlichen und optionalen Parameter für die Operation bereit, indem Sie die entsprechenden Anforderungsobjekte erstellen. 

1. Rufen Sie die entsprechende Methode auf, die vom Client, den Sie im vorhergehenden Schritt erstellt haben, bereitgestellt wird. 

**Topics**
+ [Erstellen einer Tabelle mit einem globalen sekundären Index](#GSIJavaDocumentAPI.CreateTableWithIndex)
+ [Beschreiben einer Tabelle mit einem globalen sekundären Index](#GSIJavaDocumentAPI.DescribeTableWithIndex)
+ [Abfragen eines globalen sekundären Indexes](#GSIJavaDocumentAPI.QueryAnIndex)
+ [Beispiel: Globale Sekundärindizes mithilfe der AWS SDK für Java Dokument-API](GSIJavaDocumentAPI.Example.md)

## Erstellen einer Tabelle mit einem globalen sekundären Index
<a name="GSIJavaDocumentAPI.CreateTableWithIndex"></a>

Sie können globale sekundäre Indizes gleichzeitig mit der Tabelle erstellen. Zu diesem Zweck verwenden Sie `CreateTable` und geben Ihre Spezifikationen für ein oder mehrere globale sekundäre Indizes an. Das folgende Java-Codebeispiel erstellt eine Tabelle, die Informationen über Wetterdaten enthält. Der Partitionsschlüssel ist `Location` und der Sortierschlüssel `Date`. Ein globaler sekundärer Index mit Namen `PrecipIndex` ermöglicht einen schnellen Zugriff auf Niederschlagsdaten für verschiedene Standorte.

Im Folgenden sind die Schritte zum Erstellen einer Tabelle mit einem globalen sekundären Index unter Verwendung der DynamoDB-Dokument-API aufgeführt. 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `CreateTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen.

   Sie müssen den Tabellennamen, seinen zugehörigen Primärschlüssel und die Werte des bereitgestellten Durchsatzes angeben. Für den globalen sekundären Index müssen Sie den Indexnamen, seine Einstellungen des bereitgestellten Durchsatzes, die Attributdefinitionen für den Index, das Schlüsselschema für den Index und die Attributprojektion angeben.

1. Rufen Sie die `createTable`-Methode auf, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht. Der Code erstellt eine Tabelle (`WeatherData`) mit einem globalen sekundären Index (`PrecipIndex`). Der Index-Partitionsschlüssel ist `Date` und der Sortierschlüssel `Precipitation`. Alle Tabellenattribute werden in den Index projiziert. Benutzer können diesen Index abfragen, um Wetterdaten für ein bestimmtes Datum abzurufen. Optional können diese nach Niederschlagsmenge sortiert werden. 

Da es sich bei `Precipitation` um kein Schlüsselattribut für die Tabelle handelt, ist es nicht erforderlich. `WeatherData`-Elemente ohne `Precipitation` erscheinen jedoch nicht in `PrecipIndex`.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

// Attribute definitions
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Location")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Date")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Precipitation")
    .withAttributeType("N"));

// Table key schema
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Location")
    .withKeyType(KeyType.HASH));  //Partition key
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.RANGE));  //Sort key

// PrecipIndex
GlobalSecondaryIndex precipIndex = new GlobalSecondaryIndex()
    .withIndexName("PrecipIndex")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 10)
        .withWriteCapacityUnits((long) 1))
        .withProjection(new Projection().withProjectionType(ProjectionType.ALL));

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.HASH));  //Partition key
indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Precipitation")
    .withKeyType(KeyType.RANGE));  //Sort key

precipIndex.setKeySchema(indexKeySchema);

CreateTableRequest createTableRequest = new CreateTableRequest()
    .withTableName("WeatherData")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 5)
        .withWriteCapacityUnits((long) 1))
    .withAttributeDefinitions(attributeDefinitions)
    .withKeySchema(tableKeySchema)
    .withGlobalSecondaryIndexes(precipIndex);

Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen.

## Beschreiben einer Tabelle mit einem globalen sekundären Index
<a name="GSIJavaDocumentAPI.DescribeTableWithIndex"></a>

Um Informationen zu globalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie `DescribeTable`. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

Im Folgenden werden die Schritte zum Zugriff auf globale sekundäre Index-Informationen in einer Tabelle dargelegt. 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse, um den Index darzustellen, mit dem Sie arbeiten möchten.

1. Rufen Sie die `describe`-Methode für das `Table`-Objekt auf.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("WeatherData");
TableDescription tableDesc = table.describe();
    

Iterator<GlobalSecondaryIndexDescription> gsiIter = tableDesc.getGlobalSecondaryIndexes().iterator();
while (gsiIter.hasNext()) {
    GlobalSecondaryIndexDescription gsiDesc = gsiIter.next();
    System.out.println("Info for index "
         + gsiDesc.getIndexName() + ":");

    Iterator<KeySchemaElement> kseIter = gsiDesc.getKeySchema().iterator();
    while (kseIter.hasNext()) {
        KeySchemaElement kse = kseIter.next();
        System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
    }
    Projection projection = gsiDesc.getProjection();
    System.out.println("\tThe projection type is: "
        + projection.getProjectionType());
    if (projection.getProjectionType().toString().equals("INCLUDE")) {
        System.out.println("\t\tThe non-key projected attributes are: "
            + projection.getNonKeyAttributes());
    }
}
```

## Abfragen eines globalen sekundären Indexes
<a name="GSIJavaDocumentAPI.QueryAnIndex"></a>

Sie können `Query` für einen globalen sekundären Index genauso nutzen, wie Sie `Query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexpartitionsschlüssel und Sortierschlüssel (falls vorhanden) und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `PrecipIndex`, der über den Partitionsschlüssel `Date` und den Sortierschlüssel `Precipitation` verfügt. Die Indexabfrage gibt alle Wetterdaten für ein bestimmtes Datum zurück, in denen der Niederschlag größer als Null ist.

Im Folgenden werden die Schritte beschrieben, um einen globalen sekundären Index mithilfe der Document API abzufragen. AWS SDK für Java 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse, um den Index darzustellen, mit dem Sie arbeiten möchten.

1. Erstellen Sie für den Index, den Sie abfragen möchten, eine Instance der `Index`-Klasse.

1. Rufen Sie die `query`-Methode für das `Index`-Objekt auf.

Der Attributname `Date` ist ein DynamoDB-reserviertes Wort. Daher müssen Sie einen Ausdrucksattributnamen als Platzhalter in dem `KeyConditionExpression` verwenden.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("WeatherData");
Index index = table.getIndex("PrecipIndex");

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("#d = :v_date and Precipitation = :v_precip")
    .withNameMap(new NameMap()
        .with("#d", "Date"))
    .withValueMap(new ValueMap()
        .withString(":v_date","2013-08-10")
        .withNumber(":v_precip",0));

ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> iter = items.iterator(); 
while (iter.hasNext()) {
    System.out.println(iter.next().toJSONPretty());
}
```

# Beispiel: Globale Sekundärindizes mithilfe der AWS SDK für Java Dokument-API
<a name="GSIJavaDocumentAPI.Example"></a>

Das folgende Java-Codebeispiel zeigt, wie Sie mit globalen sekundären Indizes arbeiten. Das Beispiel erstellt eine Tabelle mit dem Namen `Issues`, die in einem einfachen Fehlerüberwachungssystem für Softwareentwicklung verwendet werden könnte. Der Partitionsschlüssel ist `IssueId` und der Sortierschlüssel `Title`. Es gibt drei globale sekundäre Indizes in dieser Tabelle:
+ `CreateDateIndex` – Der Partitionsschlüssel ist `CreateDate` und der Sortierschlüssel `IssueId`. Zusätzlich zu den Tabellenschlüsseln werden die Attribute `Description` und `Status` in den Index projiziert.
+ `TitleIndex` – Der Partitionsschlüssel ist `Title` und der Sortierschlüssel `IssueId`. Keine anderen Attribute als die Tabellenschlüssel werden in den Index projiziert.
+ `DueDateIndex` — Der Partitionsschlüssel ist `DueDate`. Ein Sortierschlüssel ist nicht vorhanden.) Alle Tabellenattribute werden in den Index projiziert.

Nachdem die `Issues`-Tabelle erstellt wurde, lädt das Programm die Tabelle mit Daten, die Software-Fehlerberichte darstellen. Anschließend werden die Daten mithilfe der globalen sekundären Indizes abgefragt. Schließlich löscht das Programm die `Issues`-Tabelle.

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md).

**Example**  

```
package com.amazonaws.codesamples.document;

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class DocumentAPIGlobalSecondaryIndexExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    public static String tableName = "Issues";

    public static void main(String[] args) throws Exception {

        createTable();
        loadData();

        queryIndex("CreateDateIndex");
        queryIndex("TitleIndex");
        queryIndex("DueDateIndex");

        deleteTable(tableName);

    }

    public static void createTable() {

        // Attribute definitions
        ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

        attributeDefinitions.add(new AttributeDefinition().withAttributeName("IssueId").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("Title").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("CreateDate").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("DueDate").withAttributeType("S"));

        // Key schema for table
        ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
        tableKeySchema.add(new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.HASH)); // Partition
                                                                                                           // key
        tableKeySchema.add(new KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.RANGE)); // Sort
                                                                                                          // key

        // Initial provisioned throughput settings for the indexes
        ProvisionedThroughput ptIndex = new ProvisionedThroughput().withReadCapacityUnits(1L)
                .withWriteCapacityUnits(1L);

        // CreateDateIndex
        GlobalSecondaryIndex createDateIndex = new GlobalSecondaryIndex().withIndexName("CreateDateIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("CreateDate").withKeyType(KeyType.HASH), // Partition
                                                                                                                 // key
                        new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort
                                                                                                        // key
                .withProjection(
                        new Projection().withProjectionType("INCLUDE").withNonKeyAttributes("Description", "Status"));

        // TitleIndex
        GlobalSecondaryIndex titleIndex = new GlobalSecondaryIndex().withIndexName("TitleIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.HASH), // Partition
                                                                                                            // key
                        new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort
                                                                                                        // key
                .withProjection(new Projection().withProjectionType("KEYS_ONLY"));

        // DueDateIndex
        GlobalSecondaryIndex dueDateIndex = new GlobalSecondaryIndex().withIndexName("DueDateIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("DueDate").withKeyType(KeyType.HASH)) // Partition
                                                                                                              // key
                .withProjection(new Projection().withProjectionType("ALL"));

        CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName)
                .withProvisionedThroughput(
                        new ProvisionedThroughput().withReadCapacityUnits((long) 1).withWriteCapacityUnits((long) 1))
                .withAttributeDefinitions(attributeDefinitions).withKeySchema(tableKeySchema)
                .withGlobalSecondaryIndexes(createDateIndex, titleIndex, dueDateIndex);

        System.out.println("Creating table " + tableName + "...");
        dynamoDB.createTable(createTableRequest);

        // Wait for table to become active
        System.out.println("Waiting for " + tableName + " to become ACTIVE...");
        try {
            Table table = dynamoDB.getTable(tableName);
            table.waitForActive();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void queryIndex(String indexName) {

        Table table = dynamoDB.getTable(tableName);

        System.out.println("\n***********************************************************\n");
        System.out.print("Querying index " + indexName + "...");

        Index index = table.getIndex(indexName);

        ItemCollection<QueryOutcome> items = null;

        QuerySpec querySpec = new QuerySpec();

        if (indexName == "CreateDateIndex") {
            System.out.println("Issues filed on 2013-11-01");
            querySpec.withKeyConditionExpression("CreateDate = :v_date and begins_with(IssueId, :v_issue)")
                    .withValueMap(new ValueMap().withString(":v_date", "2013-11-01").withString(":v_issue", "A-"));
            items = index.query(querySpec);
        } else if (indexName == "TitleIndex") {
            System.out.println("Compilation errors");
            querySpec.withKeyConditionExpression("Title = :v_title and begins_with(IssueId, :v_issue)")
                    .withValueMap(
                            new ValueMap().withString(":v_title", "Compilation error").withString(":v_issue", "A-"));
            items = index.query(querySpec);
        } else if (indexName == "DueDateIndex") {
            System.out.println("Items that are due on 2013-11-30");
            querySpec.withKeyConditionExpression("DueDate = :v_date")
                    .withValueMap(new ValueMap().withString(":v_date", "2013-11-30"));
            items = index.query(querySpec);
        } else {
            System.out.println("\nNo valid index name provided");
            return;
        }

        Iterator<Item> iterator = items.iterator();

        System.out.println("Query: printing results...");

        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }

    }

    public static void deleteTable(String tableName) {

        System.out.println("Deleting table " + tableName + "...");

        Table table = dynamoDB.getTable(tableName);
        table.delete();

        // Wait for table to be deleted
        System.out.println("Waiting for " + tableName + " to be deleted...");
        try {
            table.waitForDelete();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void loadData() {

        System.out.println("Loading data into table " + tableName + "...");

        // IssueId, Title,
        // Description,
        // CreateDate, LastUpdateDate, DueDate,
        // Priority, Status

        putItem("A-101", "Compilation error", "Can't compile Project X - bad version number. What does this mean?",
                "2013-11-01", "2013-11-02", "2013-11-10", 1, "Assigned");

        putItem("A-102", "Can't read data file", "The main data file is missing, or the permissions are incorrect",
                "2013-11-01", "2013-11-04", "2013-11-30", 2, "In progress");

        putItem("A-103", "Test failure", "Functional test of Project X produces errors", "2013-11-01", "2013-11-02",
                "2013-11-10", 1, "In progress");

        putItem("A-104", "Compilation error", "Variable 'messageCount' was not initialized.", "2013-11-15",
                "2013-11-16", "2013-11-30", 3, "Assigned");

        putItem("A-105", "Network issue", "Can't ping IP address 127.0.0.1. Please fix this.", "2013-11-15",
                "2013-11-16", "2013-11-19", 5, "Assigned");

    }

    public static void putItem(

            String issueId, String title, String description, String createDate, String lastUpdateDate, String dueDate,
            Integer priority, String status) {

        Table table = dynamoDB.getTable(tableName);

        Item item = new Item().withPrimaryKey("IssueId", issueId).withString("Title", title)
                .withString("Description", description).withString("CreateDate", createDate)
                .withString("LastUpdateDate", lastUpdateDate).withString("DueDate", dueDate)
                .withNumber("Priority", priority).withString("Status", status);

        table.putItem(item);
    }

}
```

# Arbeiten mit globalen sekundären Indizes: .NET
<a name="GSILowLevelDotNet"></a>

Sie können die AWS SDK für .NET Low-Level-API verwenden, um eine Amazon DynamoDB-Tabelle mit einem oder mehreren globalen Sekundärindizes zu erstellen, die Indizes in der Tabelle zu beschreiben und Abfragen mithilfe der Indizes durchzuführen. Diese Operationen entsprechen den entsprechenden DynamoDB-Operationen. Weitere Informationen finden Sie in der [Amazon-DynamoDB-API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/). 

Folgende sind die allgemeinen Schritte für Tabellenoperationen mithilfe der .NET-Low-Level-API. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie den erforderlichen und optionalen Parameter für die Operation bereit, indem Sie die entsprechenden Anforderungsobjekte erstellen.

   Erstellen Sie beispielsweise ein `CreateTableRequest`-Objekt, um eine Tabelle zu erstellen und ein `QueryRequest`-Objekt, um eine Tabelle oder einen Index abzufragen. 

1. Rufen Sie die entsprechende Methode auf, die vom Client, den Sie im vorhergehenden Schritt erstellt haben, bereitgestellt wird. 

**Topics**
+ [Erstellen einer Tabelle mit einem globalen sekundären Index](#GSILowLevelDotNet.CreateTableWithIndex)
+ [Beschreiben einer Tabelle mit einem globalen sekundären Index](#GSILowLevelDotNet.DescribeTableWithIndex)
+ [Abfragen eines globalen sekundären Indexes](#GSILowLevelDotNet.QueryAnIndex)
+ [Beispiel: Globale Sekundärindizes unter Verwendung der Low-Level-API AWS SDK für .NET](GSILowLevelDotNet.Example.md)

## Erstellen einer Tabelle mit einem globalen sekundären Index
<a name="GSILowLevelDotNet.CreateTableWithIndex"></a>

Sie können globale sekundäre Indizes gleichzeitig mit der Tabelle erstellen. Zu diesem Zweck verwenden Sie `CreateTable` und geben Ihre Spezifikationen für ein oder mehrere globale sekundäre Indizes an. Das folgende C\$1-Codebeispiel erstellt eine Tabelle, die Informationen über Wetterdaten enthält. Der Partitionsschlüssel ist `Location` und der Sortierschlüssel `Date`. Ein globaler sekundärer Index mit Namen `PrecipIndex` ermöglicht einen schnellen Zugriff auf Niederschlagsdaten für verschiedene Standorte.

Im Folgenden werden die Schritte zum Erstellen einer Tabelle mit einem globalen sekundären Index mithilfe der .NET-Low-Level-API dargelegt. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Erstellen Sie eine Instance der `CreateTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen. 

   Sie müssen den Tabellennamen, seinen zugehörigen Primärschlüssel und die Werte des bereitgestellten Durchsatzes angeben. Für den globalen sekundären Index müssen Sie den Indexnamen, seine Einstellungen des bereitgestellten Durchsatzes, die Attributdefinitionen für den Index, das Schlüsselschema für den Index und die Attributprojektion angeben.

1. Führen Sie die `CreateTable`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Erstellt eine Tabelle (`WeatherData`) mit einem globalen und lokalen sekundären Index (`PrecipIndex`). Der Index-Partitionsschlüssel ist `Date` und der Sortierschlüssel `Precipitation`. Alle Tabellenattribute werden in den Index projiziert. Benutzer können diesen Index abfragen, um Wetterdaten für ein bestimmtes Datum abzurufen. Optional können diese nach Niederschlagsmenge sortiert werden. 

Da es sich bei `Precipitation` um kein Schlüsselattribut für die Tabelle handelt, ist es nicht erforderlich. `WeatherData`-Elemente ohne `Precipitation` erscheinen jedoch nicht in `PrecipIndex`.

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

// Attribute definitions
var attributeDefinitions = new List<AttributeDefinition>()
{
    {new AttributeDefinition{
        AttributeName = "Location",
        AttributeType = "S"}},
    {new AttributeDefinition{
        AttributeName = "Date",
        AttributeType = "S"}},
    {new AttributeDefinition(){
        AttributeName = "Precipitation",
        AttributeType = "N"}
    }
};

// Table key schema
var tableKeySchema = new List<KeySchemaElement>()
{
    {new KeySchemaElement {
        AttributeName = "Location",
        KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement {
        AttributeName = "Date",
        KeyType = "RANGE"}  //Sort key
    }
};

// PrecipIndex
var precipIndex = new GlobalSecondaryIndex
{
    IndexName = "PrecipIndex",
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)10,
        WriteCapacityUnits = (long)1
    },
    Projection = new Projection { ProjectionType = "ALL" }
};

var indexKeySchema = new List<KeySchemaElement> {
    {new KeySchemaElement { AttributeName = "Date", KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement{AttributeName = "Precipitation",KeyType = "RANGE"}}  //Sort key
};

precipIndex.KeySchema = indexKeySchema;

CreateTableRequest createTableRequest = new CreateTableRequest
{
    TableName = tableName,
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)5,
        WriteCapacityUnits = (long)1
    },
    AttributeDefinitions = attributeDefinitions,
    KeySchema = tableKeySchema,
    GlobalSecondaryIndexes = { precipIndex }
};

CreateTableResponse response = client.CreateTable(createTableRequest);
Console.WriteLine(response.CreateTableResult.TableDescription.TableName);
Console.WriteLine(response.CreateTableResult.TableDescription.TableStatus);
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen.

## Beschreiben einer Tabelle mit einem globalen sekundären Index
<a name="GSILowLevelDotNet.DescribeTableWithIndex"></a>

Um Informationen zu globalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie `DescribeTable`. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

Im Folgenden werden die Schritte zum Zugriff auf globale sekundäre Index-Informationen in einer Tabelle mithilfe der .NET-Low-Level-API dargelegt. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Führen Sie die `describeTable`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

   Erstellen Sie eine Instance der `DescribeTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen. Sie müssen den Tabellennamen angeben.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest { TableName = tableName});

List<GlobalSecondaryIndexDescription> globalSecondaryIndexes =
response.DescribeTableResult.Table.GlobalSecondaryIndexes;

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.

foreach (GlobalSecondaryIndexDescription gsiDescription in globalSecondaryIndexes) {
     Console.WriteLine("Info for index " + gsiDescription.IndexName + ":");

     foreach (KeySchemaElement kse in gsiDescription.KeySchema) {
          Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType);
     }

      Projection projection = gsiDescription.Projection;
      Console.WriteLine("\tThe projection type is: " + projection.ProjectionType);

      if (projection.ProjectionType.ToString().Equals("INCLUDE")) {
           Console.WriteLine("\t\tThe non-key projected attributes are: "
                + projection.NonKeyAttributes);
      }
}
```

## Abfragen eines globalen sekundären Indexes
<a name="GSILowLevelDotNet.QueryAnIndex"></a>

Sie können `Query` für einen globalen sekundären Index genauso nutzen, wie Sie `Query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexpartitionsschlüssel und Sortierschlüssel (falls vorhanden) und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `PrecipIndex`, der über den Partitionsschlüssel `Date` und den Sortierschlüssel `Precipitation` verfügt. Die Indexabfrage gibt alle Wetterdaten für ein bestimmtes Datum zurück, in denen der Niederschlag größer als Null ist.

Im Folgenden werden die Schritte zur Abfrage eines globalen sekundären Indizes mithilfe der .NET-Low-Level-API dargelegt. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Erstellen Sie eine Instance der `QueryRequest`-Klasse, um die Anforderungsinformationen bereitzustellen.

1. Führen Sie die `query`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

Der Attributname `Date` ist ein DynamoDB-reserviertes Wort. Daher müssen Sie einen Ausdrucksattributnamen als Platzhalter in dem `KeyConditionExpression` verwenden.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
client = new AmazonDynamoDBClient();

QueryRequest queryRequest = new QueryRequest
{
    TableName = "WeatherData",
    IndexName = "PrecipIndex",
    KeyConditionExpression = "#dt = :v_date and Precipitation > :v_precip",
    ExpressionAttributeNames = new Dictionary<String, String> {
        {"#dt", "Date"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
        {":v_date", new AttributeValue { S =  "2013-08-01" }},
        {":v_precip", new AttributeValue { N =  "0" }}
    },
    ScanIndexForward = true
};

var result = client.Query(queryRequest);

var items = result.Items;
foreach (var currentItem in items)
{
    foreach (string attr in currentItem.Keys)
    {
        Console.Write(attr + "---> ");
        if (attr == "Precipitation")
        {
            Console.WriteLine(currentItem[attr].N);
    }
    else
    {
        Console.WriteLine(currentItem[attr].S);
    }

         }
     Console.WriteLine();
}
```

# Beispiel: Globale Sekundärindizes unter Verwendung der Low-Level-API AWS SDK für .NET
<a name="GSILowLevelDotNet.Example"></a>

Das folgende C\$1-Codebeispiel zeigt, wie Sie mit globalen sekundären Indizes arbeiten. Das Beispiel erstellt eine Tabelle mit dem Namen `Issues`, die in einem einfachen Fehlerüberwachungssystem für Softwareentwicklung verwendet werden könnte. Der Partitionsschlüssel ist `IssueId` und der Sortierschlüssel `Title`. Es gibt drei globale sekundäre Indizes in dieser Tabelle:
+ `CreateDateIndex` – Der Partitionsschlüssel ist `CreateDate` und der Sortierschlüssel `IssueId`. Zusätzlich zu den Tabellenschlüsseln werden die Attribute `Description` und `Status` in den Index projiziert.
+ `TitleIndex` – Der Partitionsschlüssel ist `Title` und der Sortierschlüssel `IssueId`. Keine anderen Attribute als die Tabellenschlüssel werden in den Index projiziert.
+ `DueDateIndex` — Der Partitionsschlüssel ist `DueDate`. Ein Sortierschlüssel ist nicht vorhanden.) Alle Tabellenattribute werden in den Index projiziert.

Nachdem die `Issues`-Tabelle erstellt wurde, lädt das Programm die Tabelle mit Daten, die Software-Fehlerberichte darstellen. Anschließend werden die Daten mithilfe der globalen sekundären Indizes abgefragt. Schließlich löscht das Programm die `Issues`-Tabelle.

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter. [.NET-Codebeispiele](CodeSamples.DotNet.md)

**Example**  

```
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class LowLevelGlobalSecondaryIndexExample
    {
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
        public static String tableName = "Issues";

        public static void Main(string[] args)
        {
            CreateTable();
            LoadData();

            QueryIndex("CreateDateIndex");
            QueryIndex("TitleIndex");
            QueryIndex("DueDateIndex");

            DeleteTable(tableName);

            Console.WriteLine("To continue, press enter");
            Console.Read();
        }

        private static void CreateTable()
        {
            // Attribute definitions
            var attributeDefinitions = new List<AttributeDefinition>()
        {
            {new AttributeDefinition {
                 AttributeName = "IssueId", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "Title", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "CreateDate", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "DueDate", AttributeType = "S"
             }}
        };

            // Key schema for table
            var tableKeySchema = new List<KeySchemaElement>() {
            {
                new KeySchemaElement {
                    AttributeName= "IssueId",
                    KeyType = "HASH" //Partition key
                }
            },
            {
                new KeySchemaElement {
                    AttributeName = "Title",
                    KeyType = "RANGE" //Sort key
                }
            }
        };

            // Initial provisioned throughput settings for the indexes
            var ptIndex = new ProvisionedThroughput
            {
                ReadCapacityUnits = 1L,
                WriteCapacityUnits = 1L
            };

            // CreateDateIndex
            var createDateIndex = new GlobalSecondaryIndex()
            {
                IndexName = "CreateDateIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "CreateDate", KeyType = "HASH" //Partition key
                },
                new KeySchemaElement {
                    AttributeName = "IssueId", KeyType = "RANGE" //Sort key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "INCLUDE",
                    NonKeyAttributes = {
                    "Description", "Status"
                }
                }
            };

            // TitleIndex
            var titleIndex = new GlobalSecondaryIndex()
            {
                IndexName = "TitleIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "Title", KeyType = "HASH" //Partition key
                },
                new KeySchemaElement {
                    AttributeName = "IssueId", KeyType = "RANGE" //Sort key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "KEYS_ONLY"
                }
            };

            // DueDateIndex
            var dueDateIndex = new GlobalSecondaryIndex()
            {
                IndexName = "DueDateIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "DueDate",
                    KeyType = "HASH" //Partition key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "ALL"
                }
            };



            var createTableRequest = new CreateTableRequest
            {
                TableName = tableName,
                ProvisionedThroughput = new ProvisionedThroughput
                {
                    ReadCapacityUnits = (long)1,
                    WriteCapacityUnits = (long)1
                },
                AttributeDefinitions = attributeDefinitions,
                KeySchema = tableKeySchema,
                GlobalSecondaryIndexes = {
                createDateIndex, titleIndex, dueDateIndex
            }
            };

            Console.WriteLine("Creating table " + tableName + "...");
            client.CreateTable(createTableRequest);

            WaitUntilTableReady(tableName);
        }

        private static void LoadData()
        {
            Console.WriteLine("Loading data into table " + tableName + "...");

            // IssueId, Title,
            // Description,
            // CreateDate, LastUpdateDate, DueDate,
            // Priority, Status

            putItem("A-101", "Compilation error",
                "Can't compile Project X - bad version number. What does this mean?",
                "2013-11-01", "2013-11-02", "2013-11-10",
                1, "Assigned");

            putItem("A-102", "Can't read data file",
                "The main data file is missing, or the permissions are incorrect",
                "2013-11-01", "2013-11-04", "2013-11-30",
                2, "In progress");

            putItem("A-103", "Test failure",
                "Functional test of Project X produces errors",
                "2013-11-01", "2013-11-02", "2013-11-10",
                1, "In progress");

            putItem("A-104", "Compilation error",
                "Variable 'messageCount' was not initialized.",
                "2013-11-15", "2013-11-16", "2013-11-30",
                3, "Assigned");

            putItem("A-105", "Network issue",
                "Can't ping IP address 127.0.0.1. Please fix this.",
                "2013-11-15", "2013-11-16", "2013-11-19",
                5, "Assigned");
        }

        private static void putItem(
            String issueId, String title,
            String description,
            String createDate, String lastUpdateDate, String dueDate,
            Int32 priority, String status)
        {
            Dictionary<String, AttributeValue> item = new Dictionary<string, AttributeValue>();

            item.Add("IssueId", new AttributeValue
            {
                S = issueId
            });
            item.Add("Title", new AttributeValue
            {
                S = title
            });
            item.Add("Description", new AttributeValue
            {
                S = description
            });
            item.Add("CreateDate", new AttributeValue
            {
                S = createDate
            });
            item.Add("LastUpdateDate", new AttributeValue
            {
                S = lastUpdateDate
            });
            item.Add("DueDate", new AttributeValue
            {
                S = dueDate
            });
            item.Add("Priority", new AttributeValue
            {
                N = priority.ToString()
            });
            item.Add("Status", new AttributeValue
            {
                S = status
            });

            try
            {
                client.PutItem(new PutItemRequest
                {
                    TableName = tableName,
                    Item = item
                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void QueryIndex(string indexName)
        {
            Console.WriteLine
                ("\n***********************************************************\n");
            Console.WriteLine("Querying index " + indexName + "...");

            QueryRequest queryRequest = new QueryRequest
            {
                TableName = tableName,
                IndexName = indexName,
                ScanIndexForward = true
            };


            String keyConditionExpression;
            Dictionary<string, AttributeValue> expressionAttributeValues = new Dictionary<string, AttributeValue>();

            if (indexName == "CreateDateIndex")
            {
                Console.WriteLine("Issues filed on 2013-11-01\n");

                keyConditionExpression = "CreateDate = :v_date and begins_with(IssueId, :v_issue)";
                expressionAttributeValues.Add(":v_date", new AttributeValue
                {
                    S = "2013-11-01"
                });
                expressionAttributeValues.Add(":v_issue", new AttributeValue
                {
                    S = "A-"
                });
            }
            else if (indexName == "TitleIndex")
            {
                Console.WriteLine("Compilation errors\n");

                keyConditionExpression = "Title = :v_title and begins_with(IssueId, :v_issue)";
                expressionAttributeValues.Add(":v_title", new AttributeValue
                {
                    S = "Compilation error"
                });
                expressionAttributeValues.Add(":v_issue", new AttributeValue
                {
                    S = "A-"
                });

                // Select
                queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES";
            }
            else if (indexName == "DueDateIndex")
            {
                Console.WriteLine("Items that are due on 2013-11-30\n");

                keyConditionExpression = "DueDate = :v_date";
                expressionAttributeValues.Add(":v_date", new AttributeValue
                {
                    S = "2013-11-30"
                });

                // Select
                queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES";
            }
            else
            {
                Console.WriteLine("\nNo valid index name provided");
                return;
            }

            queryRequest.KeyConditionExpression = keyConditionExpression;
            queryRequest.ExpressionAttributeValues = expressionAttributeValues;

            var result = client.Query(queryRequest);
            var items = result.Items;
            foreach (var currentItem in items)
            {
                foreach (string attr in currentItem.Keys)
                {
                    if (attr == "Priority")
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].N);
                    }
                    else
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].S);
                    }
                }
                Console.WriteLine();
            }
        }

        private static void DeleteTable(string tableName)
        {
            Console.WriteLine("Deleting table " + tableName + "...");
            client.DeleteTable(new DeleteTableRequest
            {
                TableName = tableName
            });
            WaitForTableToBeDeleted(tableName);
        }

        private static void WaitUntilTableReady(string tableName)
        {
            string status = null;
            // Let us wait until table is created. Call DescribeTable.
            do
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                    status = res.Table.TableStatus;
                }
                catch (ResourceNotFoundException)
                {
                    // DescribeTable is eventually consistent. So you might
                    // get resource not found. So we handle the potential exception.
                }
            } while (status != "ACTIVE");
        }

        private static void WaitForTableToBeDeleted(string tableName)
        {
            bool tablePresent = true;

            while (tablePresent)
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                }
                catch (ResourceNotFoundException)
                {
                    tablePresent = false;
                }
            }
        }
    }
}
```

# Arbeiten mit globalen sekundären Indizes in DynamoDB mithilfe der AWS CLI
<a name="GCICli"></a>

Sie können die AWS CLI zum Erstellen einer Amazon-DynamoDB-Tabelle mit einem oder mehreren globalen sekundären Indizes, zum Beschreiben der Indizes in der Tabelle und zur Ausführung von Abfragen mithilfe des Indizes, verwenden.

**Topics**
+ [Erstellen einer Tabelle mit einem globalen sekundären Index](#GCICli.CreateTableWithIndex)
+ [Hinzufügen eines globalen sekundären Indexes zu einer vorhandenen Tabelle](#GCICli.CreateIndexAfterTable)
+ [Beschreiben einer Tabelle mit einem globalen sekundären Index](#GCICli.DescribeTableWithIndex)
+ [Abfragen eines globalen sekundären Indexes](#GCICli.QueryAnIndex)

## Erstellen einer Tabelle mit einem globalen sekundären Index
<a name="GCICli.CreateTableWithIndex"></a>

Globale sekundäre Indizes können gleichzeitig mit der Tabelle erstellt werden. Zu diesem Zweck verwenden Sie den `create-table`-Parameter und geben Ihre Spezifikationen für ein oder mehrere globale sekundäre Indizes an. Im folgenden Beispiel wird eine Tabelle mit dem Namen `GameScores` mit einem globalen sekundären Index `GameTitleIndex` erstellt. Die Basistabelle hat einen Partitionsschlüssel von `UserId` und einen Sortierschlüssel von `GameTitle`, mit dem Sie effizient die beste Punktzahl eines einzelnen Benutzers für ein bestimmtes Spiel finden können, während die GSI einen Partitionsschlüssel von `GameTitle` und einen Sortierschlüssel von `TopScore` hat, mit dem Sie finden Sie schnell die höchste Gesamtpunktzahl für ein bestimmtes Spiel.

```
aws dynamodb create-table \
    --table-name GameScores \
    --attribute-definitions AttributeName=UserId,AttributeType=S \
                            AttributeName=GameTitle,AttributeType=S \
                            AttributeName=TopScore,AttributeType=N  \
    --key-schema AttributeName=UserId,KeyType=HASH \
                 AttributeName=GameTitle,KeyType=RANGE \
    --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --global-secondary-indexes \
        "[
            {
                \"IndexName\": \"GameTitleIndex\",
                \"KeySchema\": [{\"AttributeName\":\"GameTitle\",\"KeyType\":\"HASH\"},
                                {\"AttributeName\":\"TopScore\",\"KeyType\":\"RANGE\"}],
                \"Projection\":{
                    \"ProjectionType\":\"INCLUDE\",
                    \"NonKeyAttributes\":[\"UserId\"]
                },
                \"ProvisionedThroughput\": {
                    \"ReadCapacityUnits\": 10,
                    \"WriteCapacityUnits\": 5
                }
            }
        ]"
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen. Mit [describe-table](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/describe-table.html) können Sie den Status der Tabellenerstellung ermitteln.

## Hinzufügen eines globalen sekundären Indexes zu einer vorhandenen Tabelle
<a name="GCICli.CreateIndexAfterTable"></a>

Globale sekundäre Indizes können auch nach der Tabellenerstellung hinzugefügt oder geändert werden. Zu diesem Zweck verwenden Sie den `update-table`-Parameter und geben Ihre Spezifikationen für ein oder mehrere globale sekundäre Indizes an. Im folgenden Beispiel wird dasselbe Schema wie im vorherigen Beispiel verwendet, es wird jedoch davon ausgegangen, dass die Tabelle bereits erstellt wurde und die GSI später hinzugefügt wird.

```
aws dynamodb update-table \
    --table-name GameScores \
    --attribute-definitions AttributeName=TopScore,AttributeType=N  \
    --global-secondary-index-updates \
        "[
            {
                \"Create\": {
                    \"IndexName\": \"GameTitleIndex\",
                    \"KeySchema\": [{\"AttributeName\":\"GameTitle\",\"KeyType\":\"HASH\"},
                                    {\"AttributeName\":\"TopScore\",\"KeyType\":\"RANGE\"}],
                    \"Projection\":{
                        \"ProjectionType\":\"INCLUDE\",
                        \"NonKeyAttributes\":[\"UserId\"]
                    }
                }
            }
        ]"
```

## Beschreiben einer Tabelle mit einem globalen sekundären Index
<a name="GCICli.DescribeTableWithIndex"></a>

Um Informationen zu globalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie den Parameter `describe-table`. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

```
aws dynamodb describe-table --table-name GameScores
```

## Abfragen eines globalen sekundären Indexes
<a name="GCICli.QueryAnIndex"></a>

Sie können die Operation `query` für einen globalen sekundären Index genauso nutzen, wie Sie `query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexsortierschlüssel und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `GameTitleIndex` und der Indexsortierschlüssel `GameTitle`.

Die einzigen zurückgegebenen Attribute sind die, die in den Index projiziert wurden. Sie könnten diese Abfrage ändern, um auch Nicht-Schlüsselattribute auszuwählen, aber dies würde eine Tabellenabrufaktivität erfordern, die relativ teuer ist. Weitere Informationen zum Abrufen von Tabellen finden Sie unter [Attributprojektionen](GSI.md#GSI.Projections).

```
aws dynamodb query --table-name GameScores\
    --index-name GameTitleIndex \
    --key-condition-expression "GameTitle = :v_game" \
    --expression-attribute-values '{":v_game":{"S":"Alien Adventure"} }'
```

# Lokale sekundäre Indizes
<a name="LSI"></a>

Einige Anwendungen müssen Daten nur mithilfe der Basistabelle des Primärschlüssels abfragen. Es kann jedoch Situationen geben, in denen ein alternativer Sortierschlüssel hilfreich wäre. Um Ihrer Anwendung verschiedene Sortierschlüssel zur Auswahl anzubieten, können Sie einen oder mehrere lokale sekundäre Indizes in einer Amazon-DynamoDB-Tabelle erstellen und `Query`- oder `Scan`-Anforderungen für diese Indizes generieren.

**Topics**
+ [Schritt 6: Verwenden eines lokalenx sekundären Indexes](#LSI.Scenario)
+ [Attributprojektionen](#LSI.Projections)
+ [Erstellen eines lokalen sekundären Index](#LSI.Creating)
+ [Lesen von Daten aus einem lokalen sekundären Index](#LSI.Reading)
+ [Schreibvorgänge und lokale sekundäre Indizes](#LSI.Writes)
+ [Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für lokale sekundäre Indizes](#LSI.ThroughputConsiderations)
+ [Speicherüberlegungen für lokale sekundäre Indizes](#LSI.StorageConsiderations)
+ [Elementauflistungen in lokalen sekundären Indizes](#LSI.ItemCollections)
+ [Arbeiten mit lokalen sekundären Indizes: Java](LSIJavaDocumentAPI.md)
+ [Arbeiten mit lokalen sekundären Indizes: .NET](LSILowLevelDotNet.md)
+ [Arbeiten mit lokalen sekundären Indizes in der DynamoDB-AWS CLI](LCICli.md)

## Schritt 6: Verwenden eines lokalenx sekundären Indexes
<a name="LSI.Scenario"></a>

Betrachten Sie als Beispiel die `Thread`-Tabelle. Diese Tabelle ist nützlich für eine Anwendung wie [AWS -Diskussionsforen](https://forums.aws.amazon.com/). Das folgende Diagramm zeigt, wie die Elemente in der Tabelle organisiert wären. (Es werden nicht alle Attribute angezeigt.)

![\[Thread-Tabelle mit einer Liste von Forumnamen, Themen, Uhrzeit des letzten Beitrags und Anzahl der Antworten.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/LSI_01.png)


DynamoDB speichert alle Elemente mit demselben Partitionsschlüsselwert fortlaufend. In diesem Beispiel könnte mit einem bestimmten `ForumName` eine `Query`-Operation sofort alle Threads für dieses Forum ermitteln. Innerhalb einer Gruppe von Elementen mit demselben Partitionsschlüsselwert werden die Elemente nach Sortierschlüsselwert sortiert. Wenn der Sortierschlüssel (`Subject`) in der Abfrage auch angegeben ist, kann DynamoDB die Ergebnisse, die zurückgegeben werden, einschränken und z. B. alle Threads im Forum „S3“ mit einem `Subject`, der mit „A“ beginnt, zurückgeben.

Einige Anforderungen erfordern komplexere Datenzugriffsmuster. Zum Beispiel:
+ Welche Forum-Threads erhalten die meisten Ansichten und Antworten?
+ Welcher Thread in einem bestimmten Forum enthält die meisten Nachrichten?
+ Wie viele Threads wurden in einem bestimmten Forum in einem angegebenen Zeitraum gepostet?

Um diese Fragen zu beantworten, würde die `Query`-Aktion nicht ausreichen. Stattdessen müssen Sie die gesamte Tabelle `Scan`. Bei einer Tabelle mit Millionen von Elementen würde dabei der bereitgestellte Lesedurchsatz größtenteils aufgebraucht und der Vorgang würde sehr lange dauern.

Sie können jedoch einen oder mehrere lokale sekundäre Indizes für Nicht-Schlüsselattribute angeben, z. B. `Replies` oder `LastPostDateTime`.

Ein *lokaler sekundärer Index* verwaltet einen alternativen Sortierschlüssel für einen bestimmten Partitionsschlüsselwert. Ein lokaler sekundärer Index enthält auch eine Kopie einiger oder aller Attribute aus seiner Basistabelle. Sie geben beim Erstellen der Tabelle an, welche Attribute in den lokalen sekundären Index projiziert werden. Die Daten in einem lokalen sekundären Index werden durch denselben Partitionsschlüssel strukturiert wie die Basistabelle, jedoch mit einem anderen Sortierschlüssel. Auf diese Weise können Sie in dieser anderen Dimension effizient auf Datenelemente zugreifen. Wenn Sie eine größere Abfrage- oder Scanflexibilität benötigen, können Sie bis zu fünf lokale sekundäre Indizes pro Tabelle erstellen. 

Angenommen, eine Anwendung muss alle Threads ermitteln, die in den letzten drei Monaten in einem bestimmten Forum veröffentlicht wurden. Ohne lokalen sekundären Index müsste die Anwendung eine `Scan`-Aktion für die gesamte `Thread`-Tabelle ausführen und alle Beiträge, die nicht innerhalb des Zeitraums gepostet wurden, verwerfen. Mit einem lokalen sekundären Index könnte eine `Query`-Operation `LastPostDateTime` verwenden, um Daten schnell zu finden.

Das folgende Diagramm zeigt einen lokalen sekundären Index mit dem Namen `LastPostIndex`. Beachten Sie, dass der Partitionsschlüssel mit dem Schlüssel der `Thread`-Tabelle übereinstimmt, der Sortierschlüssel jedoch `LastPostDateTime` ist.

![\[LastPostIndex Tabelle mit einer Liste von Forennamen, Themen und der Zeit des letzten Beitrags.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/LSI_02.png)


Jeder lokale sekundäre Index muss die folgenden Bedingungen erfüllen:
+ Der Partitionsschlüssel ist mit dem Schlüssel der Basistabelle identisch.
+ Der Sortierschlüssel besteht aus genau einem skalaren Attribut.
+ Der Sortierschlüssel der Basistabelle wird in den Index projiziert, wo er als Nicht-Schlüsselattribut fungiert.

In diesem Beispiel lautet der Partitionsschlüssel `ForumName` und der Sortierschlüssel des lokalen sekundären Indexes lautet `LastPostDateTime`. Darüber hinaus wird der Sortierschlüsselwert der Basistabelle (in diesem Beispiel `Subject`) in den Index projiziert, ist jedoch kein Bestandteil des Indexschlüssels. Wenn eine Anwendung eine Liste basierend auf `ForumName` und `LastPostDateTime` benötigt, kann sie eine `Query`-Anforderung für `LastPostIndex` erstellen. Die Abfrageergebnisse sind nach `LastPostDateTime` sortiert und können in auf- oder absteigender Reihenfolge zurückgegeben werden. Die Abfrage kann auch Schlüsselbedingungen anwenden, z. B. nur Elemente zurückgeben mit einem `LastPostDateTime` innerhalb einer bestimmten Zeitspanne.

Jeder lokale sekundäre Index enthält automatisch die Partitions- und Sortierschlüssel der Basistabelle. Nicht-Schlüsselattribute können Sie optional in den Index projizieren. Wenn Sie den Index abfragen, kann DynamoDB diese projizierten Attribute effizient abrufen. Beim Abfragen eines lokalen sekundären Indizes können auch Attribute abgerufen werden, die *nicht* in den Index projiziert sind. DynamoDB ruft diese Attribute automatisch aus der Basistabelle ab, jedoch mit größerer Latenz und höheren Kosten für den bereitgestellten Durchsatz.

Für alle lokale sekundäre Indizes können Sie bis zu 10 GB Daten pro eindeutigem Partitionsschlüsselwert speichern. Diese Abbildung enthält alle Elemente in der Basistabelle sowie alle Elemente in den Indizes, die denselben Partitionsschlüsselwert haben. Weitere Informationen finden Sie unter [Elementauflistungen in lokalen sekundären Indizes](#LSI.ItemCollections).

## Attributprojektionen
<a name="LSI.Projections"></a>

Mit `LastPostIndex` könnte eine Anwendung `ForumName` und `LastPostDateTime` als Abfragekriterien verwenden. Um jedoch zusätzliche Attribute abzurufen, muss DynamoDB zusätzliche Lesevorgänge für die `Thread`-Tabelle ausführen. Diese zusätzlichen Lesevorgänge werden als *Abrufe* bezeichnet. Diese können die Gesamtgröße des bereitgestellten Durchsatzes, der für eine Abfrage erforderlich ist, erhöhen.

Angenommen, Sie möchten eine Webseite mit einer Liste aller Threads in „S3“ und der Anzahl der Antworten für jeden Thread füllen, sortiert nach der letzten Antwort, date/time beginnend mit der neuesten Antwort. Zum Auffüllen dieser Liste benötigen Sie die folgenden Attribute:
+ `Subject`
+ `Replies`
+ `LastPostDateTime`

Die beste Möglichkeit, diese Daten abzufragen und Abrufoperationen zu vermeiden, ist, das Attribut `Replies` aus der Tabelle in den lokalen sekundären Index zu projizieren, wie in diesem Diagramm dargestellt:

![\[LastPostIndex Tabelle mit einer Liste von Forennamen, Zeiten der letzten Beiträge, Themen und Antworten.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/LSI_03.png)




Eine *Projektion* ist der Satz von Attributen, die aus einer Tabelle in einen sekundären Index kopiert werden. Der Partitionsschlüssel und der Sortierschlüssel der Tabelle werden immer in den Index projiziert. Sie können andere Attribute projizieren, um die Abfrageanforderungen Ihrer Anwendung zu unterstützen. Wenn Sie einen Index abfragen, kann Amazon DynamoDB auf jedes Attribut in der Projektion zugreifen, als ob sich diese Attribute in einer eigenen Tabelle befinden.

Wenn Sie einen sekundären Index erstellen, müssen Sie die Attribute angeben, die in den Index projiziert werden. DynamoDB bietet hierfür drei verschiedene Optionen:
+ *KEYS\$1ONLY* – Jeder Eintrag im Index besteht nur aus dem Tabellenpartitionsschlüssel und Sortierschlüsselwerten, sowie den Indexschlüsselwerten. Die Option `KEYS_ONLY` führt zu dem kleinstmöglichen sekundären Index.
+ *INCLUDE* – Zusätzlich zu den in `KEYS_ONLY` beschriebenen Attributen, enthält der sekundäre Index andere Nicht-Schlüsselattribute, die Sie angeben.
+ *ALL* – Der sekundäre Index enthält alle Attribute der Quelltabelle. Da alle Tabellendaten im Index dupliziert werden, wird führt eine `ALL`-Projektion zu dem größtmöglichen sekundären Index.

Im vorherigen Diagramm wird das Nicht-Schlüsselattribut in `Replies` in `LastPostIndex` projiziert. Eine Anwendung kann `LastPostIndex` anstelle der vollständigen `Thread`-Tabelle abfragen, um eine Webseite mi t`Subject`, `Replies` und `LastPostDateTime` auszufüllen. Wenn alle anderen Nicht-Schlüsselattribute abgefragt werden, muss DynamoDB diese Attribute aus der `Thread`-Tabelle abrufen. 

Von der Anwendungsseite aus betrachtet, ist das Abrufen zusätzlicher Attribute aus der Basistabelle automatisch und transparent. Es muss keine Anwendungslogik umgeschrieben werden. Beachten Sie jedoch, dass dieses Abrufen den Leistungsvorteil, den ein lokaler sekundärer Index bietet, erheblich einschränken kann.

Wenn Sie die Attribute zum Projizieren in einen lokalen sekundären Index auswählen, müssen Sie die Differenz der Kosten des bereitgestellten Durchsatzes und der Speicherkosten berücksichtigen:
+ Wenn Sie nur auf wenige Attribute mit möglichst niedriger Latenz zugreifen müssen, erwägen Sie, nur diese Attribute in einen lokalen sekundären Index zu projizieren. Je kleiner der Index, desto geringer die Speicher- und somit die Schreibkosten. Wenn Sie Attribute gelegentlich abrufen müssen, können die Kosten für den bereitgestellten Durchsatz die längerfristigen Kosten für die Speicherung dieser Attribute aufwiegen.
+ Greift Ihre Anwendung häufig auf einige Nicht-Schlüsselattribute zu, sollten Sie erwägen, diese Attribute in einen lokalen sekundären Index zu projizieren. Die zusätzlichen Speicherkosten für den lokalen sekundären Index wiegen die Kosten für die Durchführung häufiger Tabellen-Scans auf.
+ Wenn Sie auf die meisten Nicht-Schlüsselattribute in regelmäßigen Abständen zugreifen müssen, können Sie diese Attribute – oder sogar die gesamte Basistabelle – in einen lokalen sekundären Index projizieren. Auf diese Weise erhalten Sie maximale Flexibilität und den niedrigsten Verbrauch des bereitgestellten Durchsatzes, da kein Abrufen erforderlich ist. Die Speicherkosten erhöhen oder verdoppeln sich allerdings sogar, wenn Sie alle Attribute projizieren.
+ Wenn Ihre Anwendung eine Tabelle selten abfragen, jedoch viele Schreibvorgänge oder Updates für die Daten in der Tabelle durchführen muss, erwägen Sie das Projizieren von *KEYS\$1ONLY*. Der wäre nur klein, stünde aber weiterhin bei Bedarf für Abfrageaktivitäten zur Verfügung. 

## Erstellen eines lokalen sekundären Index
<a name="LSI.Creating"></a>

Um einen oder mehrere lokale sekundäre Indizes für eine Tabelle zu erstellen, verwenden Sie den `LocalSecondaryIndexes`-Parameter der Operation `CreateTable`. Lokale sekundäre Indizes für eine Tabelle werden erstellt, wenn die Tabelle erstellt wird. Wenn Sie eine Tabelle löschen, werden alle lokalen sekundären Indizes in dieser Tabelle ebenfalls gelöscht.

Sie müssen ein Nicht-Schlüsselattribut angeben, das als Sortierschlüssel des lokalen sekundären Indizes dient. Das Attribut, das Sie auswählen, muss ein skalarer `String`, `Number` oder `Binary` sein. Andere Skalar-, Dokument- und Satztypen sind nicht zulässig. Eine vollständige Liste der Datentypen finden Sie unter [Datentypen](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes).

**Wichtig**  
Für Tabellen mit lokalen sekundären Indizes besteht eine Größenbeschränkung von 10 GB pro Partitionsschlüsselwert. Eine Tabelle mit lokalem sekundärem Index kann eine beliebige Anzahl von Elementen speichern, solange die Gesamtgröße eines Partitionsschlüsselwerts 10 GB nicht überschreitet. Weitere Informationen finden Sie unter [Größenlimit der Elementauflistung](#LSI.ItemCollections.SizeLimit).

Sie können Attribute jeden Datentyps in einen lokalen sekundären Index projizieren. Dazu zählen skalare Werte, Dokumente und Sätze. Eine vollständige Liste der Datentypen finden Sie unter [Datentypen](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes).

## Lesen von Daten aus einem lokalen sekundären Index
<a name="LSI.Reading"></a>

Sie können Elemente aus einem lokalen sekundären Index mit dem Befehl `Query` und `Scan` verwenden. Die `GetItem`- und `BatchGetItem`-Operationen können für einen lokalen sekundären Index nicht verwendet werden.

### Abfragen eines lokalen sekundären Indexes
<a name="LSI.Querying"></a>

In einer DynamoDB-Tabelle müssen der kombinierte Partitionsschlüsselwert und der Sortierschlüsselwert für jedes Element eindeutig sein. In einem lokalen sekundären Index müssen die Sortierschlüsselwerte für einen bestimmten Partitionsschlüsselwert jedoch nicht eindeutig sein. Wenn mehrere Elemente mit demselben Sortierschlüsselwert im lokalen sekundären Index vorhanden sind, gibt eine `Query`-Operation alle Elemente mit demselben Partitionsschlüsselwert zurück. In der Antwort werden die übereinstimmenden Elemente nicht in einer bestimmten Reihenfolge zurückgegeben.

Sie können einen lokalen sekundären Index mit Eventually-Consistent- oder Strongly-Consistent-Lesevorgängen abfragen. Um die Art der Konsistenz anzugeben, verwenden Sie den Parameter `ConsistentRead` der `Query`-Operation. Bei einem Strongly-Consistent-Lesevorgang von einem lokalen sekundären Index werden immer die zuletzt aktualisierten Werte zurückgegeben. Wenn die Abfrage weitere Attribute aus der Basistabelle abrufen muss, sind diese Attribute in Bezug auf den Index konsistent.

**Example**  
Betrachten Sie die folgenden Daten, die von einer `Query`-Operation zum Abfragen von Daten aus den Diskussionsbeiträgen in einem bestimmten Forum zurückgegeben werden:  

```
{
    "TableName": "Thread",
    "IndexName": "LastPostIndex",
    "ConsistentRead": false,
    "ProjectionExpression": "Subject, LastPostDateTime, Replies, Tags",
    "KeyConditionExpression": 
        "ForumName = :v_forum and LastPostDateTime between :v_start and :v_end",
    "ExpressionAttributeValues": {
        ":v_start": {"S": "2015-08-31T00:00:00.000Z"},
        ":v_end": {"S": "2015-11-31T00:00:00.000Z"},
        ":v_forum": {"S": "EC2"}
    }
}
```
Vorgänge in dieser Abfrage:  
+ DynamoDB greift auf `LastPostIndex` mit dem Partitionsschlüssel `ForumName` zu, um die Indexelemente für „EC2“ zu ermitteln. Alle Indexelemente mit diesem Schlüssel werden nebeneinander gespeichert, um ein schnelles Abrufen zu ermöglichen.
+ In diesem Forum verwendet DynamoDB den Index, um die Schlüssel, die der angegebenen `LastPostDateTime`-Bedingung entsprechen, zu suchen.
+ Da das Attribut `Replies` in den Index projiziert wird, kann DynamoDB dieses Attribut abrufen, ohne zusätzlichen bereitgestellten Durchsatz zu verbrauchen.
+ Das Attribut `Tags` wird nicht in den Index projiziert, sodass DynamoDB auf die `Thread`-Tabelle zugreifen muss, um dieses Attribut abzurufen.
+ Die Ergebnisse werden sortiert nach `LastPostDateTime`. Die Indexeinträge sind nach Partitionsschlüsselwert und dann nach Sortierschlüsselwert sortiert und `Query` gibt sie in der Reihenfolge, in der sie gespeichert werden, zurück. (Sie können den Parameter `ScanIndexForward` verwenden, um die Ergebnisse in absteigender Reihenfolge anzuzeigen.)
Da das Attribut `Tags` nicht in den lokalen sekundären Index projiziert wird, muss DynamoDB zusätzliche Lesekapazitätseinheiten verbrauchen, um dieses Attribut aus der Basistabelle abzurufen. Wenn Sie diese Abfrage häufig ausführen müssen, sollten Sie `Tags` in `LastPostIndex` verwenden, um das Abrufen von der Basistabelle zu vermeiden. Wenn Sie jedoch nur gelegentlich auf `Tags` zugreifen müssen, lohnen sich die zusätzlichen Speicherkosten für das Projizieren von `Tags` in den Index möglicherweise nicht.

### Scannen eines lokalen sekundären Indexes
<a name="LSI.Scanning"></a>

Sie können `Scan` verwenden, um alle Daten aus einem lokalen sekundären Index abzurufen. Geben Sie dazu den Namen der Basistabelle sowie den Indexnamen in der Abfrage an. Mit einer `Scan`-Operation liest DynamoDB alle Daten im Index und gibt sie an die Anwendung zurück. Sie können auch anfordern, dass nur einige der Daten zurückgegeben und die verbleibenden Daten verworfen werden. Verwenden Sie dazu den Parameter `FilterExpression` der `Scan`-API. Weitere Informationen finden Sie unter [Filterausdrücke für Scan](Scan.md#Scan.FilterExpression).

## Schreibvorgänge und lokale sekundäre Indizes
<a name="LSI.Writes"></a>

DynamoDB synchronisiert automatisch alle lokalen sekundären Indizes mit ihren jeweiligen Basistabellen. Anwendungen schreiben niemals direkt in einen Index. Allerdings ist es wichtig, zu wissen, welche Auswirkungen es hat, wie DynamoDB diese Indizes verwaltet.

Beim Erstellen eines lokalen sekundären Indizes geben Sie ein Attribut als Sortierschlüssel für den Index an. Außerdem bestimmen Sie einen Datentyp für dieses Attribut. Das bedeutet, dass wenn Sie ein Element in die Basistabelle schreiben und das Element ein Indexschlüsselattribut definiert, der entsprechende Typ dem Datentyp des Indexschlüsselschemas entsprechen muss. Im Fall von `LastPostIndex` wird der Sortierschlüssel `LastPostDateTime` im Index als Datentyp `String` definiert. Wenn Sie versuchen, der Tabelle `Thread` ein Element hinzuzufügen und einen anderen Datentyp für `LastPostDateTime` (wie z. B. `Number`) anzugeben, gibt DynamoDB eine `ValidationException` aufgrund der fehlenden Übereinstimmung des Datentyps zurück.

Es ist keine one-to-one Beziehung zwischen den Elementen in einer Basistabelle und den Elementen in einem lokalen sekundären Index erforderlich. In der Tat kann dieses Verhalten für viele Anwendungen vorteilhaft sein. 

Eine Tabelle mit vielen lokalen sekundären Indizes verursacht höhere Kosten für Schreibaktivitäten als Tabellen mit weniger Indizes. Weitere Informationen finden Sie unter [Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für lokale sekundäre Indizes](#LSI.ThroughputConsiderations).

**Wichtig**  
Für Tabellen mit lokalen sekundären Indizes besteht eine Größenbeschränkung von 10 GB pro Partitionsschlüsselwert. Eine Tabelle mit lokalem sekundärem Index kann eine beliebige Anzahl von Elementen speichern, solange die Gesamtgröße eines Partitionsschlüsselwerts 10 GB nicht überschreitet. Weitere Informationen finden Sie unter [Größenlimit der Elementauflistung](#LSI.ItemCollections.SizeLimit).

## Überlegungen im Hinblick auf die bereitgestellte Durchsatzkapazität für lokale sekundäre Indizes
<a name="LSI.ThroughputConsiderations"></a>

Wenn Sie eine Tabelle in DynamoDB erstellen, stellen Sie Lese- und Schreibkapazitätseinheiten für den erwarteten Workload der Tabelle bereit. Dieser Workload umfasst Lese- und Schreibaktivitäten in den lokalen sekundären Indizes der Tabelle.

Die aktuellen Preise für die bereitgestellte Durchsatzkapazität finden Sie unter [Amazon-DynamoDB-Preise](https://aws.amazon.com/dynamodb/pricing).

### Lesekapazitätseinheiten
<a name="LSI.ThroughputConsiderations.Reads"></a>

Wenn Sie einen lokalen sekundären Index abfragen, hängt die Anzahl der verbrauchten Lesekapazitätseinheiten davon ab, wie auf die Daten zugegriffen wird.

Ähnlich wie Tabellenabfragen kann eine Indexabfrage auch entweder Eventually-Consistent- oder Strongly-Consistent-Lesevorgänge abhängig vom Wert `ConsistentRead` verwenden. Ein Strongly-Consistent-Lesevorgang belegt eine Lesekapazitätseinheit, ein Eventually-Consistent-Lesevorgang verbraucht nur die Hälfte. Daher können Sie Ihre Kosten für Lesekapazitätseinheiten durch Auswählen von Eventually Consistent-Lesevorgängen reduzieren.

Für Indexabfragen, die nur Indexschlüssel und projizierte Attribute anfordern, berechnet DynamoDB die bereitgestellten Leseaktivitäten auf die gleiche Weise wie für Tabellenabfragen. Der einzige Unterschied besteht darin, dass die Berechnung auf der Größe der Indexeinträge und nicht auf der Größe des Elements in der Basistabelle beruht. Die Anzahl der Lesekapazitätseinheiten ist die Summe aller projizierten Attributgrößen sämtlicher zurückgegebener Elemente. Das Ergebnis wird dann auf den nächsten 4 KB-Grenzwert aufgerundet. Weitere Informationen darüber, wie DynamoDB die bereitgestellte Durchsatznutzung berechnet, finden Sie unter [DynamoDB – Modus mit bereitgestellter Kapazität](provisioned-capacity-mode.md).

Bei Indexabfragen, die Attribute lesen, die nicht in den lokalen sekundären Index projiziert werden, muss DynamoDB diese Attribute zusätzlich zum Lesen der projizierten Attribute aus dem Index aus der Basistabelle abrufen. Diese Abrufe treten auf, wenn Sie nicht projizierte Attribute in die Parameter `Select` oder `ProjectionExpression` der `Query`-Operation einbeziehen. Das Abrufen verursacht zusätzliche Latenz bei Abfrageantworten und verursacht auch höhere Kosten für den bereitgestellten Durchsatz: Zusätzlich zu den zuvor beschriebenen Lesevorgängen aus dem lokalen sekundären Index werden Ihnen Lesekapazitätseinheiten für jedes abgerufene Basistabellenelement in Rechnung gestellt. Diese Kosten fallen nicht nur für die angeforderten Attribute an, sondern für jedes Element, das aus der Tabelle gelesen wird.

Die maximale Größe der von einer `Query`-Operation zurückgegebenen Ergebnisse beträgt 1 MB. Diese umfasst die Größen aller Attributnamen und Werte sämtlicher zurückgegebenen Elemente. Wenn jedoch eine Abfrage für einen lokalen sekundären Index veranlasst, dass DynamoDB Elementattribute aus der Basistabelle abruft, kann die maximale Größe der Daten in den Ergebnissen niedriger sein. In diesem Fall setzt sich die Ergebnisgröße aus folgender Summe zusammen:
+ Die Größe der übereinstimmenden Elemente im Index wird auf die nächste 4 KB aufgerundet.
+ Die Größe der einzelnen übereinstimmenden Elemente in der Basistabelle wird für jedes einzelne Element auf die nächste 4 KB aufgerundet.

Mit dieser Formel beträgt die maximale Größe der von einer Abfrageoperation zurückgegebenen Ergebnisse 1 MB.

Nehmen wir als Beispiel eine Tabelle, in der die Größe jedes Element 300 Byte beträgt. Es gibt einen lokalen sekundären Index in dieser Tabelle, aber nur 200 Byte pro Element werden in den Index projiziert. Angenommen, Sie führen eine `Query`-Operation für diesen Index aus, die Abfrage erfordert Tabellenabrufe für jedes Element und die Abfrage gibt vier Elemente zurück. DynamoDB fasst Folgendes zusammen:
+ Die Größe der übereinstimmenden Elemente im Index: 200 Byte × 4 Elemente = 800 Byte. Dieser Wert wird dann auf 4 KB aufgerundet.
+ Die Größe der einzelnen übereinstimmenden Elemente in der Basistabelle: (300 Byte, auf 4 KB aufgerundet) × 4 Elemente = 16 KB.

Die Gesamtgröße der Daten im Ergebnis beträgt somit 20 KB.

### Schreibkapazitätseinheiten
<a name="LSI.ThroughputConsiderations.Writes"></a>

Wenn ein Element in einer Tabelle hinzugefügt, aktualisiert oder gelöscht wird, verbraucht die Aktualisierung der lokalen sekundären Indizes bereitgestellte Schreibkapazitätseinheiten für die Tabelle. Die gesamten bereitgestellten Durchsatzkosten für einen Schreibvorgang sind die Summe der Schreibkapazitätseinheiten, die durch das Schreiben in die Tabelle verbraucht werden, und denjenigen, die durch die Aktualisierung der lokalen sekundären Indizes verbraucht werden.

Die Kosten für das Schreiben eines Elements in einen lokalen Sekundärindex hängen von mehreren Faktoren ab:
+ Wenn Sie ein neues Element in die Tabelle schreiben, die ein indiziertes Attribut definiert, oder ein vorhandenes Element zum Definieren eines zuvor nicht definierten indizierten Attributs aktualisieren, ist ein Schreibvorgang erforderlich, um das Element in den Index einzufügen.
+ Wenn eine Aktualisierung der Tabelle den Wert eines indizierten Schlüsselattributs (von A in B) ändert, sind zwei Schreibvorgänge erforderlich, und zwar einer zum Löschen des vorherigen Elements aus dem Index und einer zum Schreiben des neuen Elements in den Index.  
+ Wenn ein Element im Index vorhanden war, ein Schreibvorgang in der Tabelle jedoch dazu führte, dass das indizierte Attribut gelöscht wurde, ist ein Schreibvorgang erforderlich, um die alte Elementprojektion im Index zu löschen.
+ Wenn ein Element nicht im Index vorhanden ist, bevor oder nachdem das Element aktualisiert wird, fallen keine zusätzlichen Kosten für das Schreiben in den Index an.

Alle diese Faktoren setzen voraus, dass die Größe der einzelnen Elemente im Index kleiner oder gleich der 1-KB- Elementgröße für das Berechnen der Schreibkapazitätseinheiten ist. Größere Indexeinträge erfordern zusätzliche Schreibkapazitätseinheiten. Sie können Ihre Kosten für Schreibvorgänge minimieren, indem Sie überlegen, welche Attribute Ihre Abfragen zurückgeben müssen, und nur diese Attribute in den Index projizieren.

## Speicherüberlegungen für lokale sekundäre Indizes
<a name="LSI.StorageConsiderations"></a>

Wenn eine Anwendung ein Element in eine Tabelle schreibt, kopiert DynamoDB automatisch die richtige Teilmenge der Attribute in den lokalen sekundären Index, in dem diese Attribute angezeigt werden sollen. Ihrem AWS Konto werden sowohl die Speicherung des Elements in der Basistabelle als auch die Speicherung von Attributen in allen lokalen Sekundärindizes dieser Tabelle in Rechnung gestellt.

Der Speicherplatz, der von einem Indexelement belegt wird, ergibt sich aus der Summe von folgenden Werten:
+ Die Größe in Byte des Primärschlüssels der Basistabelle (Partitionsschlüssel und Sortierschlüssel)
+ Die Größe in Byte des Indexschlüsselattributs
+ Die Größe in Byte der projizierten Attribute (sofern vorhanden)
+ 100 Bytes des Overheads pro Indexelement

Um den Speicherbedarf für einen lokalen sekundären Index zu schätzen, können Sie die durchschnittliche Größe eines Elements im Index schätzen und dann mit der Anzahl der Elemente im Index multiplizieren.

Wenn eine Tabelle ein Element enthält, in dem ein bestimmtes Attribut nicht definiert ist, dieses Attribut aber als Indexsortierschlüssel festgelegt ist, schreibt DynamoDB keine Daten für dieses Element in den Index. 

## Elementauflistungen in lokalen sekundären Indizes
<a name="LSI.ItemCollections"></a>

**Anmerkung**  
Dieser Abschnitt betrifft nur Tabellen mit lokalen sekundären Indizes.

In DynamoDB ist eine *Elementsammlung* eine beliebige Gruppe von Elementen, die denselben Partitionsschlüsselwert in einer Tabelle und allen ihren lokalen sekundären Indizes aufweisen. In den Beispielen in diesem Abschnitt lautet der Partitionsschlüssel für die `Thread`-Tabelle `ForumName` und der Partitionsschlüssel für `LastPostIndex` ist ebenfalls `ForumName`. Alle Tabellen- und Indexelemente mit demselben `ForumName` gehören zur selben Elementauflistung. In der `Thread`-Tabelle und dem `LastPostIndex`- ist beispielsweise eine Elementauflistung für das `EC2`-Forum und eine andere Elementauflistung für das `RDS`-Forum vorhanden.

Das folgende Diagramm zeigt die Elementauflistung für das `S3`-Forum:

![\[Eine DynamoDB-Elementauflistung, die denselben Partitionsschlüsselwert von S3 in einer Tabelle und allen ihren lokalen sekundären Indizes aufweisen.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/LSI_04.png)


In diesem Diagramm enthält die Elementauflistung alle Elemente von `Thread` und `LastPostIndex`, wobei der Partitionsschlüsselwert `ForumName` „S3“ lautet. Wenn die Tabelle andere lokale sekundäre Indizes enthält, wären alle Elemente in diesen Indizes mit `ForumName` gleich „S3“ ebenfalls Teil der Elementsammlung.

Sie können eine der folgenden Operationen in DynamoDB verwenden, um Informationen zu Elementauflistungen zu erhalten:
+ `BatchWriteItem`
+ `DeleteItem`
+ `PutItem`
+ `UpdateItem`
+ `TransactWriteItems`

Jede dieser Operationen unterstützt den Parameter `ReturnItemCollectionMetrics`. Wenn Sie diesen Parameter auf `SIZE` festlegen, können Sie Informationen über die Größe der einzelnen Elementauflistung im Index anzeigen.

**Example**  
Nachfolgend finden Sie ein Beispiel aus der Ausgabe einer `UpdateItem`-Operation für die `Thread`-Tabelle, mit `ReturnItemCollectionMetrics` auf `SIZE`. Das Element, das aktualisiert wurde, hatte den `ForumName` „EC2“, sodass die Ausgabe Informationen über diese Elementauflistung enthält.  

```
{
    ItemCollectionMetrics: {
        ItemCollectionKey: {
            ForumName: "EC2"
        },
        SizeEstimateRangeGB: [0.0, 1.0]
    }
}
```
Das `SizeEstimateRangeGB`-Objekt zeigt, dass die Größe dieser Elementauflistung zwischen 0 und 1 GB beträgt. DynamoDB aktualisiert diese Größenschätzung in regelmäßigen Abständen, sodass die Zahlen bei der nächsten Änderung des Elements anders lauten können.

### Größenlimit der Elementauflistung
<a name="LSI.ItemCollections.SizeLimit"></a>

Die maximale Größe einer Elementauflistung für eine Tabelle mit einem oder mehreren lokalen sekundären Indizes beträgt 10 GB. Dies gilt nicht für Elementauflistungen in Tabellen ohne lokale sekundäre Indizes und auch nicht für Elementauflistungen in globalen sekundären Indizes. Es sind nur Tabellen mit einem oder mehreren lokalen sekundären Indizes betroffen.

Wenn eine Artikelsammlung den Grenzwert von 10 GB überschreitet, gibt DynamoDB möglicherweise eine zurück`ItemCollectionSizeLimitExceededException`, und Sie können der Artikelsammlung möglicherweise keine weiteren Artikel hinzufügen oder die Größe der Elemente in der Artikelsammlung erhöhen. (Lese- und Schreibvorgänge, die die Größe der Elementauflistung reduzieren, sind nach wie vor zulässig.) Sie können weiterhin Elemente zu anderen Elementauflistungen hinzufügen.

Um die Größe einer Elementauflistung zu reduzieren, können Sie einen der folgenden Schritte ausführen:
+ Löschen Sie alle unnötigen Elemente mit dem betreffenden Partitionsschlüsselwert. Wenn Sie diese Elemente aus der Basistabelle löschen, entfernt DynamoDB auch alle Indexeinträge, die denselben Partitionsschlüsselwert aufweisen.
+ Aktualisieren Sie die Elemente durch Entfernen von Attributen oder durch die Reduzierung der Größe der Attribute. Wenn diese Attribute in lokale sekundäre Indizes projiziert werden, reduziert DynamoDB auch die Größe der entsprechenden Indexeinträge.
+ Erstellen Sie eine neue Tabelle mit demselben Partitions- und Sortierschlüssel und verschieben Sie die Elemente von der alten in die neue Tabelle. Dies ist ein guter Ansatz, wenn eine Tabelle über historische Daten verfügt, auf die selten zugegriffen wird. Sie können auch in Betracht ziehen, diese historischen Daten in Amazon Simple Storage Service (Amazon S3) zu archivieren.

Wenn die Gesamtgröße der Elementsammlung unter 10 GB sinkt, können Sie erneut Elemente mit demselben Partitionsschlüsselwert hinzufügen.

Wir empfehlen als bewährte Methode, Ihre Anwendung zu instrumentieren, um die Größe Ihrer Elementauflistungen zu überwachen. Eine Möglichkeit dazu ist, den Parameter `ReturnItemCollectionMetrics` auf `SIZE` festzulegen, sobald Sie `BatchWriteItem`, `DeleteItem`, `PutItem` oder `UpdateItem`. verwenden. Ihre Anwendung sollte das `ReturnItemCollectionMetrics`-Objekt in der Ausgabe untersuchen und eine Fehlermeldung protokollieren, wenn eine Elementauflistung einen benutzerdefinierten Grenzwert (z. B. 8 GB) überschreitet. Wenn Sie einen geringeren Wert als 10 GB als Limit festlegen, ist dies ein Frühwarnsystem, da Sie so rechtzeitig erfahren, dass sich eine Elementauflistung dem Limit nähert, und entsprechende Maßnahmen ergreifen können.

### Elementauflistungen und Partitionen
<a name="LSI.ItemCollections.OnePartition"></a>

In einer Tabelle mit einem oder mehreren lokalen sekundären Indizes wird jede Elementauflistung in einer Partition gespeichert. Die Gesamtgröße einer solchen Elementauflistung ist auf die Kapazität dieser Partition beschränkt: 10 GB. Für eine Anwendung, bei der das Datenmodell Elementauflistungen enthält, deren Größe unbegrenzt ist oder bei denen Sie vernünftigerweise davon ausgehen können, dass einige Elementauflistungen in Zukunft auf mehr als 10 GB anwachsen werden, sollten Sie stattdessen einen globalen sekundären Index verwenden.

Sie sollten Ihre Anwendungen so konzipieren, dass Tabellendaten gleichmäßig auf unterschiedliche Partitionsschlüsselwerte verteilt werden. Für Tabellen mit lokalen sekundären Indizes sollten Ihre Anwendungen keine „Hotspots“ für Lese- und Schreibaktivitäten innerhalb einer einzigen Elementauflistung in einer einzelnen Partition erstellen. 

# Arbeiten mit lokalen sekundären Indizes: Java
<a name="LSIJavaDocumentAPI"></a>

Sie können die AWS SDK für Java Document-API verwenden, um eine Amazon DynamoDB-Tabelle mit einem oder mehreren lokalen Sekundärindizes zu erstellen, die Indizes in der Tabelle zu beschreiben und Abfragen mithilfe der Indizes durchzuführen.

Im Folgenden werden die üblichen Schritte für Tabellenoperationen mit der Document-API beschrieben. AWS SDK für Java 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Stellen Sie den erforderlichen und optionalen Parameter für die Operation bereit, indem Sie die entsprechenden Anforderungsobjekte erstellen. 

1. Rufen Sie die entsprechende Methode auf, die vom Client, den Sie im vorhergehenden Schritt erstellt haben, bereitgestellt wird. 

**Topics**
+ [Erstellen einer Tabelle mit einem lokalen sekundären Index](#LSIJavaDocumentAPI.CreateTableWithIndex)
+ [Beschreiben einer Tabelle mit einem lokalen sekundären Index](#LSIJavaDocumentAPI.DescribeTableWithIndex)
+ [Abfragen eines lokalen sekundären Indexes](#LSIJavaDocumentAPI.QueryAnIndex)
+ [Beispiel: Lokale sekundäre Indizes mit der Java-Dokument-API](LSIJavaDocumentAPI.Example.md)

## Erstellen einer Tabelle mit einem lokalen sekundären Index
<a name="LSIJavaDocumentAPI.CreateTableWithIndex"></a>

Lokale sekundäre Indizes müssen gleichzeitig mit dem Erstellen einer Tabelle erstellt werden. Verwenden Sie dazu die Methode `createTable` und geben Sie Ihre Angaben für einen oder mehrere lokale Sekundärindizes an. Das folgende Java-Codebeispiel erstellt eine Tabelle, die Informationen über Songs in einer Musiksammlung enthält. Der Partitionsschlüssel ist `Artist` und der Sortierschlüssel `SongTitle`. Der sekundäre Index, `AlbumTitleIndex`, vereinfacht Abfragen von Albumtiteln. 

Im Folgenden werden die Schritte zum Erstellen einer Tabelle mit einem lokalen sekundären Index mithilfe der DynamoDB-Dokument-API dargelegt. 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `CreateTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen. 

   Sie müssen den Tabellennamen, seinen zugehörigen Primärschlüssel und die Werte des bereitgestellten Durchsatzes angeben. Für den lokalen sekundären Index müssen Sie den Indexnamen, den Namen und den Datentyp des Indexsortierschlüssels, des Schlüsselschemas für den Index und der Attributprojektion angeben.

1. Rufen Sie die `createTable`-Methode auf, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht. Der Codeerstellt eine Tabelle (`Music`) mit einem sekundären Index auf dem `AlbumTitle`-Attribut. Der Tabellenpartitionsschlüssel und der Sortierschlüssel, sowie der Indexsortierschlüssel sind die einzigen in den Index projizierten Attribute.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

String tableName = "Music";

CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName);

//ProvisionedThroughput
createTableRequest.setProvisionedThroughput(new ProvisionedThroughput().withReadCapacityUnits((long)5).withWriteCapacityUnits((long)5));

//AttributeDefinitions
ArrayList<AttributeDefinition> attributeDefinitions= new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition().withAttributeName("Artist").withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition().withAttributeName("SongTitle").withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition().withAttributeName("AlbumTitle").withAttributeType("S"));

createTableRequest.setAttributeDefinitions(attributeDefinitions);

//KeySchema
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement().withAttributeName("Artist").withKeyType(KeyType.HASH));  //Partition key
tableKeySchema.add(new KeySchemaElement().withAttributeName("SongTitle").withKeyType(KeyType.RANGE));  //Sort key

createTableRequest.setKeySchema(tableKeySchema);

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();
indexKeySchema.add(new KeySchemaElement().withAttributeName("Artist").withKeyType(KeyType.HASH));  //Partition key
indexKeySchema.add(new KeySchemaElement().withAttributeName("AlbumTitle").withKeyType(KeyType.RANGE));  //Sort key

Projection projection = new Projection().withProjectionType(ProjectionType.INCLUDE);
ArrayList<String> nonKeyAttributes = new ArrayList<String>();
nonKeyAttributes.add("Genre");
nonKeyAttributes.add("Year");
projection.setNonKeyAttributes(nonKeyAttributes);

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex()
    .withIndexName("AlbumTitleIndex").withKeySchema(indexKeySchema).withProjection(projection);

ArrayList<LocalSecondaryIndex> localSecondaryIndexes = new ArrayList<LocalSecondaryIndex>();
localSecondaryIndexes.add(localSecondaryIndex);
createTableRequest.setLocalSecondaryIndexes(localSecondaryIndexes);

Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen.

## Beschreiben einer Tabelle mit einem lokalen sekundären Index
<a name="LSIJavaDocumentAPI.DescribeTableWithIndex"></a>

Um Informationen zu lokalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie die Methode `describeTable`. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

Im Folgenden sind die Schritte für den Zugriff auf lokale sekundäre Indexinformationen einer Tabelle mithilfe der AWS SDK für Java -Dokument-API aufgeführt.

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse. Sie müssen den Tabellennamen angeben.

1. Rufen Sie die `describeTable`-Methode für das `Table`-Objekt auf.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

String tableName = "Music";

Table table = dynamoDB.getTable(tableName);

TableDescription tableDescription = table.describe();

List<LocalSecondaryIndexDescription> localSecondaryIndexes 
    = tableDescription.getLocalSecondaryIndexes();

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.

Iterator<LocalSecondaryIndexDescription> lsiIter = localSecondaryIndexes.iterator();
while (lsiIter.hasNext()) {

    LocalSecondaryIndexDescription lsiDescription = lsiIter.next();
    System.out.println("Info for index " + lsiDescription.getIndexName() + ":");
    Iterator<KeySchemaElement> kseIter = lsiDescription.getKeySchema().iterator();
    while (kseIter.hasNext()) {
        KeySchemaElement kse = kseIter.next();
        System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
    }
    Projection projection = lsiDescription.getProjection();
    System.out.println("\tThe projection type is: " + projection.getProjectionType());
    if (projection.getProjectionType().toString().equals("INCLUDE")) {
        System.out.println("\t\tThe non-key projected attributes are: " + projection.getNonKeyAttributes());
    }
}
```

## Abfragen eines lokalen sekundären Indexes
<a name="LSIJavaDocumentAPI.QueryAnIndex"></a>

Sie können die Operation `Query` für einen lokalen sekundären Index genauso nutzen, wie Sie `Query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexsortierschlüssel und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `AlbumTitleIndex` und der Indexsortierschlüssel `AlbumTitle`. 

Die einzigen zurückgegebenen Attribute sind die, die in den Index projiziert wurden. Sie könnten diese Abfrage ändern, um auch Nicht-Schlüsselattribute auszuwählen, aber dies würde eine Tabellenabrufaktivität erfordern, die relativ teuer ist. Weitere Informationen zum Abrufen von Tabellen finden Sie unter [Attributprojektionen](LSI.md#LSI.Projections).

Im Folgenden werden die Schritte zum Abfragen eines lokalen sekundären Indexes mithilfe der AWS SDK für Java Dokument-API beschrieben. 

1. Erstellen Sie eine Instance der `DynamoDB`-Klasse.

1. Erstellen Sie eine Instance der `Table`-Klasse. Sie müssen den Tabellennamen angeben.

1. Erstellen Sie eine Instance der `Index`-Klasse. Sie müssen den Indexnamen angeben.

1. Rufen Sie die `query`-Methode für die `Index`-Klasse auf.

Im folgenden Java-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

String tableName = "Music";

Table table = dynamoDB.getTable(tableName);
Index index = table.getIndex("AlbumTitleIndex");

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("Artist = :v_artist and AlbumTitle = :v_title")
    .withValueMap(new ValueMap()
        .withString(":v_artist", "Acme Band")
        .withString(":v_title", "Songs About Life"));

ItemCollection<QueryOutcome> items = index.query(spec);

Iterator<Item> itemsIter = items.iterator();

while (itemsIter.hasNext()) {
    Item item = itemsIter.next();
    System.out.println(item.toJSONPretty());
}
```

### Konsistente Lesevorgänge auf einem lokalen sekundären Index
<a name="LSIJavaDocumentAPI.ConsistentReads"></a>

Im Gegensatz zu globalen Sekundärindizes, die nur eventuell konsistente Lesevorgänge unterstützen, unterstützt ein lokaler sekundärer Index sowohl letztlich konsistente als auch stark konsistente Lesevorgänge. Bei einem Strongly-Consistent-Lesevorgang von einem lokalen sekundären Index werden immer die zuletzt aktualisierten Werte zurückgegeben. Wenn die Abfrage zusätzliche Attribute aus der Basistabelle abrufen muss, sind diese abgerufenen Attribute auch in Bezug auf den Index konsistent.

`Query`Verwendet standardmäßig eventuell konsistente Lesevorgänge. Um einen stark konsistenten Lesevorgang anzufordern, setzen Sie `true` in der `ConsistentRead` auf`QuerySpec`. Im folgenden Beispiel wird für `AlbumTitleIndex` Abfragen ein stark konsistenter Lesevorgang verwendet:

**Example**  

```
QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("Artist = :v_artist and AlbumTitle = :v_title")
    .withValueMap(new ValueMap()
        .withString(":v_artist", "Acme Band")
        .withString(":v_title", "Songs About Life"))
    .withConsistentRead(true);
```

**Anmerkung**  
Ein stark konsistenter Lesevorgang verbraucht eine Lesekapazitätseinheit pro 4 KB zurückgegebener Daten (aufgerundet), wohingegen ein eventuell konsistenter Lesevorgang die Hälfte davon verbraucht. Beispielsweise verbraucht ein stark konsistenter Lesevorgang, der 9 KB an Daten zurückgibt, 3 Lesekapazitätseinheiten (9 KB/4 KB = 2,25, aufgerundet auf 3), während dieselbe Abfrage, die einen eventuell konsistenten Lesevorgang verwendet, 1,5 Lesekapazitätseinheiten verbraucht. Wenn Ihre Anwendung das Lesen von Daten verträgt, die möglicherweise etwas veraltet sind, verwenden Sie eventuell konsistente Lesevorgänge, um Ihre Lesekapazitätsnutzung zu reduzieren. Weitere Informationen finden Sie unter [Lesekapazitätseinheiten](LSI.md#LSI.ThroughputConsiderations.Reads).

# Beispiel: Lokale sekundäre Indizes mit der Java-Dokument-API
<a name="LSIJavaDocumentAPI.Example"></a>

Das folgende Java-Codebeispiel zeigt, wie Sie mit lokalen sekundären Indizes in Amazon DynamoDB arbeiten. Das Beispiel erstellt eine Tabelle mit dem Namen `CustomerOrders` mit `CustomerId` als Partitionsschlüssel und `OrderId` als Sortierschlüssel. Es gibt zwei lokale sekundäre Indizes in dieser Tabelle:
+ `OrderCreationDateIndex` – der Sortierschlüssel ist `OrderCreationDate` und die folgenden Attribute werden in den Index projiziert:
  + `ProductCategory`
  + `ProductName`
  + `OrderStatus`
  + `ShipmentTrackingId`
+ `IsOpenIndex` – der Sortierschlüssel ist `IsOpen` und alle Tabellenattribute werden in den Index projiziert.

Nachdem die `CustomerOrders`-Tabelle erstellt wurde, lädt das Programm die Tabelle mit Daten, die Kundenaufträge darstellen. Mit If Then werden die Daten unter Verwendung der lokalen sekundären Indizes abgefragt. Schließlich löscht das Programm die `CustomerOrders`-Tabelle.

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter[Java-Codebeispiele](CodeSamples.Java.md).

**Example**  

```
package com.example.dynamodb;

import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.*;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;

import java.util.HashMap;
import java.util.Map;

public class DocumentAPILocalSecondaryIndexExample {

    static DynamoDbClient client = DynamoDbClient.create();
    public static String tableName = "CustomerOrders";

    public static void main(String[] args) {
        createTable();
        loadData();
        query(null);
        query("IsOpenIndex");
        query("OrderCreationDateIndex");
        deleteTable(tableName);
    }

    public static void createTable() {
        CreateTableRequest request = CreateTableRequest.builder()
            .tableName(tableName)
            .provisionedThroughput(ProvisionedThroughput.builder()
                .readCapacityUnits(1L)
                .writeCapacityUnits(1L)
                .build())
            .attributeDefinitions(
                AttributeDefinition.builder().attributeName("CustomerId").attributeType(ScalarAttributeType.S).build(),
                AttributeDefinition.builder().attributeName("OrderId").attributeType(ScalarAttributeType.N).build(),
                AttributeDefinition.builder().attributeName("OrderCreationDate").attributeType(ScalarAttributeType.N).build(),
                AttributeDefinition.builder().attributeName("IsOpen").attributeType(ScalarAttributeType.N).build())
            .keySchema(
                KeySchemaElement.builder().attributeName("CustomerId").keyType(KeyType.HASH).build(),
                KeySchemaElement.builder().attributeName("OrderId").keyType(KeyType.RANGE).build())
            .localSecondaryIndexes(
                LocalSecondaryIndex.builder()
                    .indexName("OrderCreationDateIndex")
                    .keySchema(
                        KeySchemaElement.builder().attributeName("CustomerId").keyType(KeyType.HASH).build(),
                        KeySchemaElement.builder().attributeName("OrderCreationDate").keyType(KeyType.RANGE).build())
                    .projection(Projection.builder()
                        .projectionType(ProjectionType.INCLUDE)
                        .nonKeyAttributes("ProductCategory", "ProductName")
                        .build())
                    .build(),
                LocalSecondaryIndex.builder()
                    .indexName("IsOpenIndex")
                    .keySchema(
                        KeySchemaElement.builder().attributeName("CustomerId").keyType(KeyType.HASH).build(),
                        KeySchemaElement.builder().attributeName("IsOpen").keyType(KeyType.RANGE).build())
                    .projection(Projection.builder()
                        .projectionType(ProjectionType.ALL)
                        .build())
                    .build())
            .build();

        System.out.println("Creating table " + tableName + "...");
        client.createTable(request);

        try (DynamoDbWaiter waiter = client.waiter()) {
            WaiterResponse<DescribeTableResponse> response = waiter.waitUntilTableExists(r -> r.tableName(tableName));
            response.matched().response().ifPresent(System.out::println);
        }
    }

    public static void query(String indexName) {
        System.out.println("\n***********************************************************\n");
        System.out.println("Querying table " + tableName + "...");

        if ("IsOpenIndex".equals(indexName)) {
            System.out.println("\nUsing index: '" + indexName + "': Bob's orders that are open.");
            System.out.println("Only a user-specified list of attributes are returned\n");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":v_custid", AttributeValue.builder().s("bob@example.com").build());
            values.put(":v_isopen", AttributeValue.builder().n("1").build());

            QueryRequest request = QueryRequest.builder()
                .tableName(tableName)
                .indexName(indexName)
                .keyConditionExpression("CustomerId = :v_custid and IsOpen = :v_isopen")
                .expressionAttributeValues(values)
                .projectionExpression("OrderCreationDate, ProductCategory, ProductName, OrderStatus")
                .build();

            System.out.println("Query: printing results...");
            client.query(request).items().forEach(System.out::println);

        } else if ("OrderCreationDateIndex".equals(indexName)) {
            System.out.println("\nUsing index: '" + indexName + "': Bob's orders that were placed after 01/31/2015.");
            System.out.println("Only the projected attributes are returned\n");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":v_custid", AttributeValue.builder().s("bob@example.com").build());
            values.put(":v_orddate", AttributeValue.builder().n("20150131").build());

            QueryRequest request = QueryRequest.builder()
                .tableName(tableName)
                .indexName(indexName)
                .keyConditionExpression("CustomerId = :v_custid and OrderCreationDate >= :v_orddate")
                .expressionAttributeValues(values)
                .select(Select.ALL_PROJECTED_ATTRIBUTES)
                .build();

            System.out.println("Query: printing results...");
            client.query(request).items().forEach(System.out::println);

        } else {
            System.out.println("\nNo index: All of Bob's orders, by OrderId:\n");

            Map<String, AttributeValue> values = new HashMap<>();
            values.put(":v_custid", AttributeValue.builder().s("bob@example.com").build());

            QueryRequest request = QueryRequest.builder()
                .tableName(tableName)
                .keyConditionExpression("CustomerId = :v_custid")
                .expressionAttributeValues(values)
                .build();

            System.out.println("Query: printing results...");
            client.query(request).items().forEach(System.out::println);
        }
    }

    public static void deleteTable(String tableName) {
        System.out.println("Deleting table " + tableName + "...");
        client.deleteTable(DeleteTableRequest.builder().tableName(tableName).build());

        try (DynamoDbWaiter waiter = client.waiter()) {
            waiter.waitUntilTableNotExists(r -> r.tableName(tableName));
        }
    }

    public static void loadData() {
        System.out.println("Loading data into table " + tableName + "...");

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("alice@example.com").build(),
            "OrderId", AttributeValue.builder().n("1").build(),
            "IsOpen", AttributeValue.builder().n("1").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150101").build(),
            "ProductCategory", AttributeValue.builder().s("Book").build(),
            "ProductName", AttributeValue.builder().s("The Great Outdoors").build(),
            "OrderStatus", AttributeValue.builder().s("PACKING ITEMS").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("alice@example.com").build(),
            "OrderId", AttributeValue.builder().n("2").build(),
            "IsOpen", AttributeValue.builder().n("1").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150221").build(),
            "ProductCategory", AttributeValue.builder().s("Bike").build(),
            "ProductName", AttributeValue.builder().s("Super Mountain").build(),
            "OrderStatus", AttributeValue.builder().s("ORDER RECEIVED").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("alice@example.com").build(),
            "OrderId", AttributeValue.builder().n("3").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150304").build(),
            "ProductCategory", AttributeValue.builder().s("Music").build(),
            "ProductName", AttributeValue.builder().s("A Quiet Interlude").build(),
            "OrderStatus", AttributeValue.builder().s("IN TRANSIT").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("176493").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("1").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150111").build(),
            "ProductCategory", AttributeValue.builder().s("Movie").build(),
            "ProductName", AttributeValue.builder().s("Calm Before The Storm").build(),
            "OrderStatus", AttributeValue.builder().s("SHIPPING DELAY").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("859323").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("2").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150124").build(),
            "ProductCategory", AttributeValue.builder().s("Music").build(),
            "ProductName", AttributeValue.builder().s("E-Z Listening").build(),
            "OrderStatus", AttributeValue.builder().s("DELIVERED").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("756943").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("3").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150221").build(),
            "ProductCategory", AttributeValue.builder().s("Music").build(),
            "ProductName", AttributeValue.builder().s("Symphony 9").build(),
            "OrderStatus", AttributeValue.builder().s("DELIVERED").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("645193").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("4").build(),
            "IsOpen", AttributeValue.builder().n("1").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150222").build(),
            "ProductCategory", AttributeValue.builder().s("Hardware").build(),
            "ProductName", AttributeValue.builder().s("Extra Heavy Hammer").build(),
            "OrderStatus", AttributeValue.builder().s("PACKING ITEMS").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("5").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150309").build(),
            "ProductCategory", AttributeValue.builder().s("Book").build(),
            "ProductName", AttributeValue.builder().s("How To Cook").build(),
            "OrderStatus", AttributeValue.builder().s("IN TRANSIT").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("440185").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("6").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150318").build(),
            "ProductCategory", AttributeValue.builder().s("Luggage").build(),
            "ProductName", AttributeValue.builder().s("Really Big Suitcase").build(),
            "OrderStatus", AttributeValue.builder().s("DELIVERED").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("893927").build()));

        putItem(Map.of(
            "CustomerId", AttributeValue.builder().s("bob@example.com").build(),
            "OrderId", AttributeValue.builder().n("7").build(),
            "OrderCreationDate", AttributeValue.builder().n("20150324").build(),
            "ProductCategory", AttributeValue.builder().s("Golf").build(),
            "ProductName", AttributeValue.builder().s("PGA Pro II").build(),
            "OrderStatus", AttributeValue.builder().s("OUT FOR DELIVERY").build(),
            "ShipmentTrackingId", AttributeValue.builder().s("383283").build()));
    }

    private static void putItem(Map<String, AttributeValue> item) {
        client.putItem(PutItemRequest.builder().tableName(tableName).item(item).build());
    }
}
```

# Arbeiten mit lokalen sekundären Indizes: .NET
<a name="LSILowLevelDotNet"></a>

**Topics**
+ [Erstellen einer Tabelle mit einem lokalen sekundären Index](#LSILowLevelDotNet.CreateTableWithIndex)
+ [Beschreiben einer Tabelle mit einem lokalen sekundären Index](#LSILowLevelDotNet.DescribeTableWithIndex)
+ [Abfragen eines lokalen sekundären Indexes](#LSILowLevelDotNet.QueryAnIndex)
+ [Beispiel: Lokale sekundäre Indizes mithilfe der Low-Level-API AWS SDK für .NET](LSILowLevelDotNet.Example.md)

Sie können die AWS SDK für .NET Low-Level-API verwenden, um eine Amazon DynamoDB-Tabelle mit einem oder mehreren lokalen Sekundärindizes zu erstellen, die Indizes in der Tabelle zu beschreiben und Abfragen mithilfe der Indizes durchzuführen. Diese Operationen entsprechen den Low-Level-DynamoDB-API-Aktionen. Weitere Informationen finden Sie unter [.NET-Codebeispiele](CodeSamples.DotNet.md). 

Folgende sind die allgemeinen Schritte für Tabellenoperationen mithilfe der .NET-Low-Level-API. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Stellen Sie den erforderlichen und optionalen Parameter für die Operation bereit, indem Sie die entsprechenden Anforderungsobjekte erstellen.

   Erstellen Sie beispielsweise ein `CreateTableRequest`-Objekt, um eine Tabelle zu erstellen und ein `QueryRequest`-Objekt, um eine Tabelle oder einen Index abzufragen. 

1. Rufen Sie die entsprechende Methode auf, die vom Client, den Sie im vorhergehenden Schritt erstellt haben, bereitgestellt wird. 

## Erstellen einer Tabelle mit einem lokalen sekundären Index
<a name="LSILowLevelDotNet.CreateTableWithIndex"></a>

Lokale sekundäre Indizes müssen gleichzeitig beim Erstellen einer Tabelle erstellt werden. Zu diesem Zweck verwenden Sie `CreateTable` und geben Ihre Spezifikationen für ein oder mehrere lokale sekundäre Indizes an. Das folgende C\$1-Codebeispiel erstellt eine Tabelle, die Informationen über Songs in einer Musiksammlung enthält. Der Partitionsschlüssel ist `Artist` und der Sortierschlüssel `SongTitle`. Der sekundäre Index, `AlbumTitleIndex`, vereinfacht Abfragen von Albumtiteln. 

Im Folgenden sind die Schritte zum Erstellen einer Tabelle mit einem lokalen sekundären Index unter Verwendung der .NET-API auf niedriger Ebene aufgeführt. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Erstellen Sie eine Instance der `CreateTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen. 

   Sie müssen den Tabellennamen, seinen zugehörigen Primärschlüssel und die Werte des bereitgestellten Durchsatzes angeben. Für den lokalen sekundären Index müssen Sie den Indexnamen, den Namen und den Datentyp des Indexsortierschlüssels, das Schlüsselschema für den Index und die Attributprojektion angeben.

1. Führen Sie die `CreateTable`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht. Der Codeerstellt eine Tabelle (`Music`) mit einem sekundären Index auf dem `AlbumTitle`-Attribut. Der Tabellenpartitionsschlüssel und der Sortierschlüssel, sowie der Indexsortierschlüssel sind die einzigen in den Index projizierten Attribute.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "Music";

CreateTableRequest createTableRequest = new CreateTableRequest()
{
    TableName = tableName
};

//ProvisionedThroughput
createTableRequest.ProvisionedThroughput = new ProvisionedThroughput()
{
    ReadCapacityUnits = (long)5,
    WriteCapacityUnits = (long)5
};

//AttributeDefinitions
List<AttributeDefinition> attributeDefinitions = new List<AttributeDefinition>();

attributeDefinitions.Add(new AttributeDefinition()
{
    AttributeName = "Artist",
    AttributeType = "S"
});

attributeDefinitions.Add(new AttributeDefinition()
 {
     AttributeName = "SongTitle",
     AttributeType = "S"
 });

attributeDefinitions.Add(new AttributeDefinition()
 {
     AttributeName = "AlbumTitle",
     AttributeType = "S"
 });

createTableRequest.AttributeDefinitions = attributeDefinitions;

//KeySchema
List<KeySchemaElement> tableKeySchema = new List<KeySchemaElement>();

tableKeySchema.Add(new KeySchemaElement() { AttributeName = "Artist", KeyType = "HASH" });  //Partition key
tableKeySchema.Add(new KeySchemaElement() { AttributeName = "SongTitle", KeyType = "RANGE" });  //Sort key

createTableRequest.KeySchema = tableKeySchema;

List<KeySchemaElement> indexKeySchema = new List<KeySchemaElement>();
indexKeySchema.Add(new KeySchemaElement() { AttributeName = "Artist", KeyType = "HASH" });  //Partition key
indexKeySchema.Add(new KeySchemaElement() { AttributeName = "AlbumTitle", KeyType = "RANGE" });  //Sort key

Projection projection = new Projection() { ProjectionType = "INCLUDE" };

List<string> nonKeyAttributes = new List<string>();
nonKeyAttributes.Add("Genre");
nonKeyAttributes.Add("Year");
projection.NonKeyAttributes = nonKeyAttributes;

LocalSecondaryIndex localSecondaryIndex = new LocalSecondaryIndex()
{
    IndexName = "AlbumTitleIndex",
    KeySchema = indexKeySchema,
    Projection = projection
};

List<LocalSecondaryIndex> localSecondaryIndexes = new List<LocalSecondaryIndex>();
localSecondaryIndexes.Add(localSecondaryIndex);
createTableRequest.LocalSecondaryIndexes = localSecondaryIndexes;

CreateTableResponse result = client.CreateTable(createTableRequest);
Console.WriteLine(result.CreateTableResult.TableDescription.TableName);
Console.WriteLine(result.CreateTableResult.TableDescription.TableStatus);
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen.

## Beschreiben einer Tabelle mit einem lokalen sekundären Index
<a name="LSILowLevelDotNet.DescribeTableWithIndex"></a>

Um Informationen zu lokalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie die `DescribeTable`-API. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

Im Folgenden finden Sie die Schritte zum Zugreifen auf lokale sekundäre Indexinformationen einer Tabelle mithilfe der .NET-Low-Level-API. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Erstellen Sie eine Instance der `DescribeTableRequest`-Klasse, um die Anforderungsinformationen bereitzustellen. Sie müssen den Tabellennamen angeben.

1. Führen Sie die `describeTable`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "Music";

DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest() { TableName = tableName });
List<LocalSecondaryIndexDescription> localSecondaryIndexes =
    response.DescribeTableResult.Table.LocalSecondaryIndexes;

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.
foreach (LocalSecondaryIndexDescription lsiDescription in localSecondaryIndexes)
{
    Console.WriteLine("Info for index " + lsiDescription.IndexName + ":");

    foreach (KeySchemaElement kse in lsiDescription.KeySchema)
    {
        Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType);
    }

    Projection projection = lsiDescription.Projection;

    Console.WriteLine("\tThe projection type is: " + projection.ProjectionType);

    if (projection.ProjectionType.ToString().Equals("INCLUDE"))
    {
        Console.WriteLine("\t\tThe non-key projected attributes are:");

        foreach (String s in projection.NonKeyAttributes)
        {
            Console.WriteLine("\t\t" + s);
        }

    }
}
```

## Abfragen eines lokalen sekundären Indexes
<a name="LSILowLevelDotNet.QueryAnIndex"></a>

Sie können `Query` für einen lokalen sekundären Index genauso nutzen, wie Sie `Query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexsortierschlüssel und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `AlbumTitleIndex` und der Indexsortierschlüssel `AlbumTitle`. 

Die einzigen zurückgegebenen Attribute sind die, die in den Index projiziert wurden. Sie könnten diese Abfrage ändern, um auch Nicht-Schlüsselattribute auszuwählen, aber dies würde eine Tabellenabrufaktivität erfordern, die relativ teuer ist. Weitere Informationen zum Abrufen von Tabellen finden Sie unter [Attributprojektionen](LSI.md#LSI.Projections)

Im Folgenden werden die Schritte zur Abfrage eines lokalen sekundären Indizes mithilfe der .NET-Low-Level-API dargelegt. 

1. Erstellen Sie eine Instance der `AmazonDynamoDBClient`-Klasse.

1. Erstellen Sie eine Instance der `QueryRequest`-Klasse, um die Anforderungsinformationen bereitzustellen.

1. Führen Sie die `query`-Methode aus, indem das Anforderungsobjekt als Parameter festgelegt wird.

Im folgenden C\$1-Codebeispiel werden die vorherigen Schritte veranschaulicht.

**Example**  

```
QueryRequest queryRequest = new QueryRequest
{
    TableName = "Music",
    IndexName = "AlbumTitleIndex",
    Select = "ALL_ATTRIBUTES",
    ScanIndexForward = true,
    KeyConditionExpression = "Artist = :v_artist and AlbumTitle = :v_title",
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":v_artist",new AttributeValue {S = "Acme Band"}},
        {":v_title",new AttributeValue {S = "Songs About Life"}}
    },
};

QueryResponse response = client.Query(queryRequest);

foreach (var attribs in response.Items)
{
    foreach (var attrib in attribs)
    {
        Console.WriteLine(attrib.Key + " ---> " + attrib.Value.S);
    }
    Console.WriteLine();
}
```

# Beispiel: Lokale sekundäre Indizes mithilfe der Low-Level-API AWS SDK für .NET
<a name="LSILowLevelDotNet.Example"></a>

Das folgende C\$1-Codebeispiel zeigt, wie Sie mit lokalen sekundären Indizes in Amazon DynamoDB arbeiten. Das Beispiel erstellt eine Tabelle mit dem Namen `CustomerOrders` mit `CustomerId` als Partitionsschlüssel und `OrderId` als Sortierschlüssel. Es gibt zwei lokale sekundäre Indizes in dieser Tabelle:
+ `OrderCreationDateIndex` – der Sortierschlüssel ist `OrderCreationDate` und die folgenden Attribute werden in den Index projiziert:
  + `ProductCategory`
  + `ProductName`
  + `OrderStatus`
  + `ShipmentTrackingId`
+ `IsOpenIndex` – der Sortierschlüssel ist `IsOpen` und alle Tabellenattribute werden in den Index projiziert.

Nachdem die `CustomerOrders`-Tabelle erstellt wurde, lädt das Programm die Tabelle mit Daten, die Kundenaufträge darstellen. Mit If Then werden die Daten unter Verwendung der lokalen sekundären Indizes abgefragt. Schließlich löscht das Programm die `CustomerOrders`-Tabelle.

 step-by-stepAnweisungen zum Testen des folgenden Beispiels finden Sie unter. [.NET-Codebeispiele](CodeSamples.DotNet.md)

**Example**  

```
using System;
using System.Collections.Generic;
using System.Linq;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class LowLevelLocalSecondaryIndexExample
    {
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
        private static string tableName = "CustomerOrders";

        static void Main(string[] args)
        {
            try
            {
                CreateTable();
                LoadData();

                Query(null);
                Query("IsOpenIndex");
                Query("OrderCreationDateIndex");

                DeleteTable(tableName);

                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }

        private static void CreateTable()
        {
            var createTableRequest =
                new CreateTableRequest()
                {
                    TableName = tableName,
                    ProvisionedThroughput =
                    new ProvisionedThroughput()
                    {
                        ReadCapacityUnits = (long)1,
                        WriteCapacityUnits = (long)1
                    }
                };

            var attributeDefinitions = new List<AttributeDefinition>()
        {
            // Attribute definitions for table primary key
            { new AttributeDefinition() {
                  AttributeName = "CustomerId", AttributeType = "S"
              } },
            { new AttributeDefinition() {
                  AttributeName = "OrderId", AttributeType = "N"
              } },
            // Attribute definitions for index primary key
            { new AttributeDefinition() {
                  AttributeName = "OrderCreationDate", AttributeType = "N"
              } },
            { new AttributeDefinition() {
                  AttributeName = "IsOpen", AttributeType = "N"
              }}
        };

            createTableRequest.AttributeDefinitions = attributeDefinitions;

            // Key schema for table
            var tableKeySchema = new List<KeySchemaElement>()
        {
            { new KeySchemaElement() {
                  AttributeName = "CustomerId", KeyType = "HASH"
              } },                                                  //Partition key
            { new KeySchemaElement() {
                  AttributeName = "OrderId", KeyType = "RANGE"
              } }                                                //Sort key
        };

            createTableRequest.KeySchema = tableKeySchema;

            var localSecondaryIndexes = new List<LocalSecondaryIndex>();

            // OrderCreationDateIndex
            LocalSecondaryIndex orderCreationDateIndex = new LocalSecondaryIndex()
            {
                IndexName = "OrderCreationDateIndex"
            };

            // Key schema for OrderCreationDateIndex
            var indexKeySchema = new List<KeySchemaElement>()
        {
            { new KeySchemaElement() {
                  AttributeName = "CustomerId", KeyType = "HASH"
              } },                                                    //Partition key
            { new KeySchemaElement() {
                  AttributeName = "OrderCreationDate", KeyType = "RANGE"
              } }                                                            //Sort key
        };

            orderCreationDateIndex.KeySchema = indexKeySchema;

            // Projection (with list of projected attributes) for
            // OrderCreationDateIndex
            var projection = new Projection()
            {
                ProjectionType = "INCLUDE"
            };

            var nonKeyAttributes = new List<string>()
        {
            "ProductCategory",
            "ProductName"
        };
            projection.NonKeyAttributes = nonKeyAttributes;

            orderCreationDateIndex.Projection = projection;

            localSecondaryIndexes.Add(orderCreationDateIndex);

            // IsOpenIndex
            LocalSecondaryIndex isOpenIndex
                = new LocalSecondaryIndex()
                {
                    IndexName = "IsOpenIndex"
                };

            // Key schema for IsOpenIndex
            indexKeySchema = new List<KeySchemaElement>()
        {
            { new KeySchemaElement() {
                  AttributeName = "CustomerId", KeyType = "HASH"
              }},                                                     //Partition key
            { new KeySchemaElement() {
                  AttributeName = "IsOpen", KeyType = "RANGE"
              }}                                                  //Sort key
        };

            // Projection (all attributes) for IsOpenIndex
            projection = new Projection()
            {
                ProjectionType = "ALL"
            };

            isOpenIndex.KeySchema = indexKeySchema;
            isOpenIndex.Projection = projection;

            localSecondaryIndexes.Add(isOpenIndex);

            // Add index definitions to CreateTable request
            createTableRequest.LocalSecondaryIndexes = localSecondaryIndexes;

            Console.WriteLine("Creating table " + tableName + "...");
            client.CreateTable(createTableRequest);
            WaitUntilTableReady(tableName);
        }

        public static void Query(string indexName)
        {
            Console.WriteLine("\n***********************************************************\n");
            Console.WriteLine("Querying table " + tableName + "...");

            QueryRequest queryRequest = new QueryRequest()
            {
                TableName = tableName,
                ConsistentRead = true,
                ScanIndexForward = true,
                ReturnConsumedCapacity = "TOTAL"
            };


            String keyConditionExpression = "CustomerId = :v_customerId";
            Dictionary<string, AttributeValue> expressionAttributeValues = new Dictionary<string, AttributeValue> {
            {":v_customerId", new AttributeValue {
                 S = "bob@example.com"
             }}
        };


            if (indexName == "IsOpenIndex")
            {
                Console.WriteLine("\nUsing index: '" + indexName
                          + "': Bob's orders that are open.");
                Console.WriteLine("Only a user-specified list of attributes are returned\n");
                queryRequest.IndexName = indexName;

                keyConditionExpression += " and IsOpen = :v_isOpen";
                expressionAttributeValues.Add(":v_isOpen", new AttributeValue
                {
                    N = "1"
                });

                // ProjectionExpression
                queryRequest.ProjectionExpression = "OrderCreationDate, ProductCategory, ProductName, OrderStatus";
            }
            else if (indexName == "OrderCreationDateIndex")
            {
                Console.WriteLine("\nUsing index: '" + indexName
                          + "': Bob's orders that were placed after 01/31/2013.");
                Console.WriteLine("Only the projected attributes are returned\n");
                queryRequest.IndexName = indexName;

                keyConditionExpression += " and OrderCreationDate > :v_Date";
                expressionAttributeValues.Add(":v_Date", new AttributeValue
                {
                    N = "20130131"
                });

                // Select
                queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES";
            }
            else
            {
                Console.WriteLine("\nNo index: All of Bob's orders, by OrderId:\n");
            }
            queryRequest.KeyConditionExpression = keyConditionExpression;
            queryRequest.ExpressionAttributeValues = expressionAttributeValues;

            var result = client.Query(queryRequest);
            var items = result.Items;
            foreach (var currentItem in items)
            {
                foreach (string attr in currentItem.Keys)
                {
                    if (attr == "OrderId" || attr == "IsOpen"
                        || attr == "OrderCreationDate")
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].N);
                    }
                    else
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].S);
                    }
                }
                Console.WriteLine();
            }
            Console.WriteLine("\nConsumed capacity: " + result.ConsumedCapacity.CapacityUnits + "\n");
        }

        private static void DeleteTable(string tableName)
        {
            Console.WriteLine("Deleting table " + tableName + "...");
            client.DeleteTable(new DeleteTableRequest()
            {
                TableName = tableName
            });
            WaitForTableToBeDeleted(tableName);
        }

        public static void LoadData()
        {
            Console.WriteLine("Loading data into table " + tableName + "...");

            Dictionary<string, AttributeValue> item = new Dictionary<string, AttributeValue>();

            item["CustomerId"] = new AttributeValue
            {
                S = "alice@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "1"
            };
            item["IsOpen"] = new AttributeValue
            {
                N = "1"
            };
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130101"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Book"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "The Great Outdoors"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "PACKING ITEMS"
            };
            /* no ShipmentTrackingId attribute */
            PutItemRequest putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "alice@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "2"
            };
            item["IsOpen"] = new AttributeValue
            {
                N = "1"
            };
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130221"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Bike"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "Super Mountain"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "ORDER RECEIVED"
            };
            /* no ShipmentTrackingId attribute */
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "alice@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "3"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130304"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Music"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "A Quiet Interlude"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "IN TRANSIT"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "176493"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "1"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130111"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Movie"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "Calm Before The Storm"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "SHIPPING DELAY"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "859323"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "2"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130124"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Music"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "E-Z Listening"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "DELIVERED"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "756943"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "3"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130221"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Music"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "Symphony 9"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "DELIVERED"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "645193"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "4"
            };
            item["IsOpen"] = new AttributeValue
            {
                N = "1"
            };
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130222"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Hardware"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "Extra Heavy Hammer"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "PACKING ITEMS"
            };
            /* no ShipmentTrackingId attribute */
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "5"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130309"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Book"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "How To Cook"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "IN TRANSIT"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "440185"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "6"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130318"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Luggage"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "Really Big Suitcase"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "DELIVERED"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "893927"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);

            item = new Dictionary<string, AttributeValue>();
            item["CustomerId"] = new AttributeValue
            {
                S = "bob@example.com"
            };
            item["OrderId"] = new AttributeValue
            {
                N = "7"
            };
            /* no IsOpen attribute */
            item["OrderCreationDate"] = new AttributeValue
            {
                N = "20130324"
            };
            item["ProductCategory"] = new AttributeValue
            {
                S = "Golf"
            };
            item["ProductName"] = new AttributeValue
            {
                S = "PGA Pro II"
            };
            item["OrderStatus"] = new AttributeValue
            {
                S = "OUT FOR DELIVERY"
            };
            item["ShipmentTrackingId"] = new AttributeValue
            {
                S = "383283"
            };
            putItemRequest = new PutItemRequest
            {
                TableName = tableName,
                Item = item,
                ReturnItemCollectionMetrics = "SIZE"
            };
            client.PutItem(putItemRequest);
        }

        private static void WaitUntilTableReady(string tableName)
        {
            string status = null;
            // Let us wait until table is created. Call DescribeTable.
            do
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                    status = res.Table.TableStatus;
                }
                catch (ResourceNotFoundException)
                {
                    // DescribeTable is eventually consistent. So you might
                    // get resource not found. So we handle the potential exception.
                }
            } while (status != "ACTIVE");
        }

        private static void WaitForTableToBeDeleted(string tableName)
        {
            bool tablePresent = true;

            while (tablePresent)
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                }
                catch (ResourceNotFoundException)
                {
                    tablePresent = false;
                }
            }
        }
    }
}
```

# Arbeiten mit lokalen sekundären Indizes in der DynamoDB-AWS CLI
<a name="LCICli"></a>

Sie können die AWS CLI zum Erstellen einer Amazon-DynamoDB-Tabelle mit einem oder mehreren lokalen sekundären Indizes, zum Beschreiben der Indizes in der Tabelle und zur Ausführung von Abfragen mithilfe des Indizes, verwenden.

**Topics**
+ [Erstellen einer Tabelle mit einem lokalen sekundären Index](#LCICli.CreateTableWithIndex)
+ [Beschreiben einer Tabelle mit einem lokalen sekundären Index](#LCICli.DescribeTableWithIndex)
+ [Abfragen eines lokalen sekundären Indexes](#LCICli.QueryAnIndex)

## Erstellen einer Tabelle mit einem lokalen sekundären Index
<a name="LCICli.CreateTableWithIndex"></a>

Lokale sekundäre Indizes müssen gleichzeitig mit dem Erstellen einer Tabelle erstellt werden. Zu diesem Zweck verwenden Sie den `create-table`-Parameter und geben Ihre Spezifikationen für ein oder mehrere lokale sekundäre Indizes an. Das folgende Beispiel erstellt eine Tabelle (`Music`), die Informationen über Songs in einer Musiksammlung enthält. Der Partitionsschlüssel ist `Artist` und der Sortierschlüssel `SongTitle`. Ein sekundärer Index, `AlbumTitleIndex` auf dem `AlbumTitle`-Attribut, erleichtert Abfragen nach Albumtitel. 

```
aws dynamodb create-table \
    --table-name Music \
    --attribute-definitions AttributeName=Artist,AttributeType=S AttributeName=SongTitle,AttributeType=S \
        AttributeName=AlbumTitle,AttributeType=S  \
    --key-schema AttributeName=Artist,KeyType=HASH AttributeName=SongTitle,KeyType=RANGE \
    --provisioned-throughput \
        ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --local-secondary-indexes \
        "[{\"IndexName\": \"AlbumTitleIndex\",
        \"KeySchema\":[{\"AttributeName\":\"Artist\",\"KeyType\":\"HASH\"},
                      {\"AttributeName\":\"AlbumTitle\",\"KeyType\":\"RANGE\"}],
        \"Projection\":{\"ProjectionType\":\"INCLUDE\",  \"NonKeyAttributes\":[\"Genre\", \"Year\"]}}]"
```

Sie müssen warten bis DynamoDB die Tabelle erstellt und den Tabellenstatus auf `ACTIVE` setzt. Im Anschluss können Sie die Daten in der Tabelle ablegen. Mit [describe-table](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/describe-table.html) können Sie den Status der Tabellenerstellung ermitteln. 

## Beschreiben einer Tabelle mit einem lokalen sekundären Index
<a name="LCICli.DescribeTableWithIndex"></a>

Um Informationen zu lokalen sekundären Indizes in einer Tabelle zu erhalten, verwenden Sie den Parameter `describe-table`. Sie können auf den Namen, das Schlüsselschema und die projizierten Attribute von jedem Index zugreifen.

```
aws dynamodb describe-table --table-name Music
```

## Abfragen eines lokalen sekundären Indexes
<a name="LCICli.QueryAnIndex"></a>

Sie können die Operation `query` für einen lokalen sekundären Index genauso nutzen, wie Sie `query` für eine Tabelle nutzen. Sie müssen den Indexnamen, die Abfragekriterien für den Indexsortierschlüssel und die Attribute angeben, die Sie zurückgeben möchten. In diesem Beispiel ist der Index `AlbumTitleIndex` und der Indexsortierschlüssel `AlbumTitle`. 

Die einzigen zurückgegebenen Attribute sind die, die in den Index projiziert wurden. Sie könnten diese Abfrage ändern, um auch Nicht-Schlüsselattribute auszuwählen, aber dies würde eine Tabellenabrufaktivität erfordern, die relativ teuer ist. Weitere Informationen zum Abrufen von Tabellen finden Sie unter [Attributprojektionen](LSI.md#LSI.Projections).

```
aws dynamodb query \
    --table-name Music \
    --index-name AlbumTitleIndex \
    --key-condition-expression "Artist = :v_artist and AlbumTitle = :v_title" \
    --expression-attribute-values  '{":v_artist":{"S":"Acme Band"},":v_title":{"S":"Songs About Life"} }'
```

# Verwalten komplexer Workflows mit DynamoDB-Transaktionen
<a name="transactions"></a>

Amazon DynamoDB-Transaktionen vereinfachen die Entwicklererfahrung, wenn sie koordinierte all-or-nothing Änderungen an mehreren Elementen sowohl innerhalb als auch tabellenübergreifend vornehmen müssen. Transaktionen ermöglichen in DynamoDB Atomarität, Konsistenz, Isolation und Haltbarkeit (ACID), wodurch Sie die Richtigkeit der Daten in Ihren Anwendungen einfacher verwalten können.

Sie können das transaktionale Lesen und Schreiben von DynamoDB verwenden, APIs um komplexe Geschäftsabläufe zu verwalten, bei denen mehrere Elemente in einem einzigen Vorgang hinzugefügt, aktualisiert oder gelöscht werden müssen. all-or-nothing Ein Entwickler von Videospielen kann so beispielsweise gewährleisten, dass die Profile der Spieler korrekt aktualisiert werden, wenn sie Elemente in einem Spiel austauschen oder Käufe aus einem Spiel heraus tätigen.

Mit der transaktionalen Schreib-API können Sie mehrere `Put`, `Update`-, `Delete`- und `ConditionCheck`-Aktionen gruppieren. Anschließend können Sie sie als eine einzige `TransactWriteItems`-Operation übermitteln, die entweder als Ganzes erfolgreich ist oder fehlschlägt. Dies gilt auch für mehrere `Get`-Aktionen, die Sie als einzige `TransactGetItems`-Operation gruppieren und übermitteln können.

Es fallen keine zusätzlichen Kosten für das Aktivieren von Transaktionen für Ihre DynamoDB-Tabellen an. Sie zahlen nur für Lese- oder Schreibvorgänge, die Teil Ihrer Transaktion sind. DynamoDB führt zwei zugrunde liegende Lese- oder Schreibvorgänge für jedes Element in der Transaktion aus: einen zum Vorbereiten der Transaktion und einen zum Festschreiben der Transaktion. Diese beiden zugrunde liegenden read/write Operationen sind in Ihren CloudWatch Amazon-Metriken sichtbar.

Um mit DynamoDB-Transaktionen zu beginnen, laden Sie das neueste AWS SDK oder das AWS Command Line Interface ()AWS CLI herunter. Befolgen Sie dann das Verfahren unter [DynamoDB-Transaktionen-Beispiel](transaction-example.md).

Die folgenden Abschnitte bieten einen detaillierten Überblick über die Transaktion APIs und darüber, wie Sie sie in DynamoDB verwenden können.

**Topics**
+ [Funktionsweise](transaction-apis.md)
+ [Verwenden von IAM mit Transaktionen](transaction-apis-iam.md)
+ [Beispiel-Code](transaction-example.md)

# Amazon DynamoDB Transactions: Funktionsweise
<a name="transaction-apis"></a>

Mit Amazon DynamoDB-Transaktionen können Sie mehrere Aktionen gruppieren und sie als einzelne all-or-nothing `TransactWriteItems` oder `TransactGetItems` Operation einreichen. Die folgenden Abschnitte beschreiben API-Produktionen, Kapazitätsverwaltung, bewährte Methoden und andere Details zur Verwendung von Transaktionsoperationen in DynamoDB.

**Topics**
+ [TransactWriteItems API](#transaction-apis-txwriteitems)
+ [TransactGetItems API](#transaction-apis-txgetitems)
+ [Isolationsstufen für DynamoDB-Transaktionen](#transaction-isolation)
+ [Handhabung von Transaktionskonflikten in DynamoDB](#transaction-conflict-handling)
+ [Verwenden von Transactional APIs in DynamoDB Accelerator (DAX)](#transaction-apis-dax)
+ [Kapazitätsverwaltung für Transaktionen](#transaction-capacity-handling)
+ [Bewährte Methoden für Transaktionen](#transaction-best-practices)
+ [Verwenden Sie transaktionale Tabellen APIs mit globalen Tabellen](#transaction-integration)
+ [DynamoDB-Transaktionen im Vergleich zur AWSLabs Transactions-Clientbibliothek](#transaction-vs-library)

## TransactWriteItems API
<a name="transaction-apis-txwriteitems"></a>

`TransactWriteItems`ist eine synchrone und idempotente Schreiboperation, die bis zu 100 Schreibaktionen in einer einzigen Operation gruppiert. all-or-nothing Diese Aktionen können auf bis zu 100 verschiedene Elemente in einer oder mehreren DynamoDB-Tabellen innerhalb desselben AWS Kontos und in derselben Region abzielen. Die aggregierte Größe der Elemente in der Transaktion darf 4 MB nicht übersteigen. Die Aktionen werden atomarisch ausgeführt, d. h. entweder sind alle von ihnen oder keine von ihnen erfolgreich.

**Anmerkung**  
 Eine `TransactWriteItems`-Operation unterscheidet sich darin von einer `BatchWriteItem`-Operation, dass alle darin enthaltenen Aktionen erfolgreich ausgeführt werden müssen, damit irgendwelche Änderungen vorgenommen werden. Bei einer `BatchWriteItem`-Operation ist es dagegen möglich, dass nur einige der Aktionen im Stapel erfolgreich sind und andere fehlschlagen. 
 Transaktionen können nicht mit Indizes ausgeführt werden. 

Sie können nicht in derselben Transaktion mit mehreren Operationen auf das gleiche Element abzielen. Beispiel: In derselben Transaktion ist es nicht möglich eine `ConditionCheck`- sowie eine `Update`-Aktion für dasselbe Element auszuführen.

Sie können die folgenden Aktionstypen zu einer Transaktion hinzufügen:
+ `Put` – Initiiert eine `PutItem`-Produktion, um bedingungsabhängig oder bedingungslos ein neues Element zu erstellen oder ein altes Element durch ein neues Element zu ersetzen.
+ `Update` – Initiiert eine `UpdateItem`-Produktion, um die Attribute eines vorhandenen Elements zu bearbeiten oder ein neues Element zur Tabelle hinzuzufügen, sofern noch nicht vorhanden. Mit dieser Aktion können Sie Attribute für ein vorhandenes Element bedingungsabhängig oder bedingungslos hinzufügen, löschen oder aktualisieren.
+ `Delete` – Initiiert eine `DeleteItem`-Produktion,, um ein einzelnes Element über seinen Primärschlüssel in einer Tabelle zu löschen.
+ `ConditionCheck` – Überprüft, ob ein Element vorhanden ist, oder überprüft die Bedingung bestimmter Attribute des Elements.

Wenn eine Transaktion in DynamoDB abgeschlossen ist, werden ihre Änderungen an globale Sekundärindizes (GSIs), Streams und Backups weitergegeben. Diese Übertragung erfolgt schrittweise: Stream-Datensätze aus derselben Transaktion können zu unterschiedlichen Zeiten erscheinen und sich mit Datensätzen aus anderen Transaktionen überlappen. Stream-Konsumenten sollten nicht davon ausgehen, dass Transaktionen vollständig sind oder dass es sich um Bestellgarantien handelt.

Um eine atomare Momentaufnahme der in einer Transaktion geänderten Elemente sicherzustellen, verwenden Sie den TransactGetItems Vorgang, um alle relevanten Elemente zusammen zu lesen. Dieser Vorgang bietet eine konsistente Ansicht der Daten, sodass Sie entweder alle Änderungen einer abgeschlossenen Transaktion oder gar keine sehen.

Da die Weitergabe nicht unmittelbar erfolgt, kann eine Tabelle, wenn sie aus Backup ([RestoreTableFromBackup](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_RestoreTableFromBackup.html)) wiederhergestellt oder zu einem Zeitpunkt ([ExportTableToPointInTime](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ExportTableToPointInTime.html)) während der Weitergabe exportiert wird, nur einige der Änderungen enthalten, die während einer kürzlich durchgeführten Transaktion vorgenommen wurden.

### Idempotenz
<a name="transaction-apis-txwriteitems-idempotency"></a>

Sie können optional ein Client-Token einschließen, wenn Sie einen `TransactWriteItems`-Aufruf machen, um sicherzustellen, dass die Anforderung *idempotent* ist. Durch idempotente Transaktionen lassen sich Anwendungsfehler vermeiden, falls dieselbe Operation aufgrund einer Verbindungszeitüberschreitung oder sonstiger Konnektivitätsprobleme mehrmals übermittelt wird.

Wenn der ursprüngliche `TransactWriteItems`-Aufruf erfolgreich war, werden nachfolgende `TransactWriteItems`-Aufrufe mit demselben Client-Token als erfolgreich zurückgegeben, ohne Änderungen vorzunehmen. Wenn der Parameter `ReturnConsumedCapacity` eingestellt ist, gibt der erstmalige `TransactWriteItems`-Aufruf die Anzahl an Schreibkapazitätseinheiten zurück, die beim Vornehmen der Änderungen verbraucht wurden. Nachfolgende `TransactWriteItems`-Aufrufe mit demselben Client-Token geben die Anzahl der Lesekapazitätseinheiten zurück, die beim Lesen des Elements verbraucht wurden.

**Wichtige Punkte bezüglich Idempotenz**
+ Ein Client-Token ist weitere 10 Minuten lang gültig, nachdem die Anforderung, die davon Gebrauch gemacht hat, beendet wurde. Nach 10 Minuten werden alle Anforderungen, die dasselbe Client-Token nutzen, als neue Anforderung angesehen. Deshalb sollten Sie dasselbe Client-Token nach 10 Minuten nicht erneut für dieselbe Anwendung verwenden.
+ Wenn Sie eine Anforderung mit demselben Client-Token innerhalb des 10-minütigen Idempotenzfenster wiederholen, aber einen anderen Anforderungsparameter ändern, gibt DynamoDB die Ausnahme `IdempotentParameterMismatch` zurück.

### Fehlerbehandlung beim Schreiben
<a name="transaction-apis-txwriteitems-errors"></a>

Schreibtransaktionen schlagen unter den folgenden Umständen fehl:
+ Wenn eine Bedingung in einem der Bedingungsausdrücke nicht erfüllt wird.
+ Wenn ein Transaktionsvalidierungsfehler auftritt, da mehr als eine Aktion in derselben `TransactWriteItems`-Operation auf dasselbe Element abzielt.
+ Wenn eine `TransactWriteItems`-Anforderung mit einer andauernden `TransactWriteItems`-Operation an mindestens einem Element in der `TransactWriteItems`-Anforderung in Konflikt steht. In diesem Fall schlägt die Anfrage mit der Ausnahme `TransactionCanceledException` fehl.
+ Wenn für die durchzuführende Transaktion nicht genügend Kapazität bereitgestellt wird.
+ Wenn ein Element zu groß wird (größer als 400 KB) oder wenn ein lokaler sekundärer Index (LSI) zu groß wird oder wenn aufgrund der durch die Transaktion vorgenommenen Änderungen ein ähnlicher Validierungsfehler auftritt.
+ Wenn ein Benutzerfehler, wie z. B. ein ungültiges Datenformat, auftritt.

 Weitere Informationen zum Umgang mit Konflikten mit `TransactWriteItems`-Operationen finden Sie unter [Handhabung von Transaktionskonflikten in DynamoDB](#transaction-conflict-handling).

## TransactGetItems API
<a name="transaction-apis-txgetitems"></a>

`TransactGetItems` ist ein synchroner Lesevorgang, der bis zu 100 `Get`-Aktionen zusammengruppiert. Diese Aktionen können auf bis zu 100 verschiedene Elemente in einer oder mehreren DynamoDB-Tabellen innerhalb desselben AWS Kontos und derselben Region abzielen. Die aggregierte Größe der Elemente in der Transaktion darf 4 MB nicht überschreiten. 

Die `Get`-Aktionen werden atomarisch durchgeführt, d. h. entweder sind alle von ihnen oder keine von ihnen erfolgreich:
+ `Get` – Initiiert eine `GetItem`-Operation, um einen Satz von Attributen für das Elemente mit dem angegebenen Primärschlüssel abzurufen. Wenn kein passendes Element gefunden wird, gibt `Get` keine Daten zurück.

### Fehlerbehandlung beim Lesen
<a name="transaction-apis-txgetitems-errors"></a>

Lesetransaktionen schlagen unter den folgenden Umständen fehl:
+ Wenn eine `TransactGetItems`-Anforderung mit einer andauernden `TransactWriteItems`-Operation an mindestens einem Element in der `TransactGetItems`-Anforderung in Konflikt steht. In diesem Fall schlägt die Anfrage mit der Ausnahme `TransactionCanceledException` fehl.
+ Wenn für die durchzuführende Transaktion nicht genügend Kapazität bereitgestellt wird.
+ Wenn ein Benutzerfehler, wie z. B. ein ungültiges Datenformat, auftritt.

 Weitere Informationen zum Umgang mit Konflikten mit `TransactGetItems`-Operationen finden Sie unter [Handhabung von Transaktionskonflikten in DynamoDB](#transaction-conflict-handling).

## Isolationsstufen für DynamoDB-Transaktionen
<a name="transaction-isolation"></a>

Die Isolationsstufen von Transaktionsoperationen (`TransactWriteItems` oder `TransactGetItems`) und anderen Operationen sind folgende:

### SERIALIZABLE
<a name="transaction-isolation-serializable"></a>

Durch die Isolationsstufe *serializable* wird sichergestellt, dass die Ergebnisse mehrerer gleichzeitiger Operationen die gleichen sind, als würde eine Operation erst beginnen, nachdem die vorherige Operation beendet wurde.

Die serialisierbare Isolation findet zwischen den folgenden Arten von Operationen statt:
+ Zwischen Transaktionsoperationen und Standardschreibvorgängen (`PutItem`, `UpdateItem` oder `DeleteItem`).
+ Zwischen Transaktionsoperationen und Standardlesevorgängen (`GetItem`).
+ Zwischen einer `TransactWriteItems`-Operation und einer `TransactGetItems`-Operation.

Obwohl eine serialisierbare Isolation zwischen Transaktionsoperationen und einzelnen Standardschreibvorgängen in einer `BatchWriteItem`-Operation auftritt, findet keine serialisierbare Isolation zwischen der Transaktion und der `BatchWriteItem`-Operation als Einheit statt.

Dementsprechend ist die Isolationsstufe zwischen einer Transaktionsoperation und einzelnen `GetItems` in einer `BatchGetItem`-Operation serialisierbar. Die Isoloationsstufe zwischen der Transaktion und der `BatchGetItem`-Operation als Einheit ist aber *read-committed*.

Eine einzelne `GetItem`-Anforderung kann in Bezug auf eine `TransactWriteItems`-Anforderung auf eine von zwei Arten serialisiert werden, entweder vor oder nach der `TransactWriteItems`-Anforderung. Mehrere `GetItem`-Anforderungen, gegen Schlüssel in einem gleichzeitigen `TransactWriteItems`-Anfragen können in beliebiger Reihenfolge ausgeführt werden, und daher sind die Ergebnisse *read-committed*.

Wenn beispielsweise `GetItem`-Anforderungen für Element A und Element B gleichzeitig mit einer `TransactWriteItems`-Anforderung ausgeführt werden, die sowohl Element A als auch Element B ändert, gibt es vier Möglichkeiten:
+ Beide `GetItem`-Anforderungen werden vor der `TransactWriteItems`-Anforderung ausgeführt.
+ Beide `GetItem`-Anforderungen werden nach der `TransactWriteItems`-Anforderung ausgeführt.
+ `GetItem`-Anforderung für Element A wird vor der `TransactWriteItems`-Anforderung ausgeführt. Für Element B wird die `GetItem` nach `TransactWriteItems` ausgeführt.
+ `GetItem`-Anforderung für Element B wird vor der `TransactWriteItems`-Anforderung ausgeführt. Für Element A wird die `GetItem` nach `TransactWriteItems` ausgeführt.

Wenn die serialisierbare Isolationsstufe für mehrere `GetItem`-Anfragen bevorzugt wird, verwenden Sie `TransactGetItems`.

Wenn mehrere Elemente, die während der Übertragung Teil derselben Transaktionsschreibanfrage waren, nicht transaktionell gelesen werden, ist es möglich, dass Sie den neuen Status einiger Elemente und den alten Status der anderen Elemente lesen können. Sie können den neuen Status aller Elemente, die Teil der Transaktionsschreibanfrage waren, nur lesen, wenn eine erfolgreiche Antwort für den transaktionalen Schreibvorgang eingegangen ist, was darauf hinweist, dass die Transaktion abgeschlossen wurde.

Sobald die Transaktion erfolgreich abgeschlossen wurde und eine Antwort eingegangen ist, können nachfolgende, *letztendlich konsistente* Lesevorgänge aufgrund des Konsistenzmodells von DynamoDB für kurze Zeit immer noch den alten Status zurückgeben. Um sicherzustellen, dass unmittelbar nach einer Transaktion möglichst up-to-date viele Daten gelesen werden, sollten Sie Strongly [*Consistent Reads verwenden*](HowItWorks.ReadConsistency.md#HowItWorks.ReadConsistency.Strongly), indem Sie den Wert `ConsistentRead` auf true setzen.

### READ-COMMITTED
<a name="transaction-isolation-read-committed"></a>

Durch die Isolation *Read-committed* wird sichergestellt, dass Lesevorgänge immer festgeschriebene Werte für ein Element zurückgeben – der Lesevorgang wird niemals eine Sicht auf das Element präsentieren, die einen Zustand aus einem letztlich nicht erfolgreichen transaktionalen Schreibvorgang darstellt. Die Isolation "Read-committed" verhindert keine Änderungen am Element direkt nach dem Lesevorgang.

Die Isolationsstufe ist read-committed zwischen allen Transaktionsoperationen und allen Lesevorgängen, die mehrere Standard-Lesevorgänge (`BatchGetItem`, `Query` oder `Scan`) umfassen. Wenn bei einem transaktionalen Schreibvorgang ein Element mitten in einer `BatchGetItem`-, `Query`- oder `Scan`-Operation aktualisiert wird, gibt der nachfolgende Teil des Lesevorgangs den neu festgeschriebenen Wert zurück (mit `ConsistentRead)` oder möglicherweise einem zuvor festgeschriebenem Wert (letztendlich konsistente Lesevorgänge).

### Zusammenfassung des Vorgangs
<a name="transaction-isolation-table"></a>

Die folgende Tabelle gibt einen Überblick über die Isolationsstufen zwischen einer Transaktionsoperation (`TransactWriteItems` oder `TransactGetItems`) und anderen Operationen.


| Operation | Isolationsstufe | 
| --- | --- | 
| `DeleteItem` | *Serializable* | 
| `PutItem` | *Serializable* | 
| `UpdateItem` | *Serializable* | 
| `GetItem` | *Serializable* | 
| `BatchGetItem` | *Read-committed*\$1 | 
| `BatchWriteItem` | *NICHT Serializable*\$1 | 
| `Query` | *Read-committed* | 
| `Scan` | *Read-committed* | 
| Andere Transaktionsoperationen | *Serializable* | 

Mit einem Sternchen (\$1) markierte Stufen gelten für die Operation als Einheit. Einzelne Aktionen innerhalb dieser Operationen besitzen jedoch die Isolationsstufe *serializable*.

## Handhabung von Transaktionskonflikten in DynamoDB
<a name="transaction-conflict-handling"></a>

Bei Anforderungen auf Elementebene kann für ein Element in einer Transaktion ein Transaktionskonflikt auftreten. Transaktionskonflikte können in den folgenden Szenarien auftreten: 
+ Eine `PutItem`-, `UpdateItem`- oder `DeleteItem`-Anforderung für ein Element konfligiert mit einer laufenden `TransactWriteItems`-Anforderung, die dasselbe Element enthält.
+ Ein Element in einer `TransactWriteItems`-Anforderung ist Teil einer anderen laufenden `TransactWriteItems`-Anforderung.
+ Ein Element in einer `TransactGetItems`-Anforderung ist Teil einer laufenden `TransactWriteItems`-, `BatchWriteItem`-, `PutItem`-, `UpdateItem`- oder `DeleteItem`-Anforderung.

**Anmerkung**  
Wenn eine `PutItem`-, `UpdateItem`- oder `DeleteItem`-Anforderung abgelehnt wird, schlägt die Anforderung mit einer `TransactionConflictException` fehl. 
Wenn irgendeine Anforderung auf Elementebene in `TransactWriteItems` oder `TransactGetItems` abgelehnt wird, schlägt die Anforderung mit einer `TransactionCanceledException` fehl. Wenn diese Anfrage fehlschlägt, AWS SDKs wiederholen Sie die Anfrage nicht.  
Wenn Sie den verwenden AWS SDK für Java, enthält die Ausnahme die Liste der [CancellationReasons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CancellationReason.html), sortiert nach der Liste der Elemente im `TransactItems` Anforderungsparameter. Bei anderen Sprachen ist in der Fehlermeldung der Ausnahme eine Zeichenfolgendarstellung der Liste enthalten. 
Wenn eine laufende `TransactWriteItems`- oder `TransactGetItems`-Operation mit einer gleichzeitigen `GetItem`-Anforderung im Konflikt steht, können beide Operationen erfolgreich durchgeführt werden.

Die [TransactionConflict CloudWatch Metrik](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html) wird für jede fehlgeschlagene Anfrage auf Elementebene inkrementiert.

## Verwenden von Transactional APIs in DynamoDB Accelerator (DAX)
<a name="transaction-apis-dax"></a>

`TransactWriteItems` und `TransactGetItems` werden in DynamoDB Accelerator (DAX) mit den gleichen Isolierungsstufen wie in DynamoDB unterstützt.

`TransactWriteItems` schreibt über DAX. DAX übergibt eineN `TransactWriteItems`-Aufruf an DynamoDB und gibt die Antwort zurück. Um den Cache nach dem Schreiben aufzufüllen, ruft DAX `TransactGetItems` im Hintergrund für jedes Element im `TransactWriteItems`-Vorgang auf, wodurch zusätzliche Lesekapazitätseinheiten verbraucht werden. (Weitere Informationen finden Sie unter [Kapazitätsverwaltung für Transaktionen](#transaction-capacity-handling).) Diese Funktion ermöglicht es, dass Ihre Anwendungslogik einfach bleibt. Außerdem können Sie so DAX für Transaktionsoperationen sowie für nicht transaktionale Operationen verwenden.

`TransactGetItems`-Aufrufe werden über DAX übergeben, ohne dass Elemente lokal zwischengespeichert werden. Dies ist dasselbe Verhalten wie beim stark konsistenten Lesen in DAX. APIs 

## Kapazitätsverwaltung für Transaktionen
<a name="transaction-capacity-handling"></a>

Es fallen keine zusätzlichen Kosten für das Aktivieren von Transaktionen für Ihre DynamoDB-Tabellen an. Sie zahlen nur für Lese- oder Schreibvorgänge, die Teil Ihrer Transaktion sind. DynamoDB führt zwei zugrunde liegende Lese- oder Schreibvorgänge für jedes Element in der Transaktion aus: einen zum Vorbereiten der Transaktion und einen zum Festschreiben der Transaktion. Die beiden zugrunde liegenden read/write Operationen sind in Ihren CloudWatch Amazon-Metriken sichtbar.

Planen Sie die zusätzlichen Lese- und Schreibvorgänge ein, die für Transaktionen erforderlich sind APIs , wenn Sie Kapazität für Ihre Tabellen bereitstellen. Angenommen, Ihre Anwendung führt eine Transaktion pro Sekunde aus und jede Transaktion schreibt drei 500-Byte-Elemente in Ihre Tabelle. Für jedes Element sind zwei Schreibkapazitätseinheiten (WCUs) erforderlich: eine für die Vorbereitung der Transaktion und eine für den Commit der Transaktion. Daher müssten Sie sechs für WCUs die Tabelle bereitstellen. 

Wenn Sie im vorherigen Beispiel DynamoDB Accelerator (DAX) verwenden würden, würden Sie auch zwei Lesekapazitätseinheiten (RCUs) für jedes Element im `TransactWriteItems` Aufruf verwenden. Sie müssten also sechs weitere RCUs für die Tabelle bereitstellen.

Wenn Ihre Anwendung eine Lesetransaktion pro Sekunde ausführt und jede Transaktion drei 500-Byte-Elemente in Ihrer Tabelle liest, müssten Sie der Tabelle entsprechend sechs Lesekapazitätseinheiten (RCUs) bereitstellen. Zum Lesen jedes Elements sind zwei erforderlich RCUs: eine für die Vorbereitung der Transaktion und eine für die Ausführung der Transaktion.

Außerdem ist das SDK-Standardverhalten, Transaktionen im Falle der Ausnahme `TransactionInProgressException` wiederholt zu versuchen. Planen Sie die zusätzlichen Lesekapazitätseinheiten (RCUs) ein, die diese Wiederholungen verbrauchen. Dies gilt auch, wenn Sie Transaktionen in Ihrem eigenen Code mit einem `ClientRequestToken` wiederholt versuchen.

## Bewährte Methoden für Transaktionen
<a name="transaction-best-practices"></a>

Erwägen Sie bei der Verwendung von DynamoDB-Transaktionen die folgenden empfohlenen Methoden.
+ Aktivieren Sie für Ihre Tabellen das Auto Scaling oder stellen Sie sicher, dass Sie die von Ihnen bereitgestellte Durchsatzkapazität zum Ausführen der beiden Lese- oder Schreibvorgänge für jedes Element in der Transaktion ausreicht.
+ Wenn Sie kein AWS bereitgestelltes SDK verwenden, fügen Sie bei einem `TransactWriteItems` Aufruf ein `ClientRequestToken` Attribut hinzu, um sicherzustellen, dass die Anfrage idempotent ist.
+ Gruppieren Sie Operationen nur dann als eine Transaktion zusammen, wenn dies wirklich erforderlich ist. Beispiel: Wenn eine einzelne Transaktion mit 10 Operationen in mehrere Transaktionen aufgeteilt werden kann, ohne die korrekte Funktionsweise der Anwendung zu gefährden, wird zur Aufteilung der Transaktion geraten. Weniger komplexe Transaktionen verbessern den Durchsatz und sind mit größerer Wahrscheinlichkeit erfolgreich. 
+ Wenn mehrere Transaktionen dieselben Elemente gleichzeitig aktualisieren, können Konflikte entstehen, die zum Abbruch der Transaktionen führen. Wir empfehlen die folgenden bewährten DynamoDB-Methoden für die Datenmodellierung, um solche Konflikte zu minimieren.
+ Wenn ein Satz von Attributen häufig im Rahmen einer einzelnen Transaktion über mehrere Elemente hinweg aktualisiert wird, empfiehlt es sich, die Attribute in einem einzigen Element zusammenzugruppieren, um den Umfang der Transaktion zu reduzieren.
+ Vermeiden Sie es, Transaktionen zur massenweisen Aufnahme von Daten zu verwenden. `BatchWriteItem` eignet sich besser für Massenschreibvorgänge.

## Verwenden Sie transaktionale Tabellen APIs mit globalen Tabellen
<a name="transaction-integration"></a>

Transaktionsoperationen bieten Garantien für Atomizität, Konsistenz, Isolation und Haltbarkeit (ACID) nur innerhalb der AWS Region, in der die Schreib-API aufgerufen wurde. Regionsübergreifende Transaktionen werden in globalen Tabellen nicht unterstützt. Angenommen, Sie haben eine globale Tabelle mit Replikaten in den Regionen USA Ost (Ohio) und USA West (Oregon) und Sie führen einen `TransactWriteItems`-Vorgang in der Region USA Ost (Nord-Virginia) aus. Dann sind möglicherweise teilweise abgeschlossene Transaktionen in der Region USA West (Oregon) zu beobachten, während Änderungen repliziert werden. Die Änderungen werden erst dann in die anderen Regionen repliziert, nachdem sie in der Quellregion in die Datenbank eingetragen wurden.

## DynamoDB-Transaktionen im Vergleich zur AWSLabs Transactions-Clientbibliothek
<a name="transaction-vs-library"></a>

DynamoDB-Transaktionen bieten einen kostengünstigeren, robusteren und leistungsfähigeren Ersatz für die [AWSLabs](https://github.com/awslabs)Transactions-Clientbibliothek. Wir empfehlen Ihnen, Ihre Anwendungen so zu aktualisieren, dass sie die native, serverseitige Transaktion verwenden. APIs

# Verwenden von IAM mit DynamoDB-Transaktionen
<a name="transaction-apis-iam"></a>

Sie können AWS Identity and Access Management (IAM) verwenden, um die Aktionen einzuschränken, die Transaktionsvorgänge in Amazon DynamoDB ausführen können. Weitere Informationen zur Verwendung der IAM-Richtlinien in DynamoDB finden Sie unter [Identitätsbasierte Richtlinien für DynamoDB](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies).

Die Berechtigungen für die Aktionen `Put`, `Update`, `Delete` und `Get` werden durch die Berechtigungen geregelt, die für die zugrundeliegenden Operationen `PutItem`, `UpdateItem`, `DeleteItem` und `GetItem` verwendet werden. Für die Aktion `ConditionCheck` können Sie die Berechtigung `dynamodb:ConditionCheckItem` in den IAM-Richtlinien verwenden.

Es folgen Beispiele für die IAM-Richtlinien, die Sie zum Konfigurieren der DynamoDB-Transaktionen verwenden können.

## Beispiel 1: Zulassen von Transaktionsoperationen
<a name="tx-policy-example-1"></a>

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ]
        }
    ]
}
```

------

## Beispiel 2: Zulassen nur von Transaktionsoperationen
<a name="tx-policy-example-2"></a>

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ],
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "dynamodb:EnclosingOperation": [
                        "TransactWriteItems",
                        "TransactGetItems"
                    ]
                }
            }
        }
    ]
}
```

------

## Beispiel 3: Zulassen von nicht-transaktionalen Lese- und Schreibvorgängen und Blockieren von transaktionalen Lese- und Schreibvorgängen
<a name="tx-policy-example-3"></a>

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ],
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "dynamodb:EnclosingOperation": [
                        "TransactWriteItems",
                        "TransactGetItems"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
             "Action": [
                 "dynamodb:PutItem",
                 "dynamodb:DeleteItem",
                 "dynamodb:GetItem",
                 "dynamodb:UpdateItem"
             ],
             "Resource": [
                 "arn:aws:dynamodb:*:*:table/table04"
             ]
         }
    ]
}
```

------

## Beispiel 4: Verhindern Sie, dass Informationen bei einem Fehler zurückgegeben werden ConditionCheck
<a name="tx-policy-example-4"></a>

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/table01",
            "Condition": {
                "StringEqualsIfExists": {
                    "dynamodb:ReturnValues": "NONE"
                }
            }
        }
    ]
}
```

------

# DynamoDB-Transaktionen-Beispiel
<a name="transaction-example"></a>

Als Beispiel für eine Situation, in der Amazon DynamoDB Transactions nützlich sein können, betrachten Sie diese Java-Beispielanwendung für eine Online-Marketplace-Site.

Die Anwendung verfügt über drei DynamoDB-Tabellen im Backend:
+ `Customers` – In dieser Tabelle werden Details zu den Marketplace-Kunden gespeichert. Der Primärschlüssel ist ein `CustomerId` eine eindeutige ID.
+ `ProductCatalog` – In dieser Tabelle werden Details wie Preis und Verfügbarkeit zu den Produkten gespeichert, die auf der Marketplace-Site zum Verkauf angeboten werden. Der Primärschlüssel ist ein `ProductId` eine eindeutige ID.
+ `Orders` – In dieser Tabelle werden Details zu Bestellungen von der Marketplace-Site gespeichert. Der Primärschlüssel ist ein `OrderId` eine eindeutige ID.

## Bestellung
<a name="transaction-example-write-order"></a>

Die folgenden Codeausschnitte veranschaulichen, wie DynamoDB-Transaktionen verwendet werden, um die verschiedenen Schritte zu koordinieren, die zum Erstellen und Verarbeiten eines Auftrags erforderlich sind. Durch die Verwendung eines einzigen all-or-nothing Vorgangs wird sichergestellt, dass, falls ein Teil der Transaktion fehlschlägt, keine Aktionen in der Transaktion ausgeführt und keine Änderungen vorgenommen werden.

In diesem Beispiel richten Sie einen Auftrag eines Kunden ein, dessen `customerId` `09e8e9c8-ec48` ist. Anschließend führen Sie sie als einzelne Transaktion aus, indem Sie den folgenden einfachen Workflow für die Auftragsverarbeitung verwenden:

1. Stellen Sie sicher, dass die Kundennummer gültig ist.

1. Stellen Sie sicher, dass das Produkt `IN_STOCK` ist und aktualisieren Sie den Produktstatus auf `SOLD`.

1. Stellen Sie sicher, dass die Bestellung noch nicht vorhanden ist, und erstellen Sie den Auftrag.

### Kunden validieren
<a name="transaction-example-order-part-a"></a>

Definieren Sie zunächst eine Aktion, um zu überprüfen, ob ein Kunde mit `customerId` gleich `09e8e9c8-ec48` in der Kundentabelle vorhanden ist.

```
final String CUSTOMER_TABLE_NAME = "Customers";
final String CUSTOMER_PARTITION_KEY = "CustomerId";
final String customerId = "09e8e9c8-ec48";
final HashMap<String, AttributeValue> customerItemKey = new HashMap<>();
customerItemKey.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));

ConditionCheck checkCustomerValid = new ConditionCheck()
    .withTableName(CUSTOMER_TABLE_NAME)
    .withKey(customerItemKey)
    .withConditionExpression("attribute_exists(" + CUSTOMER_PARTITION_KEY + ")");
```

### Aktualisieren des Produktstatus
<a name="transaction-example-order-part-b"></a>

Definieren Sie als Nächstes eine Aktion, um den Produktstatus auf `SOLD` zu aktualisieren, wenn die Bedingung, auf die der Produktstatus als `IN_STOCK`derzeit festgelegt ist, `true` ist. Das Festlegen des `ReturnValuesOnConditionCheckFailure`-Parameters gibt den Artikel zurück, wenn das Produktstatusattribut des Artikels nicht gleich `IN_STOCK` war.

```
final String PRODUCT_TABLE_NAME = "ProductCatalog";
final String PRODUCT_PARTITION_KEY = "ProductId";
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
expressionAttributeValues.put(":new_status", new AttributeValue("SOLD"));
expressionAttributeValues.put(":expected_status", new AttributeValue("IN_STOCK"));

Update markItemSold = new Update()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey)
    .withUpdateExpression("SET ProductStatus = :new_status")
    .withExpressionAttributeValues(expressionAttributeValues)
    .withConditionExpression("ProductStatus = :expected_status")
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD);
```

### Bestellung erstellen
<a name="transaction-example-order-part-c"></a>

Schließlich erstellen Sie die Bestellung, solange eine Bestellung mit diesem `OrderId` nicht bereits existiert.

```
final String ORDER_PARTITION_KEY = "OrderId";
final String ORDER_TABLE_NAME = "Orders";

HashMap<String, AttributeValue> orderItem = new HashMap<>();
orderItem.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));
orderItem.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));
orderItem.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));
orderItem.put("OrderStatus", new AttributeValue("CONFIRMED"));
orderItem.put("OrderTotal", new AttributeValue("100"));

Put createOrder = new Put()
    .withTableName(ORDER_TABLE_NAME)
    .withItem(orderItem)
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
    .withConditionExpression("attribute_not_exists(" + ORDER_PARTITION_KEY + ")");
```

### Ausführen der Transaktion
<a name="transaction-example-order-part-d"></a>

Das folgende Beispiel zeigt, wie die zuvor als einzelne all-or-nothing Operation definierten Aktionen ausgeführt werden.

```
    Collection<TransactWriteItem> actions = Arrays.asList(
        new TransactWriteItem().withConditionCheck(checkCustomerValid),
        new TransactWriteItem().withUpdate(markItemSold),
        new TransactWriteItem().withPut(createOrder));

    TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
        .withTransactItems(actions)
        .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

    // Run the transaction and process the result.
    try {
        client.transactWriteItems(placeOrderTransaction);
        System.out.println("Transaction Successful");

    } catch (ResourceNotFoundException rnf) {
        System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
    } catch (InternalServerErrorException ise) {
        System.err.println("Internal Server Error" + ise.getMessage());
    } catch (TransactionCanceledException tce) {
        System.out.println("Transaction Canceled " + tce.getMessage());
    }
```

## Lesen der Bestelldetails
<a name="transaction-example-read-order"></a>

Das folgende Beispiel zeigt, wie der abgeschlossene Auftrag transaktional über die `Orders`- und `ProductCatalog`-Tabellen gelesen wird.

```
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

HashMap<String, AttributeValue> orderKey = new HashMap<>();
orderKey.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));

Get readProductSold = new Get()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey);
Get readCreatedOrder = new Get()
    .withTableName(ORDER_TABLE_NAME)
    .withKey(orderKey);

Collection<TransactGetItem> getActions = Arrays.asList(
    new TransactGetItem().withGet(readProductSold),
    new TransactGetItem().withGet(readCreatedOrder));

TransactGetItemsRequest readCompletedOrder = new TransactGetItemsRequest()
    .withTransactItems(getActions)
    .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

// Run the transaction and process the result.
try {
    TransactGetItemsResult result = client.transactGetItems(readCompletedOrder);
    System.out.println(result.getResponses());
} catch (ResourceNotFoundException rnf) {
    System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
} catch (InternalServerErrorException ise) {
    System.err.println("Internal Server Error" + ise.getMessage());
} catch (TransactionCanceledException tce) {
    System.err.println("Transaction Canceled" + tce.getMessage());
}
```

# Ändern der Datenerfassung mit Amazon DynamoDB
<a name="streamsmain"></a>

Viele Anwendungen können zum Zeitpunkt einer Änderung von der Funktion zum Erfassen der Änderungen an den in einer DynamoDB-Tabelle gespeicherten Elementen profitieren. Im Folgenden sehen Sie einige Beispielanwendungsfälle.
+ Eine beliebte mobile App modifiziert Daten in einer DynamoDB-Tabelle mit einer Geschwindigkeit von Tausenden von Aktualisierungen pro Sekunde. Eine andere Anwendung erfasst und speichert Daten über diese Updates und stellt near-real-time Nutzungsmetriken für die mobile App bereit.
+ Eine Finanzanwendung ändert Börsendaten in einer DynamoDB-Tabelle. Verschiedene Anwendungen, die parallel laufen, verfolgen diese Veränderungen in Echtzeit value-at-risk, berechnen Portfolios und gleichen sie automatisch auf der Grundlage von Aktienkursbewegungen neu aus.
+ Sensoren in Transportfahrzeugen und Industrieanlagen senden Daten an eine DynamoDB-Tabelle. Verschiedene Anwendungen überwachen die Leistung und senden Messaging-Warnungen, wenn ein Problem erkannt wird, prognostizieren potenzielle Fehler durch Anwendung von Algorithmen für Machine Learning und komprimieren und archivieren Daten in Amazon Simple Storage Service (Amazon S3).
+ Eine Anwendung sendet Benachrichtigungen automatisch an die Mobilgeräte aller Freunde in einer Gruppe, sobald ein Freund ein neues Bild hochlädt.
+ Ein neuer Kunde fügt einer DynamoDB-Tabelle Daten hinzu. Dieses Ereignis ruft eine andere Anwendung auf, die eine Begrüßungs-E-Mail an den neuen Kunden sendet.

DynamoDB unterstützt das Streaming von Datensätzen für Änderungsdaten auf Elementebene in nahezu Echtzeit. Sie können Anwendungen erstellen, die diese Streams nutzen, und basierend auf dem Inhalt Maßnahmen ergreifen.

**Anmerkung**  
Das Hinzufügen von Tags zu DynamoDB Streams und das Verwenden der [attributbasierte Zugriffskontrolle (ABAC)](access-control-resource-based.md) bei DynamoDB Streams werden nicht unterstützt.

Das folgende Video gibt Ihnen einen einführenden Einblick in das „Change Data Capture“-Konzept.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/VVv_-mZ5Ge8/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/VVv_-mZ5Ge8)


**Topics**
+ [Streaming-Optionen für die Erfassung der Änderung von Daten](#streamsmain.choose)
+ [Verwenden von Kinesis Data Streams zum Erfassen von Änderungen an DynamoDB](kds.md)
+ [Ändern Sie die Datenerfassung für DynamoDB Streams](Streams.md)

## Streaming-Optionen für die Erfassung der Änderung von Daten
<a name="streamsmain.choose"></a>

DynamoDB bietet zwei Streaming-Modelle für die Erfassung der Änderung von Daten: Kinesis Data Streams für DynamoDB und DynamoDB Streams.

Um Ihnen bei der Auswahl der richtigen Lösung für Ihre Anwendung zu helfen, werden die Funktionen der einzelnen Streaming-Modelle in der folgenden Tabelle zusammengefasst. 

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/streamsmain.html)

Sie können beide Streaming-Modelle in derselben DynamoDB-Tabelle aktivieren.

Im folgenden Video wird mehr über die Unterschiede zwischen den beiden Optionen gesprochen.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/UgG17Wh2y0g/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/UgG17Wh2y0g)


# Verwenden von Kinesis Data Streams zum Erfassen von Änderungen an DynamoDB
<a name="kds"></a>

Sie können Amazon Kinesis Data Streams verwenden, um Änderungen an Amazon DynamoDB zu erfassen.

Kinesis Data Streams erfasst Änderungen auf Elementebene in jeder DynamoDB-Tabelle und repliziert sie in einen [Kinesis Data Stream](https://docs.aws.amazon.com/streams/latest/dev/introduction.html). Ihre Anwendungen können auf diesen Stream zugreifen und die Änderungen auf Elementebene nahezu in Echtzeit anzeigen. Sie können kontinuierlich Terabyte an Daten pro Stunde erfassen und speichern. Sie können eine längere Datenaufbewahrungszeit nutzen, und mit der Funktion für erweiterte Rundsendungen können Sie gleichzeitig zwei oder mehr nachgelagerte Anwendungen erreichen. Weitere Vorteile sind zusätzliche Prüfungen und Sicherheitstransparenz.

Mit Kinesis Data Streams haben Sie auch Zugriff auf [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) und [Amazon Managed Service für Apache Flink](https://docs.aws.amazon.com/kinesisanalytics/latest/dev/what-is.html). Diese Services können Sie bei der Erstellung von Anwendungen unterstützen, die Echtzeit-Dashboards betreiben, Warnungen generieren, dynamische Preisgestaltung und Werbung implementieren und ausgefeilte Datenanalysen sowie Algorithmen für maschinelles Lernen umsetzen.

**Anmerkung**  
Die Verwendung von Kinesis-Datenströmen für DynamoDB unterliegt sowohl den [Kinesis Data Streams-Preisen für den Datenstream](https://aws.amazon.com/kinesis/data-streams/pricing/) als auch den [DynamoDB-Preisen](https://aws.amazon.com/dynamodb/pricing/) für die Quelltabelle.

Informationen zum Aktivieren von Kinesis-Streaming in einer DynamoDB-Tabelle mithilfe der Konsole oder des Java-SDK finden Sie unter. AWS CLI[Erste Schritte mit Kinesis Data Streams für Amazon DynamoDB](kds_gettingstarted.md)

**Topics**
+ [Wie Kinesis Data Streams mit DynamoDB funktioniert](#kds_howitworks)
+ [Erste Schritte mit Kinesis Data Streams für Amazon DynamoDB](kds_gettingstarted.md)
+ [Verwenden von Shards und Metriken mit DynamoDB Streams und Kinesis Data Streams](kds_using-shards-and-metrics.md)
+ [Verwendung von IAM-Richtlinien für Amazon Kinesis Data Streams und Amazon DynamoDB](kds_iam.md)

## Wie Kinesis Data Streams mit DynamoDB funktioniert
<a name="kds_howitworks"></a>

Wenn ein Kinesis Data Stream für eine DynamoDB-Tabelle aktiviert ist, sendet die Tabelle einen Datensatz, der alle Änderungen an den Daten dieser Tabelle erfasst. Dieser Datensatz beinhaltet:
+ Die spezifische Uhrzeit, zu der ein Element kürzlich erstellt, aktualisiert oder gelöscht wurde
+ den Primärschlüssel dieses Elements
+ einen Snapshot des Datensatzes vor der Änderung
+ einen Snapshot des Datensatzes nach der Änderung 

Diese Datensätze werden nahezu in Echtzeit erfasst und veröffentlicht. Nachdem sie in den Kinesis Data Stream geschrieben wurden, können sie wie jeder andere Datensatz gelesen werden. Sie können die Kinesis Client Library verwenden AWS Lambda, die Kinesis Data Streams Streams-API verwenden, aufrufen und andere verbundene Dienste verwenden. Weitere Informationen finden Sie unter [Lesen von Daten aus Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html) im Amazon-Kinesis-Data-Streams-Entwicklerhandbuch.

Diese Änderungen an Daten werden ebenfalls asynchron erfasst. Kinesis hat keine Auswirkungen auf die Leistung einer Tabelle, von der es streamt. Die in Ihrem Kinesis Data Stream gespeicherten Streamdatensätze werden auch im Ruhezustand verschlüsselt. Weitere Informationen finden Sie unter [Datenschutz in Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/server-side-encryption.html).

Die Kinesis-Data-Stream-Datensätze werden möglicherweise in einer anderen Reihenfolge angezeigt als vor den Elementänderungen. Dieselben Elementbenachrichtigungen werden möglicherweise auch mehrmals im Stream angezeigt. Sie können das Attribut `ApproximateCreationDateTime` überprüfen, um die Reihenfolge zu ermitteln, in der die Elementänderungen aufgetreten sind, und um doppelte Datensätze zu identifizieren. 

Wenn Sie einen Kinesis Data Stream als Streaming-Ziel einer DynamoDB-Tabelle aktivieren, können Sie die Genauigkeit der `ApproximateCreationDateTime`-Werte entweder in Millisekunden oder Mikrosekunden konfigurieren. Standardmäßig gibt `ApproximateCreationDateTime` den Zeitpunkt der Änderung in Millisekunden an. Darüber hinaus können Sie diesen Wert für ein aktives Streaming-Ziel ändern. Nach einer solchen Aktualisierung weisen in Kinesis geschriebene Stream-Datensätze `ApproximateCreationDateTime`-Werte mit der gewünschten Genauigkeit auf. 

In DynamoDB geschriebene Binärwerte müssen im [Base64-codierten Format](HowItWorks.NamingRulesDataTypes.md) codiert sein. Wenn Datensätze jedoch in einen Kinesis-Datenstrom geschrieben werden, erfolgt eine zweite Codierung dieser codierten Binärwerte mit der Base64-Codierung. Beim Lesen dieser Datensätze aus einem Kinesis-Datenstrom müssen Anwendungen diese Werte zweimal dekodieren, um die rohen Binärwerte abzurufen.

DynamoDB erhebt Gebühren für die Verwendung von Kinesis Data Streams in Änderungsdatenerfassungseinheiten. 1 KB Änderung pro Einzelelement gilt als eine Änderungsdatenerfassungseinheit. Die KB der Änderung in jedem Element wird durch das Größere der „Vorher“- und „Nachher“-Images des in den Stream geschriebenen Elements berechnet, wobei dieselbe Logik wie [capacity unit consumption for write operations](read-write-operations.md#write-operation-consumption) (Verbrauch der Kapazitätseinheit für Schreibvorgänge) verwendet wird. Sie müssen keinen Kapazitätsdurchsatz für Änderungsdatenerfassungseinheiten bereitstellen, ähnlich wie der DynamoDB [on-demand](capacity-mode.md#capacity-mode-on-demand)-Modus funktioniert.

### Aktivieren eines Kinesis Data Streams für Ihre DynamoDB-Tabelle
<a name="kds_howitworks.enabling"></a>

Sie können das Streaming zu Kinesis von Ihrer vorhandenen DynamoDB-Tabelle aus aktivieren oder deaktivieren, indem Sie das AWS-Managementkonsole, das AWS SDK oder das AWS Command Line Interface () verwenden.AWS CLI
+ Sie können nur Daten von DynamoDB zu Kinesis Data Streams in demselben AWS Konto und derselben AWS Region streamen wie Ihre Tabelle. 
+ Sie können nur Daten von einer DynamoDB-Tabelle in einen Kinesis Data Stream streamen.

  

### Vornehmen von Änderungen an einem Kinesis-Data-Streams-Ziel in Ihrer DynamoDB-Tabelle
<a name="kds_howitworks.makingchanges"></a>

Standardmäßig enthalten alle Kinesis-Data-Stream-Datensätze ein `ApproximateCreationDateTime`-Attribut. Dieses Attribut stellt einen Zeitstempel in Millisekunden der ungefähren Zeit dar, zu der jeder Datensatz erstellt wurde. Sie können die Genauigkeit dieser Werte ändern, indem Sie [https://console.aws.amazon.com/kinesis, das SDK oder](https://console.aws.amazon.com/kinesis) das AWS CLI 

# Erste Schritte mit Kinesis Data Streams für Amazon DynamoDB
<a name="kds_gettingstarted"></a>

In diesem Abschnitt wird beschrieben, wie Kinesis Data Streams für Amazon DynamoDB-Tabellen mit der Amazon DynamoDB DynamoDB-Konsole, der AWS Command Line Interface (AWS CLI) und der API verwendet wird.

## Erstellen eines aktiven Amazon-Kinesis-Daten-Streams
<a name="kds_gettingstarted.making-changes"></a>

Alle diese Beispiele verwenden die `Music`-DynamoDB-Tabelle, die als Teil des [Erste Schritte mit DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)-Tutorials erstellt wurde.

Weitere Informationen zum Erstellen von Konsumenten und zum Verbinden Ihres Kinesis Data Streams mit anderen AWS -Services finden Sie unter [Lesen von Daten aus Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html) im *Amazon-Kinesis-Data-Streams-Entwicklerhandbuch*.

**Anmerkung**  
 Wenn Sie zum ersten Mal KDS-Shards verwenden, empfehlen wir, Ihre Shards so einzustellen, dass sie den Nutzungsmustern entsprechend hoch- und herunterskaliert werden. Nachdem Sie mehr Daten zu den Nutzungsmustern gesammelt haben, können Sie die Shards in Ihrem Datenstrom entsprechend anpassen. 

------
#### [ Console ]

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die Kinesis-Konsole unter [https://console.aws.amazon.com/kinesis/](https://console.aws.amazon.com/kinesis/).

1. Klicken Sie auf **Create data stream** (Datenstrom erstellen) und befolgen Sie die Anweisungen, um einen Stream mit dem Namen `samplestream` zu erstellen. 

1. Öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Klicken Sie im Navigationsbereich auf der linken Seite der Konsole auf **Tables** (Tabellen).

1. Wählen Sie die Tabelle **Music** (Musik).

1. Wählen Sie die Registerkarte **Exports and streams** (Exporte und Streams).

1. (Optional) Unter **Details zu Amazon-Kinesis-Daten-Streams** können Sie die Zeitstempelgenauigkeit des Datensatzes von Mikrosekunde (Standard) auf Millisekunde ändern. 

1. Klicken Sie auf **samplestream** aus der Dropdown-Liste.

1. Klicken Sie auf die Schaltfläche **Einschalten**.

------
#### [ AWS CLI ]

1. Erstellen Sie einen Kinesis Data Stream mit dem Namen `samplestream`, indem Sie den [Befehl create-stream](https://docs.aws.amazon.com/cli/latest/reference/kinesis/create-stream.html) wählen.

   ```
   aws kinesis create-stream --stream-name samplestream --shard-count 3 
   ```

   Sehen Sie sich [Überlegungen zur Shard-Verwaltung für Kinesis Data Streams](kds_using-shards-and-metrics.md#kds_using-shards-and-metrics.shardmanagment) an, bevor Sie die Anzahl der Shards für den Kinesis Data Stream festlegen.

1. Überprüfen Sie, ob der Kinesis Stream aktiv und einsatzbereit ist, indem Sie den [Befehl Stream beschreiben](https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html) auswählen.

   ```
   aws kinesis describe-stream --stream-name samplestream
   ```

1. Aktivieren Sie Kinesis-Streaming für die DynamoDB-Tabelle mithilfe des DynamoDB-Befehls `enable-kinesis-streaming-destination`. Ersetzen Sie den `stream-arn`-Wert durch den Wert, der im vorherigen Schritt von `describe-stream` zurückgegeben wurde. Aktivieren Sie optional das Streaming mit einer höheren Genauigkeit (Mikrosekunden) der für jeden Datensatz zurückgegebenen Zeitstempelwerte.

   So aktivieren Sie das Streaming mit einer Zeitstempelgenauigkeit im Mikrosekundenbereich:

   ```
   aws dynamodb enable-kinesis-streaming-destination \
     --table-name Music \
     --stream-arn arn:aws:kinesis:us-west-2:12345678901:stream/samplestream
     --enable-kinesis-streaming-configuration ApproximateCreationDateTimePrecision=MICROSECOND
   ```

   So aktivieren Sie das Streaming mit der standardmäßigen Zeitstempelgenauigkeit (Millisekunde):

   ```
   aws dynamodb enable-kinesis-streaming-destination \
     --table-name Music \
     --stream-arn arn:aws:kinesis:us-west-2:12345678901:stream/samplestream
   ```

1. Überprüfen Sie, ob Kinesis-Streaming in der Tabelle aktiv ist, mithilfe des DynamoDB-`describe-kinesis-streaming-destination`-Befehls.

   ```
   aws dynamodb describe-kinesis-streaming-destination --table-name Music
   ```

1. Schreiben Sie Daten in die DynamoDB-Tabelle mithilfe der `put-item`, wie in dem [Entwicklerhandbuch von DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-2.html) angegeben ist.

   ```
   aws dynamodb put-item \
       --table-name Music  \
       --item \
           '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}'
   
   aws dynamodb put-item \
       --table-name Music \
       --item \
           '{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}, "Awards": {"N": "10"} }'
   ```

1. Verwenden Sie den Kinesis-CLI-Befehl [get-records](https://docs.aws.amazon.com/cli/latest/reference/kinesis/get-records.html), um den Inhalt des Kinesis Streams abzurufen. Verwenden Sie dann den folgenden Codeausschnitt, um den Streaminhalt zu deserialisieren.

   ```
   /**
    * Takes as input a Record fetched from Kinesis and does arbitrary processing as an example.
    */
   public void processRecord(Record kinesisRecord) throws IOException {
       ByteBuffer kdsRecordByteBuffer = kinesisRecord.getData();
       JsonNode rootNode = OBJECT_MAPPER.readTree(kdsRecordByteBuffer.array());
       JsonNode dynamoDBRecord = rootNode.get("dynamodb");
       JsonNode oldItemImage = dynamoDBRecord.get("OldImage");
       JsonNode newItemImage = dynamoDBRecord.get("NewImage");
       Instant recordTimestamp = fetchTimestamp(dynamoDBRecord);
   
       /**
        * Say for example our record contains a String attribute named "stringName" and we want to fetch the value
        * of this attribute from the new item image. The following code fetches this value.
        */
       JsonNode attributeNode = newItemImage.get("stringName");
       JsonNode attributeValueNode = attributeNode.get("S"); // Using DynamoDB "S" type attribute
       String attributeValue = attributeValueNode.textValue();
       System.out.println(attributeValue);
   }
   
   private Instant fetchTimestamp(JsonNode dynamoDBRecord) {
       JsonNode timestampJson = dynamoDBRecord.get("ApproximateCreationDateTime");
       JsonNode timestampPrecisionJson = dynamoDBRecord.get("ApproximateCreationDateTimePrecision");
       if (timestampPrecisionJson != null && timestampPrecisionJson.equals("MICROSECOND")) {
           return Instant.EPOCH.plus(timestampJson.longValue(), ChronoUnit.MICROS);
       }
       return Instant.ofEpochMilli(timestampJson.longValue());
   }
   ```

------
#### [ Java ]

1. Befolgen Sie die Anweisungen im Kinesis-Data-Streams-Entwicklerhandbuch, um einen Kinesis Data Stream mit `samplestream` Java-Namen zu [erstellen](https://docs.aws.amazon.com/streams/latest/dev/kinesis-using-sdk-java-create-stream.html).

   Sehen Sie sich [Überlegungen zur Shard-Verwaltung für Kinesis Data Streams](kds_using-shards-and-metrics.md#kds_using-shards-and-metrics.shardmanagment) an, bevor Sie die Anzahl der Shards für den Kinesis Data Stream festlegen. 

1. Verwenden Sie den folgenden Codeausschnitt, um Kinesis-Streaming für die DynamoDB-Tabelle zu aktivieren. Aktivieren Sie optional das Streaming mit einer höheren Genauigkeit (Mikrosekunden) der für jeden Datensatz zurückgegebenen Zeitstempelwerte. 

   So aktivieren Sie das Streaming mit einer Zeitstempelgenauigkeit im Mikrosekundenbereich:

   ```
   EnableKinesisStreamingConfiguration enableKdsConfig = EnableKinesisStreamingConfiguration.builder()
     .approximateCreationDateTimePrecision(ApproximateCreationDateTimePrecision.MICROSECOND)
     .build();
   
   EnableKinesisStreamingDestinationRequest enableKdsRequest = EnableKinesisStreamingDestinationRequest.builder()
     .tableName(tableName)
     .streamArn(kdsArn)
     .enableKinesisStreamingConfiguration(enableKdsConfig)
     .build();
   
   EnableKinesisStreamingDestinationResponse enableKdsResponse = ddbClient.enableKinesisStreamingDestination(enableKdsRequest);
   ```

   So aktivieren Sie das Streaming mit der standardmäßigen Zeitstempelgenauigkeit (Millisekunde):

   ```
   EnableKinesisStreamingDestinationRequest enableKdsRequest = EnableKinesisStreamingDestinationRequest.builder()
     .tableName(tableName)
     .streamArn(kdsArn)
     .build();
   
   EnableKinesisStreamingDestinationResponse enableKdsResponse = ddbClient.enableKinesisStreamingDestination(enableKdsRequest);
   ```

1. Befolgen Sie die Anweisungen im *Kinesis-Data-Streams-Entwicklerhandbuch*, um aus dem erstellten Datenstrom zu [lesen](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html).

1. Verwenden Sie dann den folgenden Codeausschnitt, um den Streaminhalt zu deserialisieren

   ```
   /**
    * Takes as input a Record fetched from Kinesis and does arbitrary processing as an example.
    */
   public void processRecord(Record kinesisRecord) throws IOException {
       ByteBuffer kdsRecordByteBuffer = kinesisRecord.getData();
       JsonNode rootNode = OBJECT_MAPPER.readTree(kdsRecordByteBuffer.array());
       JsonNode dynamoDBRecord = rootNode.get("dynamodb");
       JsonNode oldItemImage = dynamoDBRecord.get("OldImage");
       JsonNode newItemImage = dynamoDBRecord.get("NewImage");
       Instant recordTimestamp = fetchTimestamp(dynamoDBRecord);
   
       /**
        * Say for example our record contains a String attribute named "stringName" and we wanted to fetch the value
        * of this attribute from the new item image, the below code would fetch this.
        */
       JsonNode attributeNode = newItemImage.get("stringName");
       JsonNode attributeValueNode = attributeNode.get("S"); // Using DynamoDB "S" type attribute
       String attributeValue = attributeValueNode.textValue();
       System.out.println(attributeValue);
   }
   
   private Instant fetchTimestamp(JsonNode dynamoDBRecord) {
       JsonNode timestampJson = dynamoDBRecord.get("ApproximateCreationDateTime");
       JsonNode timestampPrecisionJson = dynamoDBRecord.get("ApproximateCreationDateTimePrecision");
       if (timestampPrecisionJson != null && timestampPrecisionJson.equals("MICROSECOND")) {
           return Instant.EPOCH.plus(timestampJson.longValue(), ChronoUnit.MICROS);
       }
       return Instant.ofEpochMilli(timestampJson.longValue());
   }
   ```

------

## Vornehmen von Änderungen an einem aktiven Amazon-Kinesis-Daten-Stream
<a name="kds_gettingstarted.making-changes"></a>

In diesem Abschnitt wird beschrieben, wie Sie mithilfe der Konsole und der API Änderungen an einem aktiven Kinesis Data Streams for DynamoDB-Setup vornehmen. AWS CLI 

**AWS-Managementkonsole**

1. Öffnen Sie die DynamoDB-Konsole unter [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Öffnen Sie die gewünschte Tabelle.

1. Wählen Sie die Option **Exporte und Streams**.

**AWS CLI**

1. Rufen Sie `describe-kinesis-streaming-destination` auf, um zu bestätigen, dass der Stream `ACTIVE` ist. 

1. Rufen Sie `UpdateKinesisStreamingDestination` auf, wie in diesem Beispiel:

   ```
   aws dynamodb update-kinesis-streaming-destination --table-name enable_test_table --stream-arn arn:aws:kinesis:us-east-1:12345678901:stream/enable_test_stream --update-kinesis-streaming-configuration ApproximateCreationDateTimePrecision=MICROSECOND
   ```

1. Rufen Sie `describe-kinesis-streaming-destination` auf, um zu bestätigen, dass der Stream `UPDATING` ist.

1. Rufen Sie `describe-kinesis-streaming-destination` regelmäßig auf, bis der Streaming-Status wieder `ACTIVE` ist. Normalerweise dauert es bis zu 5 Minuten, bis die Aktualisierungen der Zeitstempelgenauigkeit wirksam werden. Sobald der Status aktualisiert wurde, ist die Änderung abgeschlossen, und der neue Genauigkeitswert wird auf künftige Datensätze angewendet.

1. Schreiben Sie mit `putItem` in die Tabelle.

1. Verwenden Sie den Kinesis-Befehl `get-records`, um den Inhalt des Streams abzurufen.

1. Vergewissern Sie sich, dass die `ApproximateCreationDateTime` der Schreibvorgänge die gewünschte Genauigkeit haben.

**Java-API**

1. Stellen Sie einen Codeausschnitt bereit, der eine `UpdateKinesisStreamingDestination`-Anfrage und eine `UpdateKinesisStreamingDestination`-Antwort erstellt. 

1. Stellen Sie einen Codeausschnitt bereit, der eine `DescribeKinesisStreamingDestination`-Anfrage und eine `DescribeKinesisStreamingDestination response` erstellt.

1. Rufen Sie `describe-kinesis-streaming-destination` regelmäßig auf, bis der Streaming-Status wieder `ACTIVE` ist. Dies zeigt an, dass die Änderung abgeschlossen ist und der neue Genauigkeitswert auf künftige Datensätze angewendet wird.

1. Führen Sie Schreibvorgänge in der Tabelle durch.

1.  Lesen Sie Daten aus dem Stream und deserialisieren Sie den Streaminhalt.

1. Vergewissern Sie sich, dass die `ApproximateCreationDateTime` der Schreibvorgänge die gewünschte Genauigkeit haben.

# Verwenden von Shards und Metriken mit DynamoDB Streams und Kinesis Data Streams
<a name="kds_using-shards-and-metrics"></a>

## Überlegungen zur Shard-Verwaltung für Kinesis Data Streams
<a name="kds_using-shards-and-metrics.shardmanagment"></a>

Ein Kinesis-Daten-Stream zählt seinen Durchsatz in [Shards](https://docs.aws.amazon.com/streams/latest/dev/key-concepts.html). In Amazon Kinesis Data Streams können Sie zwischen einem **On-Demand**-Modus und einem **bereitgestellten** Modus für Ihre Datenströme wählen. 

Wir empfehlen, den On-Demand-Modus für Ihren Kinesis-Daten-Stream zu verwenden, wenn Ihre DynamoDB-Schreib-Workload sehr variabel und unvorhersehbar ist. Im On-Demand-Modus ist keine Kapazitätsplanung erforderlich, da Kinesis Data Streams die Shards automatisch verwaltet, um den erforderlichen Durchsatz bereitzustellen.

Bei vorhersehbaren Workloads können Sie den bereitgestellten Modus für Ihren Kinesis-Daten-Stream verwenden. Im bereitgestellten Modus müssen Sie die Anzahl der Shards für den Datenstrom angeben, um die Datenerfassungsdatensätze der Änderungen aus DynamoDB aufzunehmen. Um die Anzahl der Shards zu ermitteln, die der Kinesis-Daten-Stream für die DynamoDB-Tabelle benötigt, sind folgende Eingabewerte erforderlich:
+ Die durchschnittliche Größe des Datensatzes Ihrer DynamoDB-Tabelle in Byte (`average_record_size_in_bytes`).
+ Die maximale Anzahl von Schreibvorgängen, die Ihre DynamoDB-Tabelle pro Sekunde ausführen wird. Dazu gehören das Erstellen, Löschen und Aktualisieren von Vorgängen, die von Ihren Anwendungen ausgeführt werden, sowie automatisch generierte Vorgänge, z. B. von Time to Live generierte Löschvorgänge (`write_throughput`).
+ Der Prozentsatz der Aktualisierungs- und Überschreibvorgänge, die Sie für Ihre Tabelle ausführen, im Vergleich zu Erstellungs- oder Löschvorgängen (`percentage_of_updates`). Aktualisierungs- und Überschreibvorgänge replizieren sowohl die alten als auch die neuen Images des geänderten Elements in den Stream. Dies erzeugt die doppelte DynamoDB-Elementgröße.

Sie können die Anzahl der Shards (`number_of_shards`), die der Kinesis-Daten-Stream benötigt, mit den Eingabewerte in der folgenden Formel berechnen:

```
number_of_shards = ceiling( max( ((write_throughput * (4+percentage_of_updates) * average_record_size_in_bytes) / 1024 / 1024), (write_throughput/1000)), 1)
```

Nehmen wir an, Sie haben einen maximalen Durchsatz von 1 040 Schreibvorgängen pro Sekunde (`write_throughput`) bei einer durchschnittlichen Datensatzgröße von 800 Byte (`average_record_size_in_bytes)`. Wenn 25 Prozent dieser Schreibvorgänge Aktualisierungsvorgänge sind (`percentage_of_updates`), benötigen Sie zwei Shards (`number_of_shards`) für Ihren DynamoDB-Streaming-Durchsatz:

```
ceiling( max( ((1040 * (4+25/100) * 800)/ 1024 / 1024), (1040/1000)), 1).
```

Beachten Sie Folgendes, bevor Sie die Formel verwenden, um die Anzahl der Shards zu berechnen, die im bereitgestellten Modus für Kinesis-Daten-Streams erforderlich sind:
+ Mit dieser Formel können Sie die Anzahl der Shards abschätzen, die für die Aufnahme Ihrer DynamoDB-Änderungsdatensätze erforderlich sind. Sie stellt nicht die Gesamtzahl der Shards dar, die in Ihrem Kinesis-Daten-Stream benötigt werden, z. B. Shards, die zur Unterstützung zusätzlicher Nutzer von Kinesis-Daten-Streams erforderlich sind.
+ Im Bereitstellungsmodus kann es immer noch zu Ausnahmen beim Lese- und Schreibdurchsatz kommen, wenn Sie Ihren Datenstrom nicht für den Spitzendurchsatz konfigurieren. In diesem Fall müssen Sie Ihren Datenstrom manuell skalieren, um den Datenverkehr zu bewältigen. 
+ Diese Formel berücksichtigt die zusätzliche Überlastung, die von DynamoDB generiert wird, bevor die Änderungsprotokoll-Datensätze an Kinesis Data Streams gestreamt werden.

Weitere Informationen zu den Kapazitätsmodi in Kinesis Data Streams finden Sie unter [Auswahl des Datenstrom-Kapazitätsmodus](https://docs.aws.amazon.com/streams/latest/dev/how-do-i-size-a-stream.html). Weitere Informationen zu den Preisunterschieden zwischen den verschiedenen Kapazitätsmodi finden Sie unter [Amazon Kinesis Data Streams – Preise](https://aws.amazon.com/kinesis/data-streams/pricing/).

## Änderung der Datenerfassung für Kinesis Data Streams überwachen
<a name="kds_using-shards-and-metrics.monitoring"></a>

DynamoDB bietet mehrere CloudWatch Amazon-Metriken, mit denen Sie die Replikation von Change Data Capture nach Kinesis überwachen können. Eine vollständige Liste der CloudWatch Metriken finden Sie unter. [DynamoDB-Metriken und -Dimensionen](metrics-dimensions.md)

Es wird empfohlen, die folgenden Elemente sowohl während der Stream-Aktivierung als auch in der Produktion zu überwachen, um festzustellen, ob der Stream über ausreichende Kapazität verfügt:
+ `ThrottledPutRecordCount`: Die Anzahl der Datensätze, die von Ihrem Kinesis-Daten-Stream aufgrund unzureichender Kinesis-Daten-Stream-Kapazität gedrosselt wurden. Der `ThrottledPutRecordCount` sollte so niedrig wie möglich bleiben, obwohl sie bei außergewöhnlichen Nutzungsspitzen eine gewisse Drosselung erfahren könnten. DynamoDB versucht erneut, gedrosselte Datensätze in das Kinesis Data Stream zu senden. Dies kann jedoch zu einer höheren Replikationslatenz führen. 

  Wenn eine übermäßige und regelmäßige Drosselung auftritt, müssen Sie möglicherweise die Anzahl der Kinesis-Stream-Shards proportional zum beobachteten Schreibdurchsatz Ihrer Tabelle erhöhen. Weitere Informationen zur Bestimmung der Größe eines Kinesis Data Streams finden Sie unter [Bestimmen der anfänglichen Größe eines Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/amazon-kinesis-streams.html#how-do-i-size-a-stream).
+ `AgeOfOldestUnreplicatedRecord`: Die verstrichene Zeit seit der ältesten Änderung auf Elementebene, die noch in den Kinesis Data Stream repliziert wurde, wurde in der DynamoDB-Tabelle angezeigt. Im Normalbetrieb sollte `AgeOfOldestUnreplicatedRecord` in der Reihenfolge von Millisekunden liegen. Diese Zahl wächst aufgrund erfolgloser Replikationsversuche, wenn diese durch kundengesteuerte Konfigurationsoptionen verursacht werden.

   Wenn die Metrik `AgeOfOldestUnreplicatedRecord` 168 Stunden überschreitet, wird die Replikation von Änderungen auf Elementebene aus der DynamoDB-Tabelle in den Kinesis-Daten-Stream automatisch deaktiviert.

  Kundengesteuerte Konfigurationsbeispiele, die zu erfolglosen Replikationsversuchen führen, sind eine zu gering bereitgestellte Kinesis-Daten-Stream-Kapazität, die zu übermäßiger Drosselung führt, oder eine manuelle Aktualisierung der Zugriffsrichtlinien Ihres Kinesis-Daten-Streams, die DynamoDB das Hinzufügen von Daten zu Ihrem Datenstrom verweigern. Um diese Metrik so niedrig wie möglich zu halten, müssen Sie möglicherweise die richtige Bereitstellung Ihrer Kinesis-Daten-Stream-Kapazität sicherstellen und sicherstellen, dass die Berechtigungen von DynamoDB unverändert bleiben. 
+ `FailedToReplicateRecordCount`: Die Anzahl der Datensätze, die DynamoDB nicht in Ihren Kinesis-Datenstrom repliziert hat. Bestimmte Elemente, die größer als 34 KB sind, können sich vergrößern, um Datensätze zu ändern, die größer als die Elementgrößengrenze von 1 MB von Kinesis Data Streams sind. Diese Größenerweiterung tritt auf, wenn diese Elemente, die größer als 34 KB sind, eine große Anzahl von booleschen oder leeren Attributwerten enthalten. Boolesche und leere Attributwerte werden in DynamoDB als 1 Byte gespeichert, erweitern sich jedoch auf bis zu 5 Byte, wenn sie mit Standard-JSON für die Kinesis-Data-Streams-Replikation serialisiert werden. DynamoDB kann solche Änderungsdatensätze nicht in Ihren Kinesis Dats Stream replizieren. DynamoDB überspringt diese Änderungsdatensätze und repliziert automatisch nachfolgende Datensätze. 

   

Sie können CloudWatch Amazon-Alarme erstellen, die eine Amazon Simple Notification Service (Amazon SNS) -Nachricht zur Benachrichtigung senden, wenn eine der oben genannten Metriken einen bestimmten Schwellenwert überschreitet. 

# Verwendung von IAM-Richtlinien für Amazon Kinesis Data Streams und Amazon DynamoDB
<a name="kds_iam"></a>

Wenn Sie Amazon Kinesis Data Streams für Amazon DynamoDB zum ersten Mal aktivieren, erstellt DynamoDB automatisch eine AWS Identity and Access Management (IAM) -Serviceverknüpfte Rolle für Sie. Diese Rolle `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` ermöglicht DynamoDB, die Replikation von Änderungen auf Elementebene in Kinesis Data Streams in Ihrem Auftrag zu verwalten. Löschen Sie diese serviceverknüpfte Rolle nicht.

Weitere Informationen zu serviceverknüpften Rollen finden Sie unter [Verwenden serviceverknüpfter Rollen](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) im *IAM-Benutzerhandbuch*.

**Anmerkung**  
DynamoDB unterstützt keine Tag-basierten Bedingungen für IAM-Richtlinien.

Damit Sie Amazon Kinesis Data Streams für Amazon DynamoDB aktivieren können, benötigen Sie die folgenden Berechtigungen für die Tabelle:
+ `dynamodb:EnableKinesisStreamingDestination`
+ `kinesis:ListStreams`
+ `kinesis:PutRecords`
+ `kinesis:DescribeStream`

Wenn Sie Amazon Kinesis Data Streams für Amazon DynamoDB für eine bestimmte DynamoDB-Tabelle beschreiben möchten, benötigen Sie die folgenden Berechtigungen für die Tabelle.
+ `dynamodb:DescribeKinesisStreamingDestination`
+ `kinesis:DescribeStreamSummary`
+ `kinesis:DescribeStream`

Damit Sie Amazon Kinesis Data Streams für Amazon DynamoDB deaktivieren können, benötigen Sie die folgenden Berechtigungen für die Tabelle.
+ `dynamodb:DisableKinesisStreamingDestination`

Damit Sie Amazon Kinesis Data Streams für Amazon DynamoDB aktualisieren können, benötigen Sie die folgenden Berechtigungen für die Tabelle.
+ `dynamodb:UpdateKinesisStreamingDestination`

Die folgenden Beispiele zeigen, wie IAM-Richtlinien verwendet werden, um Berechtigungen für Amazon Kinesis Data Streams für Amazon DynamoDB zu erteilen.

## Beispiel: Aktivieren von Amazon Kinesis Data Streams für Amazon DynamoDB
<a name="access-policy-kds-example1"></a>

Über die folgende IAM-Richtlinie werden die nötigen Berechtigungen eingeräumt, um Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle zu aktivieren. Sie gewährt keine Berechtigungen zum Deaktivieren, Aktualisieren oder Beschreiben von Kinesis Data Streams for DynamoDB für die `Music`-Tabelle. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "arn:aws:iam::*:role/aws-service-role/kinesisreplication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBKinesisDataStreamsReplication",
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": "kinesisreplication.dynamodb.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:EnableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Beispiel: Aktualisieren von Amazon Kinesis Data Streams für Amazon DynamoDB
<a name="access-policy-kds-example2"></a>

Über die folgende IAM-Richtlinie werden die nötigen Berechtigungen eingeräumt, um Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle zu aktualisieren. Sie gewährt keine Berechtigungen zum Aktivieren, Deaktivieren oder Beschreiben von Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:UpdateKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Beispiel: Deaktivieren von Amazon Kinesis Data Streams für Amazon DynamoDB
<a name="access-policy-kds-example2"></a>

Über die folgende IAM-Richtlinie werden die nötigen Berechtigungen eingeräumt, um Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle zu deaktivieren. Sie gewährt keine Berechtigungen zum Aktivieren, Aktualisieren oder Beschreiben von Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DisableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Beispiel: Selektives Anwenden von Berechtigungen für Amazon Kinesis Data Streams für Amazon DynamoDB basierend auf Ressource
<a name="access-policy-kds-example3"></a>

Über die folgende IAM-Richtlinie werden Berechtigungen zum Aktivieren und Beschreiben von Amazon Kinesis Data Streams für Amazon DynamoDB für die `Music`-Tabelle eingeräumt und Berechtigungen zum Deaktivieren von Amazon Kinesis Data Streams für Amazon DynamoDB für die Tabelle `Orders` verweigert. 

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:EnableKinesisStreamingDestination",
                "dynamodb:DescribeKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        },
        {
            "Effect": "Deny",
            "Action": [
                "dynamodb:DisableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Orders"
        }
    ]
}
```

------

## Verwenden von serviceverknüpften Rollen für Kinesis Data Streams für DynamoDB
<a name="kds-service-linked-roles"></a>

[Amazon Kinesis Data Streams für Amazon DynamoDB verwendet AWS Identity and Access Management (IAM) service-verknüpfte Rollen.](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-service-linked-role) Eine serviceverknüpfte Rolle ist ein spezieller Typ einer IAM-Rolle, die direkt mit Kinesis Data Streams für DynamoDB verknüpft ist. Dienstbezogene Rollen sind von Kinesis Data Streams for DynamoDB vordefiniert und beinhalten alle Berechtigungen, die der Dienst benötigt, um andere AWS Dienste in Ihrem Namen aufzurufen. 

Eine serviceverknüpfte Rolle vereinfacht das Einrichten von Kinesis Data Streams für DynamoDB, da Sie die erforderlichen Berechtigungen nicht manuell hinzufügen müssen. Kinesis Data Streams für DynamoDB definiert die Berechtigungen seiner serviceverknüpften Rollen. Sofern keine andere Einstellung festgelegt wurde, können nur Kinesis Data Streams für DynamoDB die Rollen übernehmen. Die definierten Berechtigungen umfassen die Vertrauens- und Berechtigungsrichtlinie. Diese Berechtigungsrichtlinie kann keinen anderen IAM-Entitäten zugewiesen werden.

Informationen zu anderen Services, die serviceverknüpften Rollen unterstützen, finden Sie unter [AWS -Services, die mit IAM funktionieren](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html). Suchen Sie nach den Services, für die **Ja** in der Spalte **Serviceverknüpfte Rolle** angegeben ist. Wählen Sie über einen Link **Yes** (Ja) aus, um die Dokumentation zu einer servicegebundenen Rolle für diesen Service anzuzeigen.

### Berechtigungen von serviceverknüpften Rollen für Kinesis Data Streams für DynamoDB
<a name="slr-permissions"></a>

Kinesis Data Streams for DynamoDB verwendet die mit dem Service verknüpfte Rolle namens. **AWSServiceRoleForDynamoDBKinesisDataStreamsReplication** Die serviceverknüpfte Rolle ermöglicht es Amazon DynamoDB, in Ihrem Namen die Replikation von Änderungen auf Elementebene in Kinesis Data Streams zu verwalten.

Die serviceverknüpfte Rolle `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` vertraut darauf, dass die folgenden Services die Rolle annehmen:
+ `kinesisreplication.dynamodb.amazonaws.com`

Die Richtlinie für Rollenberechtigungen erlaubt Kinesis Data Streams für DynamoDB die folgenden Aktionen auf den angegebenen Ressourcen durchzuführen:
+ Aktion: `Put records and describe` für `Kinesis stream`
+ Aktion: `Generate data keys` aktiviert, um Daten `AWS KMS` in Kinesis-Streams zu speichern, die mit benutzergenerierten AWS KMS Schlüsseln verschlüsselt sind.

[Den genauen Inhalt des Richtliniendokuments finden Sie unter Dynamo. DBKinesis ReplicationServiceRolePolicy](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/aws-service-role/DynamoDBKinesisReplicationServiceRolePolicy)

Sie müssen Berechtigungen konfigurieren, damit eine juristische Stelle von IAM (z. B. Benutzer, Gruppe oder Rolle) eine serviceverknüpfte Rolle erstellen, bearbeiten oder löschen kann. Weitere Informationen finden Sie unter [serviceverknüpfte Rollenberechtigungen](https://docs.aws.amazon.com/IAM/latest/UserGuide/contributorinsights-service-linked-roles.html#service-linked-role-permissions) im *IAM-Benutzerhandbuch*.

### Erstellen einer serviceverknüpften Rolle für Kinesis Data Streams für DynamoDB
<a name="create-slr"></a>

Sie müssen eine serviceverknüpfte Rolle nicht manuell erstellen. Wenn Sie Kinesis Data Streams for DynamoDB in der AWS-Managementkonsole, der oder der AWS API aktivieren, erstellt Kinesis Data Streams for DynamoDB die serviceverknüpfte Rolle für Sie. AWS CLI

Wenn Sie diese serviceverknüpfte Rolle löschen und sie dann erneut erstellen müssen, können Sie dasselbe Verfahren anwenden, um die Rolle in Ihrem Konto neu anzulegen. Wenn Sie Kinesis Data Streams für DynamoDB aktivieren, erstellt Kinesis Data Streams für DynamoDB die serviceverknüpfte Rolle erneut für Sie. 

### Bearbeiten einer serviceverknüpften Rolle für Kinesis Data Streams für DynamoDB
<a name="edit-slr"></a>

Kinesis Data Streams für DynamoDB ermöglicht es Ihnen nicht, die mit der `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` serviceverknüpfte Rolle zu bearbeiten. Da möglicherweise verschiedene Entitäten auf die Rolle verweisen, kann der Rollenname nach dem Erstellen einer serviceverknüpften Rolle nicht mehr geändert werden. Sie können jedoch die Beschreibung der Rolle mit IAM bearbeiten. Weitere Informationen finden Sie unter [Bearbeiten einer serviceverknüpften Rolle](https://docs.aws.amazon.com/IAM/latest/UserGuide/contributorinsights-service-linked-roles.html#edit-service-linked-role) im *IAM-Benutzerhandbuch*.

### Löschen einer serviceverknüpften Rolle für Kinesis Data Streams für DynamoDB
<a name="delete-slr"></a>

Sie können auch die IAM-Konsole, die AWS CLI oder die API verwenden, um die serviceverknüpfte Rolle manuell zu löschen AWS . Sie müssen jedoch die Ressourcen für Ihre serviceverknüpfte Rolle zuerst manuell bereinigen, bevor Sie diese manuell löschen können.

**Anmerkung**  
Wenn der Kinesis Data Streams für DynamoDB-Service die Rolle verwendet, wenn Sie versuchen, die Ressourcen zu löschen, schlägt das Löschen möglicherweise fehl. Wenn dies passiert, warten Sie einige Minuten und versuchen Sie es erneut.

**So löschen Sie die serviceverknüpfte Rolle mit IAM**

Verwenden Sie die IAM-Konsole, die oder die AWS API AWS CLI, um die serviceverknüpfte Rolle zu löschen. `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` Weitere Informationen finden Sie unter [Löschen einer serviceverknüpften Rolle](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) im *IAM-Leitfaden*.

# Ändern Sie die Datenerfassung für DynamoDB Streams
<a name="Streams"></a>

 DynamoDB Streams erfasst eine zeitlich geordnete Abfolge von Änderungen auf Elementebene in jeder beliebigen DynamoDB-Tabelle und speichert diese Informationen bis zu 24 Stunden. Anwendungen können auf dieses Protokoll zugreifen und die Datenelemente vor und nach der Änderung nahezu in Echtzeit aufrufen.

 Die Verschlüsselung ruhender Daten verschlüsselt die Daten in DynamoDB Streams. Weitere Informationen finden Sie unter [Ruhende DynamoDB-Verschlüsselung](EncryptionAtRest.md).

Ein *DynamoDB-Stream* ist ein strukturierter Informationsfluss zu Elementänderungen in einer DynamoDB-Tabelle. Wenn Sie den Stream für eine Tabelle aktivieren, werden von DynamoDB Informationen über jede Änderung an den Datenelementen in der Tabelle erfasst.

Wenn eine Anwendung Elemente in der Tabelle erstellt, aktualisiert oder löscht, schreibt DynamoDB Streams einen Stream-Datensatz mit dem bzw. den Primärschlüsselattributen der Elemente, die geändert wurden. Ein *Stream-Datensatz* enthält Informationen über eine Datenänderung an einem einzelnen Element einer DynamoDB-Tabelle. Sie können den Stream konfigurieren, sodass die Stream-Datensätze zusätzliche Informationen erfassen, z. B. Images der geänderten Elemente vor und nach der Änderung.

Mit DynamoDB Streams wird Folgendes sichergestellt:
+ Jeder Stream-Datensatz erscheint genau einmal im Stream.
+ Für jedes Element, das in einer DynamoDB-Tabelle geändert wird, erscheinen die Stream-Datensätze in der gleichen Reihenfolge wie die tatsächlichen Änderungen des Elements.

DynamoDB Streams schreibt Stream-Datensätze nahezu in Echtzeit, sodass Sie Anwendungen erstellen können, die diese Streams verbrauchen und basierend auf den Inhalten Aktionen einleiten.

**Topics**
+ [Endpunkte für DynamoDB Streams](#Streams.Endpoints)
+ [Aktivieren eines Streams](#Streams.Enabling)
+ [Lesen und Verarbeiten eines Streams](#Streams.Processing)
+ [DynamoDB Streams und Time to Live (TTL)](time-to-live-ttl-streams.md)
+ [Verwenden des DynamoDB-Streams-Kinesis-Adapters zum Verarbeiten von Stream-Datensätzen](Streams.KCLAdapter.md)
+ [DynamoDB-Streams-Low-Level-API: Java-Beispiel](Streams.LowLevel.Walkthrough.md)
+ [DynamoDB Streams und -Trigger AWS Lambda](Streams.Lambda.md)
+ [DynamoDB Streams und Apache Flink](StreamsApacheFlink.xml.md)

## Endpunkte für DynamoDB Streams
<a name="Streams.Endpoints"></a>

AWS verwaltet separate Endpunkte für DynamoDB- und DynamoDB Streams. Für die Arbeit mit Datenbanktabellen und Indexen muss Ihre Anwendung auf einen DynamoDB-Endpunkt zugreifen. Um DynamoDB-Streams-Datensätze zu lesen und zu verarbeiten, muss die Anwendung auf einen DynamoDB-Streams-Endpunkt in derselben Region zugreifen.

DynamoDB Streams bietet zwei Gruppen von Endpunkten. Diese sind:
+ **IPv4-only Endpoints: Endpoints** mit der Benennungskonvention. `streams.dynamodb.<region>.amazonaws.com`
+ **Dual-Stack-Endpunkte**: Neue Endpunkte, die sowohl mit als auch kompatibel sind IPv4 und IPv6 der Namenskonvention folgen. `streams-dynamodb.<region>.api.aws`

**Anmerkung**  
Eine vollständige Liste der DynamoDB- und DynamoDB-Streams-Regionen und Endpunkte finden Sie unter [Regionen und Endpunkte](https://docs.aws.amazon.com/general/latest/gr/rande.html) in der *Allgemeine AWS-Referenz*.

 AWS SDKs Sie bieten separate Clients für DynamoDB- und DynamoDB Streams. Je nach Anforderung kann die Anwendung auf einen DynamoDB-Endpunkt, einen DynamoDB-Streams-Endpunkt oder beide gleichzeitig zugreifen. Für die Verbindung mit beiden Endpunkten muss Ihre Anwendung zwei Clients instanziieren, und zwar einen für DynamoDB und einen für DynamoDB Streams.

## Aktivieren eines Streams
<a name="Streams.Enabling"></a>

Sie können einen Stream in einer neuen Tabelle aktivieren, wenn Sie ihn mit der AWS CLI oder einer der folgenden Optionen erstellen. AWS SDKs Außerdem können Sie einen Stream in einer vorhandenen Tabelle aktivieren oder deaktivieren oder die Einstellungen eines Streams ändern. DynamoDB Streams wird asynchron betrieben. Daher wirkt es sich nicht auf die Leistung der Tabelle aus, wenn Sie einen Stream aktivieren.

Die einfachste Möglichkeit zum Verwalten von DynamoDB Streams bietet die AWS-Managementkonsole.

1. Melden Sie sich bei der an AWS-Managementkonsole und öffnen Sie die DynamoDB-Konsole unter. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Wählen Sie im Dashboard der DynamoDB-Konsole die Option **Tables** (Tabellen) aus und wählen Sie eine vorhandene Tabelle aus.

1. Wählen Sie die Registerkarte **Exports and streams** (Exporte und Streams).

1. Wählen Sie im Abschnitt **Details zum DynamoDB-Stream** die Option **Einschalten** aus.

1. Wählen Sie auf der Seite **DynamoDB-Stream einschalten** die Informationen aus, die in den Stream geschrieben werden sollen, sobald Daten in der Tabelle geändert werden:
   + **Nur Schlüsselattribute** – nur die Schlüsselattribute des geänderten Elements.
   + **Neues Image** – das gesamte Element wie es nach der Änderung erscheint.
   + **Altes Image** – das gesamte Element wie es vor der Änderung erscheint.
   + **Neues und altes Image** – sowohl das neue als auch das alte Image des Elements.

   Wenn Sie die gewünschten Einstellungen vorgenommen haben, wählen Sie **Stream einschalten** aus.

1. (Optional) Um einen vorhandenen Stream zu deaktivieren, wählen Sie unter **Details zum DynamoDB-Stream** die Option **Deaktivieren** aus.

Sie können auch die `CreateTable`- oder `UpdateTable`-API-Operationen zum Aktivieren oder Ändern eines Streams verwenden. Der Parameter `StreamSpecification` bestimmt, wie der Stream konfiguriert wird:
+ `StreamEnabled` – gibt an, ob ein Stream für die Tabelle aktiviert (`true`) oder deaktiviert (`false`) ist.
+ `StreamViewType` – legt die Informationen fest, die in den Stream geschrieben werden, sobald Daten in der Tabelle geändert werden:
  + `KEYS_ONLY` – nur die Schlüsselattribute des geänderten Elements.
  + `NEW_IMAGE` – das gesamte Element, wie es nach der Änderung erscheint.
  + `OLD_IMAGE` – das gesamte Element, wie es vor der Änderung erscheint.
  + `NEW_AND_OLD_IMAGES` – sowohl das neue als auch das alte Image des Elements.

Sie können einen Stream jederzeit aktivieren oder deaktivieren. Wenn Sie versuchen, einen Stream für eine Tabelle zu aktivieren, die bereits über einen Stream verfügt, erhalten Sie jedoch eine `ValidationException`. Wenn Sie versuchen, einen Stream für eine Tabelle zu deaktivieren, die nicht über einen Stream verfügt, erhalten Sie auch eine `ValidationException`.

Wenn Sie `StreamEnabled` auf `true` festlegen, erstellt DynamoDB einen neuen Stream mit einem zugewiesenen, eindeutigen Stream-Deskriptor. Wenn Sie einen Stream in der Tabelle deaktivieren und anschließend erneut aktivieren, wird ein neuer Stream mit einem anderen Stream-Deskriptor erstellt.

Jeder Stream wird anhand eines Amazon-Ressourcennamens (ARN) eindeutig identifiziert. Nachfolgend ist ein Beispiel-ARN für einen Stream in einer DynamoDB-Tabelle mit dem Namen `TestTable` aufgeführt:

```
arn:aws:dynamodb:us-west-2:111122223333:table/TestTable/stream/2015-05-11T21:21:33.291
```

Um den aktuellen Stream-Deskriptor für eine Tabelle zu bestimmen, erstellen Sie eine DynamoDB-Anforderung `DescribeTable` und suchen das Element `LatestStreamArn` in der Antwort.

**Anmerkung**  
Es ist nicht möglich, ein `StreamViewType` zu bearbeiten, sobald ein Stream eingerichtet wurde. Wenn Sie nach der Einrichtung Änderungen an einem Stream vornehmen möchten, müssen Sie den aktuellen Stream deaktivieren und einen neuen erstellen.

## Lesen und Verarbeiten eines Streams
<a name="Streams.Processing"></a>

Zum Lesen und Verarbeiten eines Streams muss Ihre Anwendung eine Verbindung mit einem DynamoDB-Streams-Endpunkt herstellen und API-Anforderungen ausgeben.

Ein Stream besteht aus *Stream-Datensätzen*. Jeder Stream-Datensatz stellt eine einzelne Datenänderung in der DynamoDB-Tabelle dar, zu der der Stream gehört. Jedem Stream-Datensatz ist eine Sequenznummer zugewiesen, wodurch die Reihenfolge dargestellt wird, in der der Datensatz im Stream veröffentlicht wurde.

Stream-Datensätze werden in Gruppen oder *Shards* verwaltet. Jeder Shard fungiert als Container für mehrere Stream-Datensätze und enthält Informationen, die zum Abrufen und Durchlaufen dieser Datensätze erforderlich sind. Die Stream-Datensätze in einem Shard werden nach 24 Stunden automatisch entfernt.

Shards sind flüchtig, d. h., sie werden nach Bedarf automatisch erstellt und gelöscht. Jeder Shard kann in mehrere neue Shards unterteilt werden. Dieser Vorgang erfolgt automatisch. (Es ist auch möglich, dass ein übergeordneter Shard nur einen untergeordneten Shard besitzt.) Ein Shard kann aufgrund hoher Schreibaktivitäten in der übergeordneten Tabelle aufgeteilt werden, sodass Anwendungen Datensätze aus mehreren Shards parallel verarbeiten können.

Wenn Sie einen Stream deaktivieren, werden alle offenen Shards geschlossen. Die Daten im Stream bleiben 24 Stunden lang lesbar.

Da Shards hierarchisch (über- und untergeordnet) aufgebaut sind, müssen Anwendungen einen übergeordneten Shard immer vor einem untergeordneten Shard verarbeiten. So wird sichergestellt, dass die Stream-Datensätze ebenfalls in der richtigen Reihenfolge verarbeitet werden. (Wenn Sie den DynamoDB-Streams-Kinesis-Adapter verwenden, wird dies für Sie erledigt. Ihre Anwendung verarbeitet die Shards und Streamdatensätze in der richtigen Reihenfolge. Es verarbeitet automatisch neue oder abgelaufene Shards sowie Shards, die sich während der Ausführung der Anwendung teilen. Weitere Informationen finden Sie unter [Verwenden des DynamoDB-Streams-Kinesis-Adapters zum Verarbeiten von Stream-Datensätzen](Streams.KCLAdapter.md).)

Das folgende Diagramm zeigt die Beziehung zwischen einem Stream, Shards im Stream und Stream-Datensätzen in den Shards.

![\[Struktur von DynamoDB Streams. Stream-Datensätze, die Datenänderungen darstellen, sind in Shards organisiert.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/streams-terminology.png)


**Anmerkung**  
Wenn Sie eine `PutItem` oder `UpdateItem` Operation ausführen, mit der keine Daten in einem Element geändert werden, schreibt DynamoDB Streams *keinen* Stream-Datensatz für diese Operation.

Um auf einen Stream zuzugreifen und die darin enthaltenen Stream-Datensätze zu verarbeiten, führen Sie die folgenden Schritte aus:
+ Ermitteln Sie den eindeutigen ARN des Streams, auf den Sie zugreifen möchten.
+ Bestimmen Sie, welcher bzw. welche Shards im Stream die gewünschten Stream-Datensätze enthalten.
+ Greifen Sie auf den bzw. die Shards zu und rufen Sie die gewünschten Stream-Datensätze ab.

**Anmerkung**  
Es sollten nicht mehr als zwei Prozesse gleichzeitig aus dem Shard desselben Streams lesen. Wenn mehr als zwei Leser pro Shard vorhanden sind, kann eine Drosselung die Folge sein.

Die DynamoDB Streams-API bietet die folgenden Aktionen zur Verwendung durch Anwendungsprogramme:
+  `[ListStreams](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_ListStreams.html)` – Gibt eine Liste der Stream-Deskriptoren für das aktuelle Konto und den Endpunkt zurück. Sie können optional nur die Stream-Deskriptoren für einen bestimmten Tabellennamen anfordern.
+ `[DescribeStream](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_DescribeStream.html)` – Gibt Informationen über einen Stream zurück, z. B. den aktuellen Status des Streams, seinen Amazon-Ressourcennamen (ARN), die Zusammenstellung der Shards und die zugehörige DynamoDB-Tabelle. Sie können das Feld `ShardFilter` optional verwenden, um den vorhandenen untergeordneten Shard abzurufen, der dem übergeordneten Shard zugeordnet ist.
+ `[GetShardIterator](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_GetShardIterator.html)` – Gibt einen *Shard Iterator* zurück, der eine Position innerhalb eines Shards beschreibt. Sie können anfordern, dass der Iterator Zugriff auf den ältesten Punkt, den neuesten Punkt oder einen bestimmten Punkt im Stream bereitstellt.
+ `[GetRecords](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_GetRecords.html)` – Gibt die Stream-Datensätze innerhalb eines bestimmten Shards zurück. Sie müssen den von einer `GetShardIterator`-Anforderung zurückgegebenen Shard Iterator angeben.

Eine detaillierte Beschreibung dieser API-Aktionen, einschließlich Anforderungs- und Antwortbeispielen, finden Sie unter [Amazon-DynamoDB-Streams-API-Referenz](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB_Streams.html).

### Shard-Erkennung
<a name="Streams.ShardDiscovery"></a>



Mit zwei leistungsstarken Methoden können Sie neue Shards in Ihrem DynamoDB-Stream erkennen. Als Nutzer von Amazon DynamoDB Streams haben Sie zwei effektive Möglichkeiten, neue Shards zu verfolgen und zu identifizieren:

**Abfragen der gesamten Stream-Topologie**  
Verwenden Sie die `DescribeStream`-API, um den Stream regelmäßig abzufragen. Dadurch werden alle Shards im Stream zurückgegeben, einschließlich aller neu erstellten Shards. Indem Sie die Ergebnisse im Zeitverlauf vergleichen, können Sie neu hinzugefügte Shards erkennen.

**Erkennen untergeordneter Shards**  
Verwenden Sie die `DescribeStream`-API mit dem Parameter `ShardFilter`, um eine Teilmenge von Shards zu finden. Wenn Sie in der Anfrage einen übergeordneten Shard benennen, gibt DynamoDB Streams seine unmittelbar untergeordneten Shards zurück. Dieser Ansatz ist nützlich, wenn Sie nur die Herkunft der Shards verfolgen müssen, ohne den gesamten Stream zu scannen.   
Anwendungen, die Daten aus DynamoDB Streams aufnehmen, können mithilfe dieses `ShardFilter`-Parameters effizient vom Lesen eines geschlossenen Shards zum zugehörigen untergeordneten Shard übergehen. Dadurch werden wiederholte Aufrufe der `DescribeStream`-API vermieden, um die Shard-Zuordnung für alle geschlossenen und offenen Shards abzurufen und zu durchlaufen. So können untergeordnete Shards schnell erkannt werden, nachdem ein übergeordneter Shard geschlossen wurde. Auf diese Weise werden Stream-Verarbeitungsanwendungen reaktionsschneller und kostengünstiger.

Mit beiden Methoden können Sie den Überblick über die sich entwickelnde Struktur Ihrer DynamoDB Streams behalten, um keine wichtigen Datenaktualisierungen oder Shard-Änderungen zu verpassen.

### Datenaufbewahrungsfrist für DynamoDB Streams
<a name="Streams.DataRetention"></a>

Alle Daten in DynamoDB Streams unterliegen einer 24-Stunden-Nutzungsdauer. Sie können die Aktivitäten der letzten 24 Stunden für eine bestimmte Tabelle abrufen und analysieren. Daten, die älter als 24 Stunden sind, können jedoch jederzeit entfernt werden.

Wenn Sie einen Stream in einer Tabelle deaktivieren, bleiben die Daten im Stream 24 Stunden lang lesbar. Nach Ablauf dieses Zeitraums verfallen die Daten und die Stream-Datensätze werden automatisch gelöscht. Es gibt keinen Mechanismus zum manuellen Löschen eines vorhandenen Streams. Sie müssen nur warten, bis die Aufbewahrungsfrist abgelaufen ist (24 Stunden) und alle Stream-Datensätze gelöscht werden.

# DynamoDB Streams und Time to Live (TTL)
<a name="time-to-live-ttl-streams"></a>

Sie können Elemente, die durch die [Gültigkeitsdauer](TTL.md) (TTL) gelöscht wurden, sichern oder anderweitig verarbeiten, indem Sie Amazon DynamoDB Streams in der Tabelle aktivieren und die Streams-Datensätze der abgelaufenen Elemente verarbeiten. Weitere Informationen finden Sie unter [Lesen und Verarbeiten eines Streams](Streams.md#Streams.Processing).

Der Stream-Datensatz enthält ein Benutzeridentitätsfeld `Records[<index>].userIdentity`.

Die Elemente, die nach Ablauf durch den Gültigkeitsdauer-Prozess gelöscht wurden, haben die folgenden Felder:
+ `Records[<index>].userIdentity.type`

  `"Service"`
+ `Records[<index>].userIdentity.principalId`

  `"dynamodb.amazonaws.com"`

**Anmerkung**  
Wenn Sie TTL in einer globalen Tabelle verwenden, wird das Feld `userIdentity` für die Region, in der die TTL ausgeführt wurde, festgelegt. Dieses Feld wird in anderen Regionen nicht festgelegt, wenn der Löschvorgang repliziert wird.

Der folgende JSON-Ausdruck zeigt den relevanten Teil eines einzelnen Stream-Datensatzes.

```
"Records": [
    {
        ...

        "userIdentity": {
            "type": "Service",
            "principalId": "dynamodb.amazonaws.com"
        }

        ...

    }
]
```

## Verwenden von DynamoDB Streams und Lambda zum Archivieren von TTL-gelöschten Elementen
<a name="streams-archive-ttl-deleted-items"></a>

Die Kombination von [DynamoDB Time to Live (TTL)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html), [DynamoDB Streams](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html) und [AWS -Lambda](https://aws.amazon.com/lambda/) kann dazu beitragen, die Archivierung von Daten zu vereinfachen, die DynamoDB-Speicherkosten zu senken und die Codekomplexität zu reduzieren. Die Verwendung von Lambda als Stream-Konsument bietet viele Vorteile, insbesondere geringere Kosten im Vergleich zu anderen Konsumenten wie der Kinesis Client Library (KCL). `GetRecords`-API-Aufrufe in Ihrem DynamoDB-Stream werden Ihnen nicht in Rechnung gestellt, wenn Sie Lambda zum Verarbeiten von Ereignissen verwenden, und Lambda kann eine Ereignisfilterung bieten, indem es JSON-Muster in einem Stream-Ereignis identifiziert. Bei der Inhaltsfilterung nach Ereignismustern können Sie bis zu fünf verschiedene Filter definieren, um zu steuern, welche Ereignisse zur Verarbeitung an Lambda gesendet werden. Dies hilft, die Zahl der Aufrufe Ihrer Lambda-Funktionen zu reduzieren, den Code zu vereinfachen und die Gesamtkosten zu senken.

Zwar enthält DynamoDB Streams alle Datenänderungen, beispielsweise `Create`-, `Modify`- und `Remove`-Aktionen, dies kann jedoch zu unerwünschten Aufrufen Ihrer Lambda-Archivfunktion führen. Angenommen, Sie verfügen über eine Tabelle mit 2 Millionen Datenänderungen pro Stunde, die in den Stream fließen. Allerdings handelt es sich bei weniger als 5 Prozent dieser Änderungen um Elementlöschungen, die während des TTL-Prozesses ablaufen und archiviert werden müssen. Bei Verwendung von [Lambda-Ereignisquellenfiltern](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) wird die Lambda-Funktion nur 100 000-mal pro Stunde aufgerufen. Infolge der Ereignisfilterung werden Ihnen anstelle der 2 Millionen Aufrufe, die Sie ohne Ereignisfilterung hätten, nur die erforderlichen Aufrufe in Rechnung gestellt.

Die Ereignisfilterung wird auf die [Lambda-Ereignisquellenzuweisung](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html), angewendet. Hierbei handelt es sich um eine Ressource, die aus einem ausgewählten Ereignis – dem DynamoDB-Stream – Daten liest und eine Lambda-Funktion aufruft. Im folgenden Diagramm ist zu sehen, wie ein durch Time to Live gelöschtes Element von einer Lambda-Funktion unter Verwendung von Streams und Ereignisfiltern verarbeitet wird.

![\[Ein durch den TTL-Prozess gelöschtes Element startet eine Lambda-Funktion, die Streams und Ereignisfilter verwendet.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/streams-lambda-ttl.png)


### Ereignisfiltermuster für DynamoDB Time to Live
<a name="ttl-event-filter-pattern"></a>

Durch Hinzufügen der folgenden JSON zu den [Filterkriterien](https://docs.aws.amazon.com/lambda/latest/dg/API_FilterCriteria.html) für Ihre Ereignisquellenzuweisung kann Ihre Lambda-Funktion nur für TTL-gelöschte Elemente aufgerufen werden:

```
{
    "Filters": [
        {
            "Pattern": { "userIdentity": { "type": ["Service"], "principalId": ["dynamodb.amazonaws.com"] } }
        }
    ]
}
```

### AWS Lambda Erstellen Sie eine Zuordnung der Ereignisquellen
<a name="create-event-source-mapping"></a>

Verwenden Sie die folgenden Codeausschnitte, um eine gefilterte Ereignisquellenzuweisung zu erstellen, die Sie mit dem DynamoDB-Stream einer Tabelle verbinden können. Jeder Codeblock enthält das Ereignisfiltermuster.

------
#### [ AWS CLI ]

```
aws lambda create-event-source-mapping \
--event-source-arn 'arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000' \
--batch-size 10 \
--enabled \
--function-name test_func \
--starting-position LATEST \
--filter-criteria '{"Filters": [{"Pattern": "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}"}]}'
```

------
#### [ Java ]

```
LambdaClient client = LambdaClient.builder()
        .region(Region.EU_WEST_1)
        .build();

Filter userIdentity = Filter.builder()
        .pattern("{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}")
        .build();

FilterCriteria filterCriteria = FilterCriteria.builder()
        .filters(userIdentity)
        .build();

CreateEventSourceMappingRequest mappingRequest = CreateEventSourceMappingRequest.builder()
        .eventSourceArn("arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000")
        .batchSize(10)
        .enabled(Boolean.TRUE)
        .functionName("test_func")
        .startingPosition("LATEST")
        .filterCriteria(filterCriteria)
        .build();

try{
    CreateEventSourceMappingResponse eventSourceMappingResponse = client.createEventSourceMapping(mappingRequest);
    System.out.println("The mapping ARN is "+eventSourceMappingResponse.eventSourceArn());

}catch (ServiceException e){
    System.out.println(e.getMessage());
}
```

------
#### [ Node ]

```
const client = new LambdaClient({ region: "eu-west-1" });

const input = {
    EventSourceArn: "arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000",
    BatchSize: 10,
    Enabled: true,
    FunctionName: "test_func",
    StartingPosition: "LATEST",
    FilterCriteria: { "Filters": [{ "Pattern": "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}" }] }
}

const command = new CreateEventSourceMappingCommand(input);

try {
    const results = await client.send(command);
    console.log(results);
} catch (err) {
    console.error(err);
}
```

------
#### [ Python ]

```
session = boto3.session.Session(region_name = 'eu-west-1')
client = session.client('lambda')

try:
    response = client.create_event_source_mapping(
        EventSourceArn='arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000',
        BatchSize=10,
        Enabled=True,
        FunctionName='test_func',
        StartingPosition='LATEST',
        FilterCriteria={
            'Filters': [
                {
                    'Pattern': "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}"
                },
            ]
        }
    )
    print(response)
except Exception as e:
    print(e)
```

------
#### [ JSON ]

```
{
  "userIdentity": {
     "type": ["Service"],
     "principalId": ["dynamodb.amazonaws.com"]
   }
}
```

------

# Verwenden des DynamoDB-Streams-Kinesis-Adapters zum Verarbeiten von Stream-Datensätzen
<a name="Streams.KCLAdapter"></a>

Die Verwendung des Amazon-Kinesis-Adapters ist die empfohlene Methode zum Verwenden von Streams aus Amazon DynamoDB. Die DynamoDB-Streams-API ist absichtlich ähnlich gestaltet wie die von Kinesis Data Streams. In beiden Services bestehen die Daten-Streams aus Shards. Dieses sind Container für Stream-Datensätze. Beide Dienste APIs enthalten`ListStreams`, `DescribeStream``GetShards`, und `GetShardIterator` Operationen. (Diese DynamoDB-Streams-Aktionen ähneln ihren Gegenstücken in Kinesis Data Streams, sind jedoch nicht vollkommen identisch.)

Als DynamoDB-Streams-Benutzer können Sie das Entwurfsmuster in der KCL zum Verarbeiten von DynamoDB-Streams-Shards und Stream-Datensätzen verwenden. Verwenden Sie dazu den DynamoDB-Streams-Kinesis-Adapter. Der Kinesis-Adapter implementiert die Kinesis-Data-Streams-Schnittstelle so, dass die KCL zum Verwenden und Verarbeiten von Datensätzen aus DynamoDB Streams eingesetzt werden kann. [Anweisungen zur Einrichtung und Installation des DynamoDB Streams Kinesis Adapters finden Sie im Repository. GitHub](https://github.com/awslabs/dynamodb-streams-kinesis-adapter)

Sie können Anwendungen für Kinesis Data Streams mit der Kinesis Client Library (KCL) schreiben. Die KCL vereinfacht die Codierung durch Bereitstellen nützlicher Abstraktionen oberhalb der Low-Level-Kinesis-Data-Streams-API. Weitere Informationen zur KCL finden Sie im [Entwickeln von Konsumenten mit der Kinesis-Client-Library](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) im *Entwicklerhandbuch zu Amazon Kinesis Data Streams*.

DynamoDB empfiehlt die Verwendung von KCL Version 3.x mit AWS SDK for Java v2.x. [Die aktuelle Version 1.x des DynamoDB Streams Kinesis Adapters mit AWS SDK für AWS SDK für Java v1.x wird während des gesamten Lebenszyklus weiterhin vollständig unterstützt, wie dies während der Übergangsphase gemäß den Wartungsrichtlinien für Tools vorgesehen war.AWS SDKs ](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html)

**Anmerkung**  
Die Versionen 1.x und 2.x der Amazon Kinesis Client Library (KCL) sind veraltet. KCL 1.x wird am 30. Januar 2026 verfügbar sein. end-of-support Wir empfehlen dringend, KCL-Anwendungen, die Version 1.x verwenden, vor dem 30. Januar 2026 zur neuesten KCL-Version zu migrieren. Die neueste KCL-Version finden Sie auf der Seite [Amazon Kinesis Client Library](https://github.com/awslabs/amazon-kinesis-client) unter. GitHub Weitere Informationen zur aktuellen Versionen finden Sie unter [Use Kinesis Client Library](https://docs.aws.amazon.com/streams/latest/dev/kcl.html). Weitere Informationen zur Migration von KCL 1.x zu KCL 3.x finden Sie unter „Migrating from KCL 1.x to KCL 3.x“.

Das folgende Diagramm zeigt, wie diese Bibliotheken miteinander interagieren.

![\[Interaktion zwischen DynamoDB Streams, Kinesis Data Streams und KCL zur Verarbeitung von DynamoDB-Streams-Datensätzen.\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/streams-kinesis-adapter.png)


Wenn Sie den DynamoDB-Streams-Kinesis-Adapter eingerichtet haben, können Sie die Entwicklung mit der KCL-Schnittstelle starten, wobei die API-Aufrufe nahtlos an den DynamoDB-Streams-Endpunkt gerichtet werden.

Beim Start der Anwendung wird die KCL aufgerufen, einen Worker zu instanziieren. Sie müssen dem Worker Konfigurationsinformationen für die Anwendung, wie z. B. den Stream-Deskriptor und die AWS Anmeldeinformationen, sowie den Namen einer von Ihnen angegebenen Datensatzprozessorklasse zur Verfügung stellen. Da der Code im Datensatzprozessor ausgeführt wird, erledigt der Worker die folgenden Aufgaben:
+ Stellt eine Verbindung mit dem Stream her
+ Listet die Shards innerhalb des Streams auf
+ Überprüft und listet untergeordnete Shards eines geschlossenen übergeordneten Shards innerhalb des Streams auf
+ Koordiniert Shard-Zuordnungen mit anderen Auftragnehmern (wenn vorhanden)
+ Instanziiert einen Datensatzverarbeiter für jeden Shard, der verwaltet wird
+ Ruft Datensätze aus dem Stream per Pull ab
+ Skaliert die GetRecords API-Aufrufrate bei hohem Durchsatz (wenn der Nachholmodus konfiguriert ist)
+ Überträgt per Push Datensätze an den entsprechenden Datensatzverarbeiter
+ Verwendet Checkpoints für verarbeitete Datensätze
+ Gleicht Shard-Auftragnehmer-Zuordnungen aus, wenn die Auftragnehmer-Instance Änderungen zählt
+ Gleicht Shard-Worker-Zuordnungen aus, wenn Shards aufgeteilt werden

Der KCL-Adapter unterstützt den Catch-up-Modus, eine Funktion zur automatischen Anpassung der Anrufrate zur Bewältigung vorübergehender Durchsatzerhöhungen. Wenn die Verzögerung bei der Stream-Verarbeitung einen konfigurierbaren Schwellenwert (standardmäßig eine Minute) überschreitet, skaliert der Aufholmodus die GetRecords API-Aufruffrequenz um einen konfigurierbaren Wert (Standard 3x), um Datensätze schneller abzurufen, und kehrt dann zum Normalzustand zurück, sobald die Verzögerung nachlässt. Dies ist in Zeiten mit hohem Durchsatz nützlich, in denen DynamoDB-Schreibaktivitäten die Verbraucher bei Verwendung der Standardabfrageraten überfordern können. Der Nachholmodus kann über den Konfigurationsparameter aktiviert werden (Standardeinstellung falsch). `catchupEnabled`

**Anmerkung**  
Eine Beschreibung der hier aufgeführten KCL-Konzepte finden Sie unter [Entwickeln von Konsumenten mithilfe der Kinesis-Clientbibliothek](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) im *Amazon-Kinesis-Data-Streams-Entwicklerhandbuch*.  
Weitere Informationen zur Verwendung von Streams mit AWS Lambda [DynamoDB Streams und -Trigger AWS Lambda](Streams.Lambda.md)

# Migrieren von KCL 1.x zu KCL 3.x
<a name="streams-migrating-kcl"></a>

## -Übersicht
<a name="migrating-kcl-overview"></a>

In dieser Anleitung wird erläutert, wie Sie Ihre Verbraucheranwendung von KCL 1.x zu KCL 3.x migrieren. Aufgrund der unterschiedlichen Architektur von KCL 1.x und KCL 3.x müssen für die Migration mehrere Komponenten aktualisiert werden, um die Kompatibilität sicherzustellen.

KCL 1.x verwendet im Vergleich zu KCL 3.x andere Klassen und Schnittstellen. Sie müssen zuerst die Klassen „Datensatzprozessor“, „Datensatzprozessor-Factory“ und „Worker“ in das KCL 3.x-kompatible Format migrieren und dann die Schritte für die Migration von KCL 1.x zu KCL 3.x ausführen.

## Schritte zur Migration
<a name="migration-steps"></a>

**Topics**
+ [Schritt 1: Migrieren des Datensatzprozessors](#step1-record-processor)
+ [Schritt 2: Migrieren der Datensatzprozessor-Factory](#step2-record-processor-factory)
+ [Schritt 3: Migrieren des Workers](#step3-worker-migration)
+ [Schritt 4: Überblick über die Konfiguration und Empfehlungen für KCL 3.x](#step4-configuration-migration)
+ [Schritt 5: Migrieren von KCL 2.x zu KCL 3.x](#step5-kcl2-to-kcl3)

### Schritt 1: Migrieren des Datensatzprozessors
<a name="step1-record-processor"></a>

Das folgende Beispiel zeigt einen Datensatzprozessor, der für die Version KCL 1.x des DynamoDB-Streams-Kinesis-Adapters implementiert wurde:

```
package com.amazonaws.kcl;

import com.amazonaws.services.kinesis.clientlibrary.exceptions.InvalidStateException;
import com.amazonaws.services.kinesis.clientlibrary.exceptions.ShutdownException;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorCheckpointer;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware;
import com.amazonaws.services.kinesis.clientlibrary.lib.worker.ShutdownReason;
import com.amazonaws.services.kinesis.clientlibrary.types.InitializationInput;
import com.amazonaws.services.kinesis.clientlibrary.types.ProcessRecordsInput;
import com.amazonaws.services.kinesis.clientlibrary.types.ShutdownInput;

public class StreamsRecordProcessor implements IRecordProcessor, IShutdownNotificationAware {
    @Override
    public void initialize(InitializationInput initializationInput) {
        //
        // Setup record processor
        //
    }

    @Override
    public void processRecords(ProcessRecordsInput processRecordsInput) {
        for (Record record : processRecordsInput.getRecords()) {
            String data = new String(record.getData().array(), Charset.forName("UTF-8"));
            System.out.println(data);
            if (record instanceof RecordAdapter) {
                // record processing and checkpointing logic
            }
        }
    }

    @Override
    public void shutdown(ShutdownInput shutdownInput) {
        if (shutdownInput.getShutdownReason() == ShutdownReason.TERMINATE) {
            try {
                shutdownInput.getCheckpointer().checkpoint();
            } catch (ShutdownException | InvalidStateException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void shutdownRequested(IRecordProcessorCheckpointer checkpointer) {
        try {
            checkpointer.checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow exception
            //
            e.printStackTrace();
        }
    }
}
```

**Um die RecordProcessor Klasse zu migrieren**

1. Ändern Sie die Schnittstellen von `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor` und `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware` folgendermaßen zu `com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor`:

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
   // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware;
   
   import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
   ```

1. Aktualisieren Sie die Importanweisungen für die Methoden `initialize` und `processRecords`:

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.types.InitializationInput;
   import software.amazon.kinesis.lifecycle.events.InitializationInput;
   
   // import com.amazonaws.services.kinesis.clientlibrary.types.ProcessRecordsInput;
   import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
   ```

1. Ersetzen Sie die Methode `shutdownRequested` durch die folgenden neuen Methoden: `leaseLost`, `shardEnded` und `shutdownRequested`.

   ```
   //    @Override
   //    public void shutdownRequested(IRecordProcessorCheckpointer checkpointer) {
   //        //
   //        // This is moved to shardEnded(...) and shutdownRequested(ShutdownReauestedInput)
   //        //
   //        try {
   //            checkpointer.checkpoint();
   //        } catch (ShutdownException | InvalidStateException e) {
   //            //
   //            // Swallow exception
   //            //
   //            e.printStackTrace();
   //        }
   //    }
   
       @Override
       public void leaseLost(LeaseLostInput leaseLostInput) {
   
       }
   
       @Override
       public void shardEnded(ShardEndedInput shardEndedInput) {
           try {
               shardEndedInput.checkpointer().checkpoint();
           } catch (ShutdownException | InvalidStateException e) {
               //
               // Swallow the exception
               //
               e.printStackTrace();
           }
       }
   
       @Override
       public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
           try {
               shutdownRequestedInput.checkpointer().checkpoint();
           } catch (ShutdownException | InvalidStateException e) {
               //
               // Swallow the exception
               //
               e.printStackTrace();
           }
       }
   ```

Nachstehend finden Sie die aktualisierte Version der Datensatzprozessorklasse:

```
package com.amazonaws.codesamples;

import software.amazon.kinesis.exceptions.InvalidStateException;
import software.amazon.kinesis.exceptions.ShutdownException;
import software.amazon.kinesis.lifecycle.events.InitializationInput;
import software.amazon.kinesis.lifecycle.events.LeaseLostInput;
import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
import software.amazon.kinesis.lifecycle.events.ShardEndedInput;
import software.amazon.kinesis.lifecycle.events.ShutdownRequestedInput;
import software.amazon.dynamodb.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import software.amazon.dynamodb.streamsadapter.adapter.DynamoDBStreamsKinesisClientRecord;
import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import com.amazonaws.services.dynamodbv2.streamsadapter.adapter.DynamoDBStreamsClientRecord;
import software.amazon.awssdk.services.dynamodb.model.Record;

public class StreamsRecordProcessor implements DynamoDBStreamsShardRecordProcessor {

    @Override
    public void initialize(InitializationInput initializationInput) {
        
    }

    @Override
    public void processRecords(DynamoDBStreamsProcessRecordsInput processRecordsInput) {
        for (DynamoDBStreamsKinesisClientRecord record: processRecordsInput.records())
            Record ddbRecord = record.getRecord();
            // processing and checkpointing logic for the ddbRecord
        }
    }

    @Override
    public void leaseLost(LeaseLostInput leaseLostInput) {
        
    }

    @Override
    public void shardEnded(ShardEndedInput shardEndedInput) {
        try {
            shardEndedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow the exception
            //
            e.printStackTrace();
        }
    }

    @Override
    public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
        try {
            shutdownRequestedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow the exception
            //
            e.printStackTrace();
        }
    }
}
```

**Anmerkung**  
DynamoDB Streams Kinesis Adapter verwendet SDKv2 jetzt das Record-Modell. In SDKv2 geben komplexe `AttributeValue` Objekte (`BS`,,, `NS` `M``L`,`SS`) niemals Null zurück. Verwenden Sie die Methoden `hasBs()`, `hasNs()`, `hasM()`, `hasL()`, `hasSs()`, um zu überprüfen, ob diese Werte existieren.

### Schritt 2: Migrieren der Datensatzprozessor-Factory
<a name="step2-record-processor-factory"></a>

Die Datensatzprozessor-Factory ist für das Erstellen von Prozessoren verantwortlich, wenn eine Lease erworben wird. Nachfolgend sehen Sie ein Beispiel für eine KCL-1.x-Factory:

```
package com.amazonaws.codesamples;

import software.amazon.dynamodb.AmazonDynamoDB;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory;

public class StreamsRecordProcessorFactory implements IRecordProcessorFactory {
    
    @Override
    public IRecordProcessor createProcessor() {
        return new StreamsRecordProcessor(dynamoDBClient, tableName);
    }
}
```

**So migrieren Sie die `RecordProcessorFactory`**
+ Ändern Sie die implementierte Schnittstelle von `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory` folgendermaßen zu `software.amazon.kinesis.processor.ShardRecordProcessorFactory`:

  ```
  // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
  import software.amazon.kinesis.processor.ShardRecordProcessor;
  
  // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory;
  import software.amazon.kinesis.processor.ShardRecordProcessorFactory;
  
  // public class TestRecordProcessorFactory implements IRecordProcessorFactory {
  public class StreamsRecordProcessorFactory implements ShardRecordProcessorFactory {
  
  Change the return signature for createProcessor.
  
  // public IRecordProcessor createProcessor() {
  public ShardRecordProcessor shardRecordProcessor() {
  ```

Nachfolgend sehen Sie ein Beispiel für die Datensatzprozessor-Factory in 3.0:

```
package com.amazonaws.codesamples;

import software.amazon.kinesis.processor.ShardRecordProcessor;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;

public class StreamsRecordProcessorFactory implements ShardRecordProcessorFactory {

    @Override
    public ShardRecordProcessor shardRecordProcessor() {
        return new StreamsRecordProcessor();
    }
}
```

### Schritt 3: Migrieren des Workers
<a name="step3-worker-migration"></a>

In Version 3.0 der KCL wird die **Worker**-Klasse durch eine neue Klasse namens **Scheduler** ersetzt. Nachfolgend sehen Sie ein Beispiel für einen KCL-1.x-Worker.

```
final KinesisClientLibConfiguration config = new KinesisClientLibConfiguration(...)
final IRecordProcessorFactory recordProcessorFactory = new RecordProcessorFactory();
final Worker worker = StreamsWorkerFactory.createDynamoDbStreamsWorker(
        recordProcessorFactory,
        workerConfig,
        adapterClient,
        amazonDynamoDB,
        amazonCloudWatchClient);
```

**So migrieren Sie den Worker**

1. Ändern Sie die `import`-Anweisung für die `Worker`-Klasse in die Import-Anweisungen für die Klassen `Scheduler` und `ConfigsBuilder`.

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker;
   import software.amazon.kinesis.coordinator.Scheduler;
   import software.amazon.kinesis.common.ConfigsBuilder;
   ```

1. Importieren Sie `StreamTracker` und ändern Sie den Import von `StreamsWorkerFactory` zu `StreamsSchedulerFactory`.

   ```
   import software.amazon.kinesis.processor.StreamTracker;
   // import software.amazon.dynamodb.streamsadapter.StreamsWorkerFactory;
   import software.amazon.dynamodb.streamsadapter.StreamsSchedulerFactory;
   ```

1. Wählen Sie die Position, von der aus die Anwendung gestartet werden soll. Möglich sind `TRIM_HORIZON` oder `LATEST`.

   ```
   import software.amazon.kinesis.common.InitialPositionInStream;
   import software.amazon.kinesis.common.InitialPositionInStreamExtended;
   ```

1. Erstellen Sie eine `StreamTracker`-Instance.

   ```
   StreamTracker streamTracker = StreamsSchedulerFactory.createSingleStreamTracker(
           streamArn,
           InitialPositionInStreamExtended.newInitialPosition(InitialPositionInStream.TRIM_HORIZON)
   );
   ```

1. Erstellen Sie das Objekt `AmazonDynamoDBStreamsAdapterClient`.

   ```
   import software.amazon.dynamodb.streamsadapter.AmazonDynamoDBStreamsAdapterClient; 
   import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
   import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
   
   ...
   
   AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create();
   
   AmazonDynamoDBStreamsAdapterClient adapterClient = new AmazonDynamoDBStreamsAdapterClient(
           credentialsProvider, awsRegion);
   ```

1. Erstellen Sie das Objekt `ConfigsBuilder`.

   ```
   import software.amazon.kinesis.common.ConfigsBuilder;
   
   ...
   ConfigsBuilder configsBuilder = new ConfigsBuilder(
                   streamTracker,
                   applicationName,
                   adapterClient,
                   dynamoDbAsyncClient,
                   cloudWatchAsyncClient,
                   UUID.randomUUID().toString(),
                   new StreamsRecordProcessorFactory());
   ```

1. Erstellen Sie den `Scheduler` mithilfe von `ConfigsBuilder`, wie im folgenden Beispiel gezeigt:

   ```
   import java.util.UUID;
   
   import software.amazon.awssdk.regions.Region;
   import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
   import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
   import software.amazon.awssdk.services.kinesis.KinesisAsyncClient;
   
   import software.amazon.kinesis.common.KinesisClientUtil;
   import software.amazon.kinesis.coordinator.Scheduler;
   
   ...
   
                   
   DynamoDbAsyncClient dynamoClient = DynamoDbAsyncClient.builder().region(region).build();
   CloudWatchAsyncClient cloudWatchClient = CloudWatchAsyncClient.builder().region(region).build();
   
                   
   DynamoDBStreamsPollingConfig pollingConfig = new DynamoDBStreamsPollingConfig(adapterClient);
   pollingConfig.idleTimeBetweenReadsInMillis(idleTimeBetweenReadsInMillis);
   
   // Use ConfigsBuilder to configure settings
   RetrievalConfig retrievalConfig = configsBuilder.retrievalConfig();
   retrievalConfig.retrievalSpecificConfig(pollingConfig);
   
   CoordinatorConfig coordinatorConfig = configsBuilder.coordinatorConfig();
   coordinatorConfig.clientVersionConfig(CoordinatorConfig.ClientVersionConfig.CLIENT_VERSION_CONFIG_COMPATIBLE_WITH_2X);
                   
   Scheduler scheduler = StreamsSchedulerFactory.createScheduler(
                   configsBuilder.checkpointConfig(),
                   coordinatorConfig,
                   configsBuilder.leaseManagementConfig(),
                   configsBuilder.lifecycleConfig(),
                   configsBuilder.metricsConfig(),
                   configsBuilder.processorConfig(),
                   retrievalConfig,
                   adapterClient
           );
   ```

**Wichtig**  
Die Einstellung `CLIENT_VERSION_CONFIG_COMPATIBLE_WITH_2X` gewährleistet die Kompatibilität zwischen dem DynamoDB-Streams-Kinesis-Adapter für KCL v3 und KCL v1, nicht zwischen KCL v2 und v3.

### Schritt 4: Überblick über die Konfiguration und Empfehlungen für KCL 3.x
<a name="step4-configuration-migration"></a>

Eine ausführliche Beschreibung der nach KCL 1.x eingeführten Konfigurationen, die für KCL 3.x relevant sind, finden Sie unter [KCL Configurations](https://docs.aws.amazon.com//streams/latest/dev/kcl-configuration.html) und [KCL Migration Client Configuration](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration.html#client-configuration).

**Wichtig**  
Anstatt Objekte von `checkpointConfig`, `coordinatorConfig`, `leaseManagementConfig`, `metricsConfig`, `processorConfig` und `retrievalConfig` direkt zu erstellen, empfehlen wir, `ConfigsBuilder` zu verwenden, um Konfigurationen in KCL 3.x und aktuelleren Versionen einzustellen. Das verhindert Probleme mit der Scheduler-Initialisierung. `ConfigsBuilder` bietet eine flexiblere und wartungsfreundlichere Methode zur Konfiguration Ihrer KCL-Anwendung.

#### Konfigurationen mit dem Standardwert für Aktualisierungen in KCL 3.x
<a name="kcl3-configuration-overview"></a>

`billingMode`  
In der KCL-Version 1.x ist der Standardwert für `billingMode` auf `PROVISIONED` eingestellt. Bei der KCL-Version 3.x ist die Standardeinstellung für `billingMode` jedoch `PAY_PER_REQUEST` (On-Demand-Modus). Wir empfehlen Ihnen, den On-Demand-Kapazitätsmodus für Ihre Leasetabelle zu verwenden, um die Kapazität automatisch an die Nutzung anzupassen. Anleitungen zur Verwendung der bereitgestellten Kapazität für Ihre Leasetabellen finden Sie unter [Best practices for the lease table with provisioned capacity mode](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration-lease-table.html).

`idleTimeBetweenReadsInMillis`  
In der KCL-Version 1.x ist der Standardwert für `idleTimeBetweenReadsInMillis` auf 1 000 (oder 1 Sekunde) eingestellt. Die KCL-Version 3.x legt den Standardwert für `dleTimeBetweenReadsInMillis` auf 1 500 (oder 1,5 Sekunden) fest. Der Amazon-DynamoDB-Streams-Kinesis-Adapter überschreibt den Standardwert jedoch mit 1 000 (oder 1 Sekunde).

#### Neue Konfigurationen in KCL 3.x
<a name="kcl3-new-configs"></a>

`leaseAssignmentIntervalMillis`  
Diese Konfiguration definiert das Zeitintervall, bis die Verarbeitung neu erkannter Shards beginnt. Es wird nach der Formel 1,5 × `leaseAssignmentIntervalMillis` berechnet. Wenn diese Einstellung nicht explizit konfiguriert ist, beträgt das Zeitintervall standardmäßig 1,5 × `failoverTimeMillis`. Die Verarbeitung neuer Shards beinhaltet das Scannen der Leasetabelle und das Abfragen eines globalen sekundären Index (GSI) in der Leasetabelle. Eine Absenkung des `leaseAssignmentIntervalMillis`-Werts erhöht die Häufigkeit dieser Scan- und Abfragevorgänge, was zu höheren DynamoDB-Kosten führt. Wir empfehlen, diesen Wert auf 2 000 (oder 2 Sekunden) einzustellen, um die Verzögerung bei der Verarbeitung neuer Shards zu minimieren.

`shardConsumerDispatchPollIntervalMillis`  
Diese Konfiguration definiert das Intervall zwischen aufeinanderfolgenden Abfragen durch den Shard-Verbraucher, um Zustandsübergänge auszulösen. In KCL-Version 1.x wurde dieses Verhalten durch den Parameter `idleTimeInMillis` gesteuert, der nicht als konfigurierbare Einstellung verfügbar war. Bei KCL-Version 3.x empfehlen wir, diese Konfiguration auf den Wert einzustellen, der in Ihrer KCL-Version 1.x für ` idleTimeInMillis` verwendet wurde.

### Schritt 5: Migrieren von KCL 2.x zu KCL 3.x
<a name="step5-kcl2-to-kcl3"></a>

Um für einen reibungslosen Übergang und Kompatibilität mit der neuesten Version der Kinesis Client Library (KCL) zu sorgen, folgen Sie den Schritten 5–8 der Anleitung für das [Upgrade von KCL 2.x auf KCL 3.x](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration-from-2-3.html#kcl-migration-from-2-3-worker-metrics) im Migrationsleitfaden.

Informationen zur Fehlerbehebung in KCL 3.x finden Sie unter [Troubleshooting KCL consumer applications](https://docs.aws.amazon.com//streams/latest/dev/troubleshooting-consumers.html).

# Rollback zu einer früheren KCL-Version
<a name="kcl-migration-rollback"></a>

In diesem Abschnitt wird erläutert, wie Sie Ihre Verbraucheranwendung auf die vorherige KCL-Version zurücksetzen können. Der Rollback-Prozess besteht aus zwei Schritten:

1. Führen Sie das [KCL Migration Tool](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py) aus.

1. Stellen Sie den Code der vorherigen KCL-Version erneut bereit.

## Schritt 1: Ausführen des KCL Migration Tools
<a name="kcl-migration-rollback-step1"></a>

Wenn Sie zur vorherigen KCL-Version zurückkehren möchten, müssen Sie das KCL Migration Tool ausführen. Das Tool erfüllt zwei wichtige Aufgaben:
+ Es entfernt die Metadatentabelle für Worker-Metriken und den globalen sekundären Index aus der Leasetabelle in DynamoDB. Diese Artefakte werden von KCL 3.x erstellt, werden aber nicht benötigt, wenn Sie zur vorherigen Version zurückkehren.
+ Dadurch werden alle Worker in einem mit KCL 1.x kompatiblen Modus ausgeführt und verwenden wieder den Load-Balancing-Algorithmus aus früheren KCL-Versionen. Eventuelle Probleme mit dem neuen Load-Balancing-Algorithmus in KCL 3.x werden dadurch sofort behoben.

**Wichtig**  
Die Koordinatorstatustabelle in DynamoDB muss vorhanden sein und darf während des Migrations-, Rollback- und Rollforward-Prozesses nicht gelöscht werden.

**Anmerkung**  
Es ist wichtig, dass alle Worker in Ihrer Verbraucheranwendung zu einem bestimmten Zeitpunkt denselben Load-Balancing-Algorithmus verwenden. Das KCL Migration Tool sorgt dafür, dass alle Worker in Ihrer KCL-3.x-Verbraucheranwendung in den KCL-1.x-kompatiblen Modus wechseln. So führen alle Worker während des Rollbacks zur vorherigen KCL-Version denselben Load-Balancing-Algorithmus aus.

Sie können das [KCL-Migrationstool](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py) im Skriptverzeichnis des [ GitHubKCL-Repositorys](https://github.com/awslabs/amazon-kinesis-client/tree/master) herunterladen. Führen Sie das Skript über einen Worker oder Host aus, der berechtigt ist, in die Koordinatorstatustabelle, die Tabelle mit den Worker-Metriken und die Leasetabelle zu schreiben. Stellen Sie sicher, dass die entsprechenden [IAM-Berechtigungen](https://docs.aws.amazon.com/streams/latest/dev/kcl-iam-permissions.html) für KCL-Verbraucheranwendungen konfiguriert sind. Führen Sie das Skript mit dem folgenden Befehl nur einmal pro KCL-Anwendung aus:

```
python3 ./KclMigrationTool.py --region region --mode rollback [--application_name applicationName] [--lease_table_name leaseTableName] [--coordinator_state_table_name coordinatorStateTableName] [--worker_metrics_table_name workerMetricsTableName]
```

### Parameters
<a name="kcl-migration-rollback-parameters"></a>

`--region`  
Ersetze es durch *region* dein. AWS-Region

`--application_name`  
Dieser Parameter ist erforderlich, wenn Sie Standardnamen für Ihre DynamoDB-Metadatentabellen (Leasetabelle, Koordinatorstatustabelle und Worker-Metriktabelle) verwenden. Wenn Sie benutzerdefinierte Namen für diese Tabellen festgelegt haben, können Sie diesen Parameter weglassen. *applicationName*Ersetzen Sie es durch Ihren tatsächlichen KCL-Anwendungsnamen. Das Tool verwendet diesen Namen, um die Standardtabellennamen abzuleiten, wenn keine benutzerdefinierten Namen angegeben werden.

`--lease_table_name`  
Dieser Parameter wird benötigt, wenn Sie in Ihrer KCL-Konfiguration einen benutzerdefinierten Namen für die Leasetabelle festgelegt haben. Wenn Sie den Standardtabellennamen verwenden, können Sie diesen Parameter weglassen. *leaseTableName*Ersetzen Sie durch den benutzerdefinierten Tabellennamen, den Sie für Ihre Leasingtabelle angegeben haben.

`--coordinator_state_table_name`  
Dieser Parameter wird benötigt, wenn Sie in Ihrer KCL-Konfiguration einen benutzerdefinierten Namen für die Koordinatorstatustabelle festgelegt haben. Wenn Sie den Standardtabellennamen verwenden, können Sie diesen Parameter weglassen. *coordinatorStateTableName*Ersetzen Sie es durch den benutzerdefinierten Tabellennamen, den Sie für Ihre Koordinatorstatentabelle angegeben haben.

`--worker_metrics_table_name`  
Dieser Parameter wird benötigt, wenn Sie in Ihrer KCL-Konfiguration einen benutzerdefinierten Namen für die Worker-Metriktabelle festgelegt haben. Wenn Sie den Standardtabellennamen verwenden, können Sie diesen Parameter weglassen. *workerMetricsTableName*Ersetzen Sie es durch den Namen der benutzerdefinierten Tabelle, den Sie für Ihre Tabelle mit Arbeitskennzahlen angegeben haben.

## Schritt 2: Erneutes Bereitstellen des Codes mit der vorherigen KCL-Version
<a name="kcl-migration-rollback-step2"></a>

**Wichtig**  
Jede Erwähnung von Version 2.x in der vom KCL Migration Tool generierten Ausgabe sollte als Bezugnahme auf KCL-Version 1.x interpretiert werden. Durch die Ausführung des Skripts erfolgt kein vollständiges Rollback. Es wird lediglich der Load-Balancing-Algorithmus auf den in KCL Version 1.x verwendeten umgestellt.

Nachdem das KCL Migration Tool den Rollback ausgeführt hat, wird eine der folgenden Meldungen angezeigt:

Nachricht 1  
„Rollback completed. Your application was running 2x compatible functionality. Please rollback to your previous application binaries by deploying the code with your previous KCL version.“  
**Erforderliche Maßnahme:** Dies bedeutet, dass Ihre Worker im KCL-1.x-kompatiblen Modus ausgeführt wurden. Stellen Sie den Code für Ihre Worker erneut mit der vorherigen KCL-Version bereit.

Nachricht 2  
„Rollback completed. Your KCL Application was running 3x functionality and will rollback to 2x compatible functionality. If you don't see mitigation after a short period of time, please rollback to your previous application binaries by deploying the code with your previous KCL version.“  
**Erforderliche Maßnahme:** Dies bedeutet, dass Ihre Worker im KCL-3.x-kompatiblen Modus ausgeführt wurden und das KCL Migration Tool alle Worker auf den KCL-1.x-kompatiblen Modus zurückgesetzt hat. Stellen Sie den Code für Ihre Worker erneut mit der vorherigen KCL-Version bereit.

Nachricht 3  
„Application was already rolled back. Alle KCLv3 Ressourcen, die gelöscht werden könnten, wurden gelöscht, um Gebühren zu vermeiden, bis die Anwendung im Rahmen der Migration weiterentwickelt werden kann.“  
**Erforderliche Maßnahme:** Dies bedeutet, dass Ihre Worker bereits in den KCL-1.x-kompatiblen Modus zurückversetzt wurden. Stellen Sie den Code für Ihre Worker erneut mit der vorherigen KCL-Version bereit.

# Rollforward zu KCL 3.x nach einem Rollback
<a name="kcl-migration-rollforward"></a>

In diesem Abschnitt wird erläutert, wie Sie Ihre Verbraucheranwendung nach einem Rollback wieder auf KCL 3.x umstellen können. Wenn Sie einen Rollforward durchführen müssen, sind zwei Schritte erforderlich:

1. Führen Sie das [KCL Migration Tool](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py) aus.

1. Stellen Sie den Code mit KCL 3.x bereit.

## Schritt 1: Ausführen des KCL Migration Tools
<a name="kcl-migration-rollforward-step1"></a>

Führen Sie das KCL Migration Tool mit dem folgenden Befehl aus, um KCL 3.x wiederherzustellen:

```
python3 ./KclMigrationTool.py --region region --mode rollforward [--application_name applicationName] [--coordinator_state_table_name coordinatorStateTableName]
```

### Parameters
<a name="kcl-migration-rollforward-parameters"></a>

`--region`  
Ersetze es *region* durch dein AWS-Region.

`--application_name`  
Dieser Parameter ist erforderlich, wenn Sie Standardnamen für die Koordinatorstatustabelle verwenden. Wenn Sie benutzerdefinierte Namen für diese Tabelle festgelegt haben, können Sie diesen Parameter weglassen. *applicationName*Ersetzen Sie es durch Ihren tatsächlichen KCL-Anwendungsnamen. Das Tool verwendet diesen Namen, um die Standardtabellennamen abzuleiten, wenn keine benutzerdefinierten Namen angegeben werden.

`--coordinator_state_table_name`  
Dieser Parameter wird benötigt, wenn Sie in Ihrer KCL-Konfiguration einen benutzerdefinierten Namen für die Koordinatorstatustabelle festgelegt haben. Wenn Sie den Standardtabellennamen verwenden, können Sie diesen Parameter weglassen. *coordinatorStateTableName*Ersetzen Sie durch den benutzerdefinierten Tabellennamen, den Sie für Ihre Koordinatorstatustabelle angegeben haben.

Nachdem Sie das Migrationstool im Roll-Forward-Modus ausgeführt haben, erstellt KCL die folgenden DynamoDB-Ressourcen, die für KCL 3.x erforderlich sind:
+ einen globalen sekundären Index für die Leasetabelle
+ eine Tabelle mit Worker-Metriken

## Schritt 2: Bereitstellen des Codes mit KCL 3.x
<a name="kcl-migration-rollforward-step2"></a>

Nachdem Sie den Rollforward mit dem KCL Migration Tool ausgeführt haben, stellen Sie Ihren Code mit KCL 3.x für Ihre Worker bereit. Informationen zum Abschließen Ihrer Migration finden Sie unter [Schritt 8: Abschließen der Migration](https://docs.aws.amazon.com/streams/latest/dev/kcl-migration-from-2-3.html#kcl-migration-from-2-3-finish).

# Walkthrough: DynamoDB-Streams-Kinesis-Adapter
<a name="Streams.KCLAdapter.Walkthrough"></a>

In diesem Abschnitt wird eine Anleitung für eine Java-Anwendung gegeben, die die Amazon-Kinesis-Client-Library und den Amazon-DynamoDB-Streams-Kinesis-Adapter verwendet. Die Anwendung zeigt ein Beispiel für die Datenreplikation, wobei Schreibaktivitäten einer Tabelle auf eine zweite Tabelle angewendet werden und die Inhalte beider Tabellen synchron bleiben. Sie finden den Quellcode unter [Vollständiges Programm: DynamoDB-Streams-Kinesis-Adapter](Streams.KCLAdapter.Walkthrough.CompleteProgram.md).

Das Programm führt Folgendes aus:

1. Erstellt zwei DynamoDB-Tabellen namens `KCL-Demo-src` und `KCL-Demo-dst`. Für jede dieser Tabellen ist ein Stream aktiviert.

1. Generiert Aktualisierungsaktivitäten in der Quelltabelle durch Hinzufügen, Aktualisieren und Löschen von Elementen. Dies bewirkt, dass Daten in den Tabellenstream geschrieben werden.

1. Liest die Datensätze aus dem Stream, rekonstruiert diese als DynamoDB-Anforderungen und wendet die Anforderungen auf die Zieltabelle an.

1. Scannt die Quell- und Zieltabellen, um sicherzustellen, dass ihre Inhalte identisch sind.

1. Bereinigt die Daten durch Löschen der Tabellen.

Diese Schritte werden in den folgenden Abschnitten beschrieben und die vollständige Anwendung wird am Ende der Anleitung angezeigt.

**Topics**
+ [Schritt 1: Erstellen einer DynamoDB-Tabelle](#Streams.KCLAdapter.Walkthrough.Step1)
+ [Schritt 2: Generieren von Aktualisierungsaktivitäten in der Quelltabelle](#Streams.KCLAdapter.Walkthrough.Step2)
+ [Schritt 3: Verarbeiten des Streams](#Streams.KCLAdapter.Walkthrough.Step3)
+ [Schritt 4: Sicherstellen, dass beide Tabellen über identische Inhalte verfügen](#Streams.KCLAdapter.Walkthrough.Step4)
+ [Schritt 5: Bereinigen](#Streams.KCLAdapter.Walkthrough.Step5)
+ [Vollständiges Programm: DynamoDB-Streams-Kinesis-Adapter](Streams.KCLAdapter.Walkthrough.CompleteProgram.md)

## Schritt 1: Erstellen einer DynamoDB-Tabelle
<a name="Streams.KCLAdapter.Walkthrough.Step1"></a>

Im ersten Schritt erstellen Sie zwei DynamoDB-Tabellen—eine Quelltabelle und eine Zieltabelle. Der `StreamViewType` des Streams der Quelltabelle lautet `NEW_IMAGE`. Das bedeutet, dass sobald ein Element in dieser Tabelle geändert wird, das Image des Elements nach der Änderung in den Stream geschrieben wird. So verfolgt der Stream alle Schreibaktivitäten der Tabelle.

Das folgende Beispiel zeigt den Code für das Erstellen von beiden Tabellen.

```
java.util.List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition().withAttributeName("Id").withAttributeType("N"));

java.util.List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); // Partition
                                                                                         // key

ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput().withReadCapacityUnits(2L)
    .withWriteCapacityUnits(2L);

StreamSpecification streamSpecification = new StreamSpecification();
streamSpecification.setStreamEnabled(true);
streamSpecification.setStreamViewType(StreamViewType.NEW_IMAGE);
CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName)
    .withAttributeDefinitions(attributeDefinitions).withKeySchema(keySchema)
    .withProvisionedThroughput(provisionedThroughput).withStreamSpecification(streamSpecification);
```

## Schritt 2: Generieren von Aktualisierungsaktivitäten in der Quelltabelle
<a name="Streams.KCLAdapter.Walkthrough.Step2"></a>

Im nächsten Schritt erstellen Sie einige Schreibaktivitäten in der Quelltabelle. Während diese Aktivitäten ausgeführt werden, wird der Stream der Quelltabelle nahezu in Echtzeit ebenfalls aktualisiert.

Die Anwendung definiert die Hilfsprogrammklasse mit Methoden zum Aufrufen der API-Operationen `PutItem`, `UpdateItem` und `DeleteItem` zum Schreiben der Daten. Das folgende Codebeispiel zeigt, wie diese Methoden verwendet werden.

```
StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "101", "test1");
StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "101", "test2");
StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "101");
StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "102", "demo3");
StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "102", "demo4");
StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "102");
```

## Schritt 3: Verarbeiten des Streams
<a name="Streams.KCLAdapter.Walkthrough.Step3"></a>

Das Programm beginnt mit der Verarbeitung des Streams. Der DynamoDB Streams Kinesis Adapter fungiert als transparente Ebene zwischen der KCL und dem DynamoDB Streams-Endpunkt, sodass der Code die KCL vollständig nutzen kann, statt DynamoDB-Streams-Low-Level-Aufrufe tätigen zu müssen. Das Programm führt die folgenden Aufgaben durch:
+ Es definiert eine Datensatzprozessor-Klasse, `StreamsRecordProcessor`, mit Methoden, die mit der KCL-Schnittstellendefinition übereinstimmen: `initialize`, `processRecords` und `shutdown`. Die `processRecords`-Methode enthält die Logik, die zum Lesen von der Quelltabelle des Streams und zum Schreiben in die Zieltabelle erforderlich ist.
+ Sie definiert eine ClassFactory für die Datensatzprozessor-Klasse (`StreamsRecordProcessorFactory`). Dies ist für Java-Programme, die die KCL verwenden, erforderlich.
+ Die Methode instanziiert eine neue KCL `Worker`, die der Class Factory zugeordnet ist.
+ Sie fährt `Worker` herunter, wenn die Datensatzverarbeitung abgeschlossen ist.

Aktivieren Sie optional den Aufholmodus in Ihrer Streams-KCL-Adapterkonfiguration, um die GetRecords API-Aufrufrate automatisch um das Dreifache zu skalieren (Standard), wenn die Verzögerung der Stream-Verarbeitung eine Minute überschreitet (Standard), sodass Ihr Stream-Consumer hohe Durchsatzspitzen in Ihrer Tabelle bewältigen kann.

Weitere Informationen zur KCL-Schnittstellendefinition finden Sie unter [Entwickeln von Konsumenten mithilfe der Kinesis-Clientbibliothek](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) im *Amazon-Kinesis-Data-Streams-Entwicklerhandbuch*. 

Das folgende Codebeispiel zeigt die Hauptschleife in `StreamsRecordProcessor`. Die `case`-Anweisung bestimmt, welche Aktion basierend auf dem `OperationType`, der im Stream-Datensatz erscheint, durchgeführt werden soll.

```
for (Record record : records) {
    String data = new String(record.getData().array(), Charset.forName("UTF-8"));
    System.out.println(data);
    if (record instanceof RecordAdapter) {
                software.amazon.dynamodb.model.Record streamRecord = ((RecordAdapter) record)
                    .getInternalObject();

                switch (streamRecord.getEventName()) {
                    case "INSERT":
                    case "MODIFY":
                        StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName,
                            streamRecord.getDynamodb().getNewImage());
                        break;
                    case "REMOVE":
                        StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName,
                            streamRecord.getDynamodb().getKeys().get("Id").getN());
                }
    }
    checkpointCounter += 1;
    if (checkpointCounter % 10 == 0) {
        try {
            checkpointer.checkpoint();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

## Schritt 4: Sicherstellen, dass beide Tabellen über identische Inhalte verfügen
<a name="Streams.KCLAdapter.Walkthrough.Step4"></a>

An diesem Punkt sind die Inhalte der Quell- und Zieltabellen synchronisiert. Die Anwendung gibt `Scan`-Anforderungen für beide Tabellen aus, um sicherzustellen, dass ihre Inhalte identisch sind.

Die `DemoHelper`-Klasse enthält eine `ScanTable`-Methode, die die `Scan`-Low-Level-API aufruft. Das Verfahren wird im folgenden Beispiel beschrieben.

```
if (StreamsAdapterDemoHelper.scanTable(dynamoDBClient, srcTable).getItems()
    .equals(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, destTable).getItems())) {
    System.out.println("Scan result is equal.");
}
else {
    System.out.println("Tables are different!");
}
```

## Schritt 5: Bereinigen
<a name="Streams.KCLAdapter.Walkthrough.Step5"></a>

Die Demonstration ist abgeschlossen, so dass die Anwendung Quell- und Zieltabellen löscht. Beachten Sie hierzu das folgende Codebeispiel. Nachdem die Tabellen gelöscht wurden, bleiben die Streams für bis zu 24 Stunden verfügbar. Anschließend werden sie automatisch gelöscht.

```
dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(srcTable));
dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(destTable));
```

# Vollständiges Programm: DynamoDB-Streams-Kinesis-Adapter
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram"></a>

Hier finden Sie das vollständige Java-Programm, das die in [Walkthrough: DynamoDB-Streams-Kinesis-Adapter](Streams.KCLAdapter.Walkthrough.md) beschriebenen Aufgaben durchführt. Wenn Sie das Programm ausführen, wird eine Ausgabe ähnlich der folgenden angezeigt:

```
Creating table KCL-Demo-src
Creating table KCL-Demo-dest
Table is active.
Creating worker for stream: arn:aws:dynamodb:us-west-2:111122223333:table/KCL-Demo-src/stream/2015-05-19T22:48:56.601
Starting worker...
Scan result is equal.
Done.
```

**Wichtig**  
 Um dieses Programm auszuführen, stellen Sie sicher, dass die Client-Anwendung CloudWatch mithilfe von Richtlinien Zugriff auf DynamoDB und Amazon hat. Weitere Informationen finden Sie unter [Identitätsbasierte Richtlinien für DynamoDB](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies). 

Der Quellcode besteht aus vier `.java` Dateien. Um dieses Programm zu erstellen, fügen Sie die folgende Abhängigkeit hinzu, zu der die Amazon Kinesis Client Library (KCL) 3.x und das AWS SDK for Java v2 als transitive Abhängigkeiten gehören:

------
#### [ Maven ]

```
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>dynamodb-streams-kinesis-adapter</artifactId>
    <version>2.1.0</version>
</dependency>
```

------
#### [ Gradle ]

```
implementation 'com.amazonaws:dynamodb-streams-kinesis-adapter:2.1.0'
```

------

Die Quelldateien sind:
+ `StreamsAdapterDemo.java`
+ `StreamsRecordProcessor.java`
+ `StreamsRecordProcessorFactory.java`
+ `StreamsAdapterDemoHelper.java`

## StreamsAdapterDemo.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsAdapterDemo"></a>

```
package com.amazonaws.codesamples;

import com.amazonaws.services.dynamodbv2.streamsadapter.AmazonDynamoDBStreamsAdapterClient;
import com.amazonaws.services.dynamodbv2.streamsadapter.StreamsSchedulerFactory;
import com.amazonaws.services.dynamodbv2.streamsadapter.polling.DynamoDBStreamsPollingConfig;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.kinesis.common.ConfigsBuilder;
import software.amazon.kinesis.common.InitialPositionInStream;
import software.amazon.kinesis.common.InitialPositionInStreamExtended;
import software.amazon.kinesis.coordinator.Scheduler;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;
import software.amazon.kinesis.processor.StreamTracker;
import software.amazon.kinesis.retrieval.RetrievalConfig;

public class StreamsAdapterDemo {

    private static DynamoDbAsyncClient dynamoDbAsyncClient;
    private static CloudWatchAsyncClient cloudWatchAsyncClient;
    private static AmazonDynamoDBStreamsAdapterClient amazonDynamoDbStreamsAdapterClient;

    private static String tablePrefix = "KCL-Demo";
    private static String streamArn;

    private static Region region = Region.US_EAST_1;
    private static AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create();

    public static void main( String[] args ) throws Exception {
        System.out.println("Starting demo...");
        dynamoDbAsyncClient = DynamoDbAsyncClient.builder()
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build();
        cloudWatchAsyncClient = CloudWatchAsyncClient.builder()
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build();
        amazonDynamoDbStreamsAdapterClient = new AmazonDynamoDBStreamsAdapterClient(credentialsProvider, region);

        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";

        setUpTables();

        StreamTracker streamTracker = StreamsSchedulerFactory.createSingleStreamTracker(streamArn,
                InitialPositionInStreamExtended.newInitialPosition(InitialPositionInStream.TRIM_HORIZON));

        ShardRecordProcessorFactory shardRecordProcessorFactory =
                new StreamsAdapterDemoProcessorFactory(dynamoDbAsyncClient, destTable);

        ConfigsBuilder configsBuilder = new ConfigsBuilder(
                streamTracker,
                "streams-adapter-demo",
                amazonDynamoDbStreamsAdapterClient,
                dynamoDbAsyncClient,
                cloudWatchAsyncClient,
                "streams-demo-worker",
                shardRecordProcessorFactory
        );

        DynamoDBStreamsPollingConfig pollingConfig = new DynamoDBStreamsPollingConfig(amazonDynamoDbStreamsAdapterClient);
        RetrievalConfig retrievalConfig = configsBuilder.retrievalConfig();
        retrievalConfig.retrievalSpecificConfig(pollingConfig);

        System.out.println("Creating scheduler for stream " + streamArn);
        Scheduler scheduler = StreamsSchedulerFactory.createScheduler(
                configsBuilder.checkpointConfig(),
                configsBuilder.coordinatorConfig(),
                configsBuilder.leaseManagementConfig(),
                configsBuilder.lifecycleConfig(),
                configsBuilder.metricsConfig(),
                configsBuilder.processorConfig(),
                retrievalConfig,
                amazonDynamoDbStreamsAdapterClient
        );

        System.out.println("Starting scheduler...");
        Thread t = new Thread(scheduler);
        t.start();

        Thread.sleep(250000);

        System.out.println("Stopping scheduler...");
        scheduler.shutdown();
        t.join();

        if (StreamsAdapterDemoHelper.scanTable(dynamoDbAsyncClient, srcTable).items()
                .equals(StreamsAdapterDemoHelper.scanTable(dynamoDbAsyncClient, destTable).items())) {
            System.out.println("Scan result is equal.");
        } else {
            System.out.println("Tables are different!");
        }

        System.out.println("Done.");
        cleanupAndExit(0);
    }

    private static void setUpTables() {
        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";
        streamArn = StreamsAdapterDemoHelper.createTable(dynamoDbAsyncClient, srcTable);
        StreamsAdapterDemoHelper.createTable(dynamoDbAsyncClient, destTable);

        awaitTableCreation(srcTable);

        performOps(srcTable);
    }

    private static void awaitTableCreation(String tableName) {
        Integer retries = 0;
        Boolean created = false;
        while (!created && retries < 100) {
            DescribeTableResponse result = StreamsAdapterDemoHelper.describeTable(dynamoDbAsyncClient, tableName);
            created = result.table().tableStatusAsString().equals("ACTIVE");
            if (created) {
                System.out.println("Table is active.");
                return;
            } else {
                retries++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // do nothing
                }
            }
        }
        System.out.println("Timeout after table creation. Exiting...");
        cleanupAndExit(1);
    }

    private static void performOps(String tableName) {
        StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName, "101", "test1");
        StreamsAdapterDemoHelper.updateItem(dynamoDbAsyncClient, tableName, "101", "test2");
        StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName, "101");
        StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName, "102", "demo3");
        StreamsAdapterDemoHelper.updateItem(dynamoDbAsyncClient, tableName, "102", "demo4");
        StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName, "102");
    }

    private static void cleanupAndExit(Integer returnValue) {
        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";
        dynamoDbAsyncClient.deleteTable(DeleteTableRequest.builder().tableName(srcTable).build());
        dynamoDbAsyncClient.deleteTable(DeleteTableRequest.builder().tableName(destTable).build());
        System.exit(returnValue);
    }
}
```

## StreamsRecordProcessor.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsRecordProcessor"></a>

```
package com.amazonaws.codesamples;

import com.amazonaws.services.dynamodbv2.streamsadapter.adapter.DynamoDBStreamsClientRecord;
import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.Record;
import software.amazon.kinesis.exceptions.InvalidStateException;
import software.amazon.kinesis.exceptions.ShutdownException;
import software.amazon.kinesis.lifecycle.events.InitializationInput;
import software.amazon.kinesis.lifecycle.events.LeaseLostInput;
import software.amazon.kinesis.lifecycle.events.ShardEndedInput;
import software.amazon.kinesis.lifecycle.events.ShutdownRequestedInput;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

public class StreamsRecordProcessor implements DynamoDBStreamsShardRecordProcessor {

    private Integer checkpointCounter;

    private final DynamoDbAsyncClient dynamoDbAsyncClient;
    private final String tableName;

    public StreamsRecordProcessor(DynamoDbAsyncClient dynamoDbAsyncClient, String tableName) {
        this.dynamoDbAsyncClient = dynamoDbAsyncClient;
        this.tableName = tableName;
    }

    @Override
    public void initialize(InitializationInput initializationInput) {
        this.checkpointCounter = 0;
    }

    @Override
    public void processRecords(DynamoDBStreamsProcessRecordsInput dynamoDBStreamsProcessRecordsInput) {
        for (DynamoDBStreamsClientRecord record: dynamoDBStreamsProcessRecordsInput.records()) {
            String data = new String(record.data().array(), StandardCharsets.UTF_8);
            System.out.println(data);
            Record streamRecord = record.getRecord();

            switch (streamRecord.eventName()) {
                case INSERT:
                case MODIFY:
                    StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName,
                            streamRecord.dynamodb().newImage());
                case REMOVE:
                    StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName,
                            streamRecord.dynamodb().keys().get("Id").n());
            }
            checkpointCounter += 1;
            if (checkpointCounter % 10 == 0) {
                try {
                    dynamoDBStreamsProcessRecordsInput.checkpointer().checkpoint();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void leaseLost(LeaseLostInput leaseLostInput) {
        System.out.println("Lease Lost");
    }

    @Override
    public void shardEnded(ShardEndedInput shardEndedInput) {
        try {
            shardEndedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
        try {
            shutdownRequestedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            e.printStackTrace();
        }
    }
}
```

## StreamsRecordProcessorFactory.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsRecordProcessorFactory"></a>

```
package com.amazonaws.codesamples;

import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.kinesis.processor.ShardRecordProcessor;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;

public class StreamsAdapterDemoProcessorFactory implements ShardRecordProcessorFactory {
    private final String tableName;
    private final DynamoDbAsyncClient dynamoDbAsyncClient;

    public StreamsAdapterDemoProcessorFactory(DynamoDbAsyncClient asyncClient, String tableName) {
        this.tableName = tableName;
        this.dynamoDbAsyncClient = asyncClient;
    }

    @Override
    public ShardRecordProcessor shardRecordProcessor() {
        return new StreamsRecordProcessor(dynamoDbAsyncClient, tableName);
    }
}
```

## StreamsAdapterDemoHelper.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsAdapterDemoHelper"></a>

```
package com.amazonaws.codesamples;

import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.OnDemandThroughput;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException;
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
import software.amazon.awssdk.services.dynamodb.model.StreamSpecification;
import software.amazon.awssdk.services.dynamodb.model.StreamViewType;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class StreamsAdapterDemoHelper {

    /**
     * @return StreamArn
     */
    public static String createTable(DynamoDbAsyncClient client, String tableName) {
        List<AttributeDefinition> attributeDefinitions = new ArrayList<>();
        attributeDefinitions.add(AttributeDefinition.builder()
                .attributeName("Id")
                .attributeType("N")
                .build());

        List<KeySchemaElement> keySchema = new ArrayList<>();
        keySchema.add(KeySchemaElement.builder()
                .attributeName("Id")
                .keyType(KeyType.HASH) // Partition key
                .build());

        StreamSpecification streamSpecification = StreamSpecification.builder()
                .streamEnabled(true)
                .streamViewType(StreamViewType.NEW_IMAGE)
                .build();

        CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .tableName(tableName)
                .attributeDefinitions(attributeDefinitions)
                .keySchema(keySchema)
                .billingMode(BillingMode.PAY_PER_REQUEST)
                .streamSpecification(streamSpecification)
                .build();

        try {
            System.out.println("Creating table " + tableName);
            CreateTableResponse result = client.createTable(createTableRequest).join();
            return result.tableDescription().latestStreamArn();
        } catch (Exception e) {
            if (e.getCause() instanceof ResourceInUseException) {
                System.out.println("Table already exists.");
                return describeTable(client, tableName).table().latestStreamArn();
            }
            throw e;
        }
    }

    public static DescribeTableResponse describeTable(DynamoDbAsyncClient client, String tableName) {
        return client.describeTable(DescribeTableRequest.builder()
                        .tableName(tableName)
                        .build())
                .join();
    }

    public static ScanResponse scanTable(DynamoDbAsyncClient dynamoDbClient, String tableName) {
        return dynamoDbClient.scan(ScanRequest.builder()
                        .tableName(tableName)
                        .build())
                .join();
    }

    public static void putItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id, String val) {
        Map<String, AttributeValue> item = new HashMap<>();
        item.put("Id", AttributeValue.builder().n(id).build());
        item.put("attribute-1", AttributeValue.builder().s(val).build());

        putItem(dynamoDbClient, tableName, item);
    }

    public static void putItem(DynamoDbAsyncClient dynamoDbClient, String tableName,
                               Map<String, AttributeValue> items) {
        PutItemRequest putItemRequest = PutItemRequest.builder()
                .tableName(tableName)
                .item(items)
                .build();
        dynamoDbClient.putItem(putItemRequest).join();
    }

    public static void updateItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id, String val) {
        Map<String, AttributeValue> key = new HashMap<>();
        key.put("Id", AttributeValue.builder().n(id).build());

        Map<String, String> expressionAttributeNames = new HashMap<>();
        expressionAttributeNames.put("#attr2", "attribute-2");

        Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(":val", AttributeValue.builder().s(val).build());

        UpdateItemRequest updateItemRequest = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .updateExpression("SET #attr2 = :val")
                .expressionAttributeNames(expressionAttributeNames)
                .expressionAttributeValues(expressionAttributeValues)
                .build();

        dynamoDbClient.updateItem(updateItemRequest).join();
    }

    public static void deleteItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id) {
        Map<String, AttributeValue> key = new HashMap<>();
        key.put("Id", AttributeValue.builder().n(id).build());

        DeleteItemRequest deleteItemRequest = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .build();
        dynamoDbClient.deleteItem(deleteItemRequest).join();
    }
}
```

# DynamoDB-Streams-Low-Level-API: Java-Beispiel
<a name="Streams.LowLevel.Walkthrough"></a>

**Anmerkung**  
Der Code auf dieser Seite ist nicht umfassend und behandelt nicht alle Szenarien für die Nutzung von Amazon DynamoDB Streams. Die empfohlene Methode für die Nutzung von Stream-Datensätzen aus DynamoDB erfolgt anhand des Amazon-Kinesis-Adapters unter Verwendung der Kinesis-Client-Library (KCL) gemäß der Beschreibung in [Verwenden des DynamoDB-Streams-Kinesis-Adapters zum Verarbeiten von Stream-Datensätzen](Streams.KCLAdapter.md).

Dieser Abschnitt enthält ein Java-Programm, das DynamoDB Streams in Aktion zeigt. Das Programm führt Folgendes aus:

1. Erstellt eine DynamoDB-Tabelle mit einem aktivierten Stream.

1. Beschreibt die Stream-Einstellungen für diese Tabelle.

1. Ändert die Daten in der Tabelle.

1. Beschreibt die Shards im Stream.

1. Liest die Stream-Datensätze aus den Shards.

1. Ruft untergeordnete Shards ab und setzt das Lesen von Datensätzen fort.

1. Bereinigt die Daten.

Wenn Sie das Programm ausführen, wird eine Ausgabe ähnlich der folgenden angezeigt.

```
Testing Streams Demo
Creating an Amazon DynamoDB table TestTableForStreams with a simple primary key: Id
Waiting for TestTableForStreams to be created...
Current stream ARN for TestTableForStreams: arn:aws:dynamodb:us-east-2:123456789012:table/TestTableForStreams/stream/2018-03-20T16:49:55.208
Stream enabled: true
Update view type: NEW_AND_OLD_IMAGES

Performing write activities on TestTableForStreams
Processing item 1 of 100
Processing item 2 of 100
Processing item 3 of 100
...
Processing item 100 of 100
Shard: {ShardId: shardId-1234567890-...,SequenceNumberRange: {StartingSequenceNumber: 100002572486797508907,},}
    Shard iterator: EjYFEkX2a26eVTWe...
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, NewImage={Message=AttributeValue(S=New Item!), Id=AttributeValue(S=4)}, SequenceNumber=2000001584047545833909, SizeBytes=22, StreamViewType=NEW_AND_OLD_IMAGES)
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, NewImage={Message=AttributeValue(S=This is an updated item), Id=AttributeValue(S=4)}, OldImage={Message=AttributeValue(S=New Item!), Id=AttributeValue(S=4)}, SequenceNumber=2100003604869767892701, SizeBytes=55, StreamViewType=NEW_AND_OLD_IMAGES)
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, OldImage={Message=AttributeValue(S=This is an updated item), Id=AttributeValue(S=4)}, SequenceNumber=2200001099771112898434, SizeBytes=36, StreamViewType=NEW_AND_OLD_IMAGES)
...
Deleting the table...
Table StreamsDemoTable deleted.
Demo complete
```

**Example Beispiel**  

```
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeAction;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeStreamRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeStreamResponse;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.GetRecordsRequest;
import software.amazon.awssdk.services.dynamodb.model.GetRecordsResponse;
import software.amazon.awssdk.services.dynamodb.model.GetShardIteratorRequest;
import software.amazon.awssdk.services.dynamodb.model.GetShardIteratorResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.Record;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.Shard;
import software.amazon.awssdk.services.dynamodb.model.ShardFilter;
import software.amazon.awssdk.services.dynamodb.model.ShardFilterType;
import software.amazon.awssdk.services.dynamodb.model.ShardIteratorType;
import software.amazon.awssdk.services.dynamodb.model.StreamSpecification;
import software.amazon.awssdk.services.dynamodb.model.TableDescription;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.streams.DynamoDbStreamsClient;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;

public class StreamsLowLevelDemo {


    public static void main(String[] args) {
        final String usage = "Testing Streams Demo";
        try {
            System.out.println(usage);

            String tableName = "StreamsDemoTable";
            String key = "Id";
            System.out.println("Creating an Amazon DynamoDB table " + tableName + " with a simple primary key: " + key);
            Region region = Region.US_WEST_2;
            DynamoDbClient ddb = DynamoDbClient.builder()
                    .region(region)
                    .build();

            DynamoDbStreamsClient ddbStreams = DynamoDbStreamsClient.builder()
                    .region(region)
                    .build();
            DescribeTableRequest describeTableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();
            TableDescription tableDescription = null;
            try{
                tableDescription = ddb.describeTable(describeTableRequest).table();
            }catch (Exception e){
                System.out.println("Table " + tableName + " does not exist.");
                tableDescription = createTable(ddb, tableName, key);
            }

            // Print the stream settings for the table
            String streamArn = tableDescription.latestStreamArn();
           
            StreamSpecification streamSpec = tableDescription.streamSpecification();
            System.out.println("Current stream ARN for " + tableDescription.tableName() + ": " +
                   streamArn);
            System.out.println("Stream enabled: " + streamSpec.streamEnabled());
            System.out.println("Update view type: " + streamSpec.streamViewType());
            System.out.println();
            // Generate write activity in the table
            System.out.println("Performing write activities on " + tableName);
            int maxItemCount = 100;
            for (Integer i = 1; i <= maxItemCount; i++) {
                System.out.println("Processing item " + i + " of " + maxItemCount);
                // Write a new item
                putItemInTable(key, i, tableName, ddb);
                // Update the item
                updateItemInTable(key, i, tableName, ddb);
                // Delete the item
                deleteDynamoDBItem(key, i, tableName, ddb);
            }

            // Process Stream
            processStream(streamArn, maxItemCount, ddb, ddbStreams, tableName);

            // Delete the table
            System.out.println("Deleting the table...");
            DeleteTableRequest deleteTableRequest = DeleteTableRequest.builder()
                    .tableName(tableName)
                    .build();
            ddb.deleteTable(deleteTableRequest);
            System.out.println("Table " + tableName + " deleted.");
            System.out.println("Demo complete");
            ddb.close();
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
    }

    private static void processStream(String streamArn, int maxItemCount, DynamoDbClient ddb, DynamoDbStreamsClient ddbStreams, String tableName) {
        // Get all the shard IDs from the stream. Note that DescribeStream returns
        // the shard IDs one page at a time.
        String lastEvaluatedShardId = null;
        do {
            DescribeStreamRequest describeStreamRequest = DescribeStreamRequest.builder()
                    .streamArn(streamArn)
                    .exclusiveStartShardId(lastEvaluatedShardId).build();
            DescribeStreamResponse describeStreamResponse = ddbStreams.describeStream(describeStreamRequest);

            List<Shard> shards = describeStreamResponse.streamDescription().shards();

            // Process each shard on this page

            fetchShardsAndReadRecords(streamArn, maxItemCount, ddbStreams, shards);

            // If LastEvaluatedShardId is set, then there is
            // at least one more page of shard IDs to retrieve
            lastEvaluatedShardId = describeStreamResponse.streamDescription().lastEvaluatedShardId();

        } while (lastEvaluatedShardId != null);

    }

    private static void fetchShardsAndReadRecords(String streamArn, int maxItemCount, DynamoDbStreamsClient ddbStreams, List<Shard> shards) {
        for (Shard shard : shards) {
            String shardId = shard.shardId();
            System.out.println("Shard: " + shard);

            // Get an iterator for the current shard
            GetShardIteratorRequest shardIteratorRequest = GetShardIteratorRequest.builder()
                    .streamArn(streamArn).shardId(shardId)
                    .shardIteratorType(ShardIteratorType.TRIM_HORIZON).build();

            GetShardIteratorResponse getShardIteratorResult = ddbStreams.getShardIterator(shardIteratorRequest);

            String currentShardIter = getShardIteratorResult.shardIterator();

            // Shard iterator is not null until the Shard is sealed (marked as READ_ONLY).
            // To prevent running the loop until the Shard is sealed, we process only the
            // items that were written into DynamoDB and then exit.
            int processedRecordCount = 0;
            while (currentShardIter != null && processedRecordCount < maxItemCount) {
                // Use the shard iterator to read the stream records
                GetRecordsRequest getRecordsRequest = GetRecordsRequest.builder()
                        .shardIterator(currentShardIter).build();
                GetRecordsResponse getRecordsResult = ddbStreams.getRecords(getRecordsRequest);
                List<Record> records = getRecordsResult.records();
                for (Record record : records) {
                    System.out.println("        " + record.dynamodb());
                }
                processedRecordCount += records.size();
                currentShardIter = getRecordsResult.nextShardIterator();
            }
            if (currentShardIter == null){
                System.out.println("Shard has been fully processed. Shard iterator is null.");
                System.out.println("Fetch the child shard to continue processing instead of bulk fetching all shards");
                DescribeStreamRequest describeStreamRequestForChildShards = DescribeStreamRequest.builder()
                        .streamArn(streamArn)
                        .shardFilter(ShardFilter.builder()
                                .type(ShardFilterType.CHILD_SHARDS)
                                .shardId(shardId).build())
                        .build();
                DescribeStreamResponse describeStreamResponseChildShards = ddbStreams.describeStream(describeStreamRequestForChildShards);
                fetchShardsAndReadRecords(streamArn, maxItemCount, ddbStreams, describeStreamResponseChildShards.streamDescription().shards());
            }
        }
    }

    private static void putItemInTable(String key, Integer i, String tableName, DynamoDbClient ddb) {
        Map<String, AttributeValue> item = new HashMap<>();
        item.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());
        item.put("Message", AttributeValue.builder()
                .s("New Item!")
                .build());
        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(item)
                .build();
        ddb.putItem(request);
    }

    private static void updateItemInTable(String key, Integer i, String tableName, DynamoDbClient ddb) {

        HashMap<String, AttributeValue> itemKey = new HashMap<>();
        itemKey.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());


        HashMap<String, AttributeValueUpdate> updatedValues = new HashMap<>();
        updatedValues.put("Message", AttributeValueUpdate.builder()
                .value(AttributeValue.builder().s("This is an updated item").build())
                .action(AttributeAction.PUT)
                .build());

        UpdateItemRequest request = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(itemKey)
                .attributeUpdates(updatedValues)
                .build();
        ddb.updateItem(request);
    }

    public static void deleteDynamoDBItem(String key, Integer i, String tableName, DynamoDbClient ddb) {
        HashMap<String, AttributeValue> keyToGet = new HashMap<>();
        keyToGet.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());

        DeleteItemRequest deleteReq = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(keyToGet)
                .build();
        ddb.deleteItem(deleteReq);
    }

    public static TableDescription createTable(DynamoDbClient ddb, String tableName, String key) {
        DynamoDbWaiter dbWaiter = ddb.waiter();
        StreamSpecification streamSpecification = StreamSpecification.builder()
                .streamEnabled(true)
                .streamViewType("NEW_AND_OLD_IMAGES")
                .build();
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(AttributeDefinition.builder()
                        .attributeName(key)
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(KeySchemaElement.builder()
                        .attributeName(key)
                        .keyType(KeyType.HASH)
                        .build())
                .billingMode(BillingMode.PAY_PER_REQUEST) //  DynamoDB automatically scales based on traffic.
                .tableName(tableName)
                .streamSpecification(streamSpecification)
                .build();

        TableDescription newTable;
        try {
            CreateTableResponse response = ddb.createTable(request);
            DescribeTableRequest tableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();
                    
            System.out.println("Waiting for " + tableName + " to be created...");

            // Wait until the Amazon DynamoDB table is created.
            WaiterResponse<DescribeTableResponse> waiterResponse = dbWaiter.waitUntilTableExists(tableRequest);
            waiterResponse.matched().response().ifPresent(System.out::println);
            newTable = response.tableDescription();
            return newTable;

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        return null;
    }



}
```

# DynamoDB Streams und -Trigger AWS Lambda
<a name="Streams.Lambda"></a>

Amazon DynamoDB ist integriert, AWS Lambda sodass Sie *Trigger* erstellen können — Codeteile, die automatisch auf Ereignisse in DynamoDB Streams reagieren. Mit Auslösern können Sie Anwendungen erstellen, die auf Datenänderungen in DynamoDB-Tabellen reagieren.

**Topics**
+ [Tutorial \$11: Verwenden von Filtern zur Verarbeitung aller Ereignisse mit Amazon DynamoDB und AWS Lambda Verwendung der AWS CLI](Streams.Lambda.Tutorial.md)
+ [Tutorial 2: Verwenden von Filtern, um einige Ereignisse mit DynamoDB und Lambda zu verarbeiten](Streams.Lambda.Tutorial2.md)
+ [Bewährte Methoden zur Verwendung von DynamoDB Streams mit Lambda](Streams.Lambda.BestPracticesWithDynamoDB.md)

Wenn Sie DynamoDB Streams für eine Tabelle aktivieren, können Sie den Stream Amazon Resource Name (ARN) mit einer von Ihnen geschriebenen AWS Lambda Funktion verknüpfen. Alle Mutationsaktionen für diese DynamoDB-Tabelle können dann als Element im Stream erfasst werden. Sie können beispielsweise einen Auslöser festlegen, sodass beim Ändern eines Elements in einer Tabelle sofort ein neuer Datensatz im Stream der betreffenden Tabelle angezeigt wird. 

**Anmerkung**  
Wenn Sie mehr als zwei Lambda-Funktionen für einen DynamoDB-Stream abonnieren, kann es zu einer Drosselung der Lesegeschwindigkeit kommen.

Der [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html)-Service fragt den Stream viermal pro Sekunde nach neuen Datensätzen ab. Wenn neue Stream-Datensätze verfügbar sind, wird Ihre Lambda-Funktion synchron aufgerufen. Sie können bis zu zwei Lambda-Funktionen für denselben DynamoDB-Stream abonnieren. Wenn Sie mehr als zwei Lambda-Funktionen für denselben DynamoDB-Stream abonnieren, kann es zu einer Drosselung der Lesegeschwindigkeit kommen.

Die Lambda-Funktion kann eine Benachrichtigung senden, einen Workflow einleiten oder viele andere von Ihnen festgelegte Aktionen durchführen. Sie können eine Lambda-Funktion schreiben, um jeden Stream-Datensatz einfach in persistenten Speicher wie z. B. Amazon S3 File Gateway (Amazon S3) zu kopieren und einen permanenten Prüfungs-Trail der Schreibaktivitäten in Ihrer Tabelle zu erstellen. Angenommen, Sie verfügen über eine mobile Gaming-App, die Schreibvorgänge in einer `GameScores`-Tabelle vornimmt. Bei jedem Aktualisieren des `TopScore`-Attributs der `GameScores`-Tabelle wird ein entsprechender Stream-Datensatz in den Stream der Tabelle geschrieben. Dieses Ereignis kann dann automatisch eine Lambda-Funktion auslösen, die einen Glückwunsch in einem Social-Media-Netzwerk postet. Diese Funktion könnte auch so geschrieben werden, dass sie alle Stream-Datensätze ignoriert, die kein Update von `GameScores` sind oder das `TopScore`-Attribut nicht ändern.

Wenn Ihre Funktion einen Fehler zurückgibt, wiederholt Lambda den Vorgang mit dem Batch, bis die Verarbeitung erfolgreich ist oder die Daten ablaufen. Sie können Lambda auch so konfigurieren, dass eine Wiederholung mit einem kleineren Batch erfolgt, die Anzahl der Wiederholungen eingeschränkt wird, Datensätze verworfen werden, sobald sie zu alt sind, und vieles mehr.

Gemäß bewährten Methoden für die Leistung muss die Lambda-Funktion kurzlebig sein. Um unnötige Verarbeitungsverzögerungen zu vermeiden, sollte sie auch keine komplexe Logik ausführen. Insbesondere bei einem Hochgeschwindigkeits-Stream ist es besser, asynchrone Nachbearbeitungs-Schrittfunktions-Workflows auszulösen als synchrone Lambdas mit langer Laufzeit.

 Sie können Lambda-Trigger für verschiedene AWS Konten verwenden, indem Sie eine ressourcenbasierte Richtlinie für den DynamoDB-Stream konfigurieren, um der kontoübergreifenden Lesezugriff auf die Lambda-Funktion zu gewähren. Weitere Informationen darüber, wie Sie Ihren Stream so konfigurieren, dass er kontoübergreifenden Zugriff ermöglicht, finden Sie unter [Zugriff mit kontoübergreifenden AWS Lambda-Funktionen teilen](rbac-cross-account-access.md#shared-access-cross-acount-lambda) im DynamoDB-Entwicklerhandbuch.

[Weitere Informationen AWS Lambda dazu finden Sie im Entwicklerhandbuch.AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/)

# Tutorial \$11: Verwenden von Filtern zur Verarbeitung aller Ereignisse mit Amazon DynamoDB und AWS Lambda Verwendung der AWS CLI
<a name="Streams.Lambda.Tutorial"></a>

 

In diesem Tutorial erstellen Sie einen AWS Lambda Trigger zur Verarbeitung eines Streams aus einer DynamoDB-Tabelle.

**Topics**
+ [Schritt 1: Erstellen einer DynamoDB-Tabelle mit einem aktivierten Stream](#Streams.Lambda.Tutorial.CreateTable)
+ [Schritt 2: Erstellen einer Lambda-Ausführungsrolle](#Streams.Lambda.Tutorial.CreateRole)
+ [Schritt 3: Erstellen eines Amazon-SNS-Themas](#Streams.Lambda.Tutorial.SNSTopic)
+ [Schritt 4: Erstellen und Testen einer Lambda-Funktion](#Streams.Lambda.Tutorial.LambdaFunction)
+ [Schritt 5: Erstellen und Testen eines Auslösers](#Streams.Lambda.Tutorial.CreateTrigger)

Das Szenario für dieses Tutorial ist Woofer, ein einfaches soziales Netzwerk. Woofer-Benutzer kommunizieren mit einer kurzen Textnachricht *Barks* („Bellen”), die an andere Woofer-Benutzer gesendet werden. Das folgende Diagramm zeigt die Komponenten und den Workflow für diese Anwendung.

![\[Woofer-Anwendungsworkflow mit einer DynamoDB-Tabelle, einem Stream-Datensatz, einer Lambda-Funktion und einem Amazon-SNS-Thema\]](http://docs.aws.amazon.com/de_de/amazondynamodb/latest/developerguide/images/StreamsAndTriggers.png)


1. Ein Benutzer schreibt ein Element in eine DynamoDB-Tabelle (`BarkTable`). Jedes Element in der Tabelle steht für eine Textnachricht („Bark”).

1. Ein neuer Stream-Datensatz wird erstellt, um zu berücksichtigen, dass ein neues Element der `BarkTable` hinzugefügt wurde.

1. Der neue Stream-Record löst eine AWS Lambda Funktion () `publishNewBark` aus.

1. Wenn der Stream-Datensatz angibt, dass ein neues Element `BarkTable` hinzugefügt wurde, liest die Lambda-Funktion die Daten aus dem Stream-Datensatz und veröffentlicht eine Nachricht für ein Thema im Amazon Simple Notification Service (Amazon SNS).

1. Die Nachricht wird von den Abonnenten des Amazon-SNS-Themas empfangen. (In diesem Tutorial ist der einzige Abonnent eine E-Mail-Adresse.)

**Bevor Sie beginnen**  
Dieses Tutorial verwendet die AWS Command Line Interface AWS CLI. Folgen Sie den Anweisungen im [AWS Command Line Interface -Benutzerhandbuch](https://docs.aws.amazon.com/cli/latest/userguide/) zum Installieren und Konfigurieren der AWS CLI.

## Schritt 1: Erstellen einer DynamoDB-Tabelle mit einem aktivierten Stream
<a name="Streams.Lambda.Tutorial.CreateTable"></a>

In diesem Schritt erstellen Sie eine DynamoDB-Tabelle (`BarkTable`), um alle Textnachrichten von Woofer-Benutzern zu speichern. Der Primärschlüssel besteht aus `Username` (Partitionsschlüssel) und `Timestamp` (Sortierschlüssel). Bei beiden Attributen handelt es sich um Zeichenfolgen.

Für `BarkTable` ist ein Stream aktiviert. Später in diesem Tutorial erstellen Sie einen Trigger, indem Sie dem Stream eine AWS Lambda Funktion zuordnen.

1. Verwenden Sie den folgenden Befehl, um die Tabelle zu erstellen.

   ```
   aws dynamodb create-table \
       --table-name BarkTable \
       --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \
       --key-schema AttributeName=Username,KeyType=HASH  AttributeName=Timestamp,KeyType=RANGE \
       --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
       --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
   ```

1. Suchen Sie in der Ausgabe nach dem `LatestStreamArn`.

   ```
   ...
   "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

   Notieren Sie sich die `region` und die `accountID`, da Sie sie für die anderen Schritte in diesem Tutorial benötigen.

## Schritt 2: Erstellen einer Lambda-Ausführungsrolle
<a name="Streams.Lambda.Tutorial.CreateRole"></a>

In diesem Schritt erstellen Sie eine AWS Identity and Access Management (IAM-) Rolle (`WooferLambdaRole`) und weisen ihr Berechtigungen zu. Diese Rolle wird von der Lambda-Funktion verwendet, die Sie in [Schritt 4: Erstellen und Testen einer Lambda-Funktion](#Streams.Lambda.Tutorial.LambdaFunction) erstellen. 

Außerdem legen Sie eine Richtlinie für die Rolle fest. Die Richtlinie enthält alle Berechtigungen, die die Lambda-Funktion zur Laufzeit benötigt.

1. Erstellen Sie eine Datei mit dem Namen `trust-relationship.json` und dem folgenden Inhalt.

------
#### [ JSON ]

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "lambda.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
   ```

------

1. Geben Sie den folgenden Befehl ein, um `WooferLambdaRole` zu erstellen.

   ```
   aws iam create-role --role-name WooferLambdaRole \
       --path "/service-role/" \
       --assume-role-policy-document file://trust-relationship.json
   ```

1. Erstellen Sie eine Datei mit dem Namen `role-policy.json` und dem folgenden Inhalt. (Ersetzen Sie `region` und `accountID` durch Ihre AWS Region und Konto-ID.)

------
#### [ JSON ]

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream",
                   "logs:PutLogEvents"
               ],
               "Resource": "arn:aws:logs:us-east-1:111122223333:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:DescribeStream",
                   "dynamodb:GetRecords",
                   "dynamodb:GetShardIterator",
                   "dynamodb:ListStreams"
               ],
               "Resource": "arn:aws:dynamodb:us-east-1:111122223333:table/BarkTable/stream/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "sns:Publish"
               ],
               "Resource": [
                   "*"
               ]
           }
       ]
   }
   ```

------

   Die Richtlinie enthält vier Anweisungen, damit `WooferLambdaRole` folgende Aufgaben ausführen kann:
   + Führen Sie eine Lambda-Funktion (`publishNewBark`). Die Funktion erstellen Sie zu einem späteren Zeitpunkt in diesem Tutorial.
   + Greifen Sie auf Amazon CloudWatch Logs zu. Die Lambda-Funktion schreibt zur Laufzeit Diagnosen in CloudWatch Logs.
   + Lesen von Daten aus dem DynamoDB Stream für `BarkTable`.
   + Veröffentlichen Sie Nachrichten in Amazon SNS.

1. Führen Sie den folgenden Befehl aus, um die Richtlinie `WooferLambdaRole` anzufügen:

   ```
   aws iam put-role-policy --role-name WooferLambdaRole \
       --policy-name WooferLambdaRolePolicy \
       --policy-document file://role-policy.json
   ```

## Schritt 3: Erstellen eines Amazon-SNS-Themas
<a name="Streams.Lambda.Tutorial.SNSTopic"></a>

In diesem Schritt erstellen Sie ein Amazon-SNS-Thema (`wooferTopic`) und abonnieren es für eine E-Mail-Adresse. Ihre Lambda-Funktion verwendet dieses Thema zum Veröffentlichen neuer Barks von Woofer-Benutzern.

1. Geben Sie den folgenden Befehl ein, um ein neues Amazon-SNS-Thema zu erstellen.

   ```
   aws sns create-topic --name wooferTopic
   ```

1. Geben Sie den folgenden Befehl ein, um `wooferTopic` für eine E-Mail-Adresse zu abonnieren. (Ersetzen Sie `region` bzw. `accountID` durch Ihre AWS -Region bzw. die Konto-ID und `example@example.com` durch eine gültige E-Mail-Adresse.)

   ```
   aws sns subscribe \
       --topic-arn arn:aws:sns:region:accountID:wooferTopic \
       --protocol email \
       --notification-endpoint example@example.com
   ```

1. Amazon SNS sendet eine Bestätigungsnachricht an Ihre E-Mail-Adresse. Klicken Sie auf den Link **Confirm subscription** (Abonnement bestätigen) in dieser E-Mail, um Ihr Abonnement abzuschließen.

## Schritt 4: Erstellen und Testen einer Lambda-Funktion
<a name="Streams.Lambda.Tutorial.LambdaFunction"></a>

In diesem Schritt erstellen Sie eine AWS Lambda Funktion (`publishNewBark`) zur Verarbeitung von `BarkTable` Stream-Datensätzen.

Die `publishNewBark`-Funktion verarbeitet nur die Stream-Ereignisse, die neuen Elementen in `BarkTable` entsprechen. Die Funktion liest Daten eines entsprechenden Ereignisses und ruft Amazon SNS auf, um es zu veröffentlichen.

1. Erstellen Sie eine Datei mit dem Namen `publishNewBark.js` und dem folgenden Inhalt. Ersetzen Sie `region` und `accountID` durch Ihre AWS Region und Konto-ID.

   ```
   'use strict';
   var AWS = require("aws-sdk");
   var sns = new AWS.SNS();
   
   exports.handler = (event, context, callback) => {
   
       event.Records.forEach((record) => {
           console.log('Stream record: ', JSON.stringify(record, null, 2));
   
           if (record.eventName == 'INSERT') {
               var who = JSON.stringify(record.dynamodb.NewImage.Username.S);
               var when = JSON.stringify(record.dynamodb.NewImage.Timestamp.S);
               var what = JSON.stringify(record.dynamodb.NewImage.Message.S);
               var params = {
                   Subject: 'A new bark from ' + who,
                   Message: 'Woofer user ' + who + ' barked the following at ' + when + ':\n\n ' + what,
                   TopicArn: 'arn:aws:sns:region:accountID:wooferTopic'
               };
               sns.publish(params, function(err, data) {
                   if (err) {
                       console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2));
                   } else {
                       console.log("Results from sending message: ", JSON.stringify(data, null, 2));
                   }
               });
           }
       });
       callback(null, `Successfully processed ${event.Records.length} records.`);
   };
   ```

1. Erstellen Sie eine ZIP-Datei mit `publishNewBark.js`. Wenn Sie das ZIP-Befehlszeilen-Dienstprogramm verwenden, geben Sie dazu den folgenden Befehl ein.

   ```
   zip publishNewBark.zip publishNewBark.js
   ```

1. Beim Erstellen der Lambda-Funktion geben Sie den Amazon-Ressourcennamen (ARN) für `WooferLambdaRole` an, den Sie in [Schritt 2: Erstellen einer Lambda-Ausführungsrolle](#Streams.Lambda.Tutorial.CreateRole) erstellt haben. Geben Sie den folgenden Befehl ein, um diesen ARN abzurufen.

   ```
   aws iam get-role --role-name WooferLambdaRole
   ```

   Suchen Sie in der Ausgabe nach dem ARN für `WooferLambdaRole`.

   ```
   ...
   "Arn": "arn:aws:iam::region:role/service-role/WooferLambdaRole"
   ...
   ```

   Verwenden Sie den folgenden Befehl, um die Lambda-Funktion zu erstellen. *roleARN*Ersetzen Sie es durch den ARN für`WooferLambdaRole`.

   ```
   aws lambda create-function \
       --region region \
       --function-name publishNewBark \
       --zip-file fileb://publishNewBark.zip \
       --role roleARN \
       --handler publishNewBark.handler \
       --timeout 5 \
       --runtime nodejs16.x
   ```

1. Testen Sie die `publishNewBark`-Funktion. Stellen Sie dazu eine Eingabe bereit, die einem echten Datensatz aus DynamoDB Streams ähnelt.

   Erstellen Sie eine Datei mit dem Namen `payload.json` und dem folgenden Inhalt. Ersetzen Sie `region` und `accountID` durch Ihre AWS-Region und die Konto-ID:

   ```
   {
       "Records": [
           {
               "eventID": "7de3041dd709b024af6f29e4fa13d34c",
               "eventName": "INSERT",
               "eventVersion": "1.1",
               "eventSource": "aws:dynamodb",
               "awsRegion": "region",
               "dynamodb": {
                   "ApproximateCreationDateTime": 1479499740,
                   "Keys": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "NewImage": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Message": {
                           "S": "This is a bark from the Woofer social network"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "SequenceNumber": "13021600000000001596893679",
                   "SizeBytes": 112,
                   "StreamViewType": "NEW_IMAGE"
               },
               "eventSourceARN": "arn:aws:dynamodb:region:account ID:table/BarkTable/stream/2016-11-16T20:42:48.104"
           }
       ]
   }
   ```

   Verwenden Sie den folgenden Befehl, um die `publishNewBark`-Funktion zu erstellen.

   ```
   aws lambda invoke --function-name publishNewBark --payload file://payload.json --cli-binary-format raw-in-base64-out output.txt
   ```

   Wenn der Test erfolgreich war, sehen Sie die folgende Ausgabe.

   ```
   {
       "StatusCode": 200,
       "ExecutedVersion": "$LATEST"
   }
   ```

   Darüber hinaus enthält die `output.txt`-Datei folgenden Text.

   ```
   "Successfully processed 1 records."
   ```

   Außerdem erhalten Sie in wenigen Minuten eine neue E-Mail-Nachricht.
**Anmerkung**  
AWS Lambda schreibt Diagnoseinformationen in Amazon CloudWatch Logs. Wenn Fehler mit Ihrer Lambda-Funktion auftreten, können Sie folgende Diagnoseverfahren zur Fehlerbehebung verwenden:  
Öffnen Sie die CloudWatch Konsole unter [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).
Wählen Sie im Navigationsbereich **Logs** (Logs) aus.
Wählen Sie die folgende Protokollgruppe aus: `/aws/lambda/publishNewBark`
Wählen Sie den aktuellen Protokoll-Stream aus, um die Ausgabe (und Fehler) der Funktion zu sehen.

## Schritt 5: Erstellen und Testen eines Auslösers
<a name="Streams.Lambda.Tutorial.CreateTrigger"></a>

In [Schritt 4: Erstellen und Testen einer Lambda-Funktion](#Streams.Lambda.Tutorial.LambdaFunction) haben Sie die Lambda-Funktion getestet, um sicherzustellen, dass sie korrekt ausgeführt wird. In diesem Schritt erstellen Sie einen *Auslöser*, indem Sie die Lambda-Funktion (`publishNewBark`) mit einer Ereignisquelle (dem `BarkTable`-Stream) verknüpfen.

1. Wenn Sie den Auslöser erstellen, müssen Sie den ARN für den `BarkTable`-Stream angeben. Geben Sie den folgenden Befehl ein, um diesen ARN abzurufen.

   ```
   aws dynamodb describe-table --table-name BarkTable
   ```

   Suchen Sie in der Ausgabe nach dem `LatestStreamArn`.

   ```
   ...
    "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

1. Geben Sie den folgenden Befehl ein, um den Auslöser zu erstellen. Ersetzen Sie `streamARN` durch den tatsächlichen Stream-ARN.

   ```
   aws lambda create-event-source-mapping \
       --region region \
       --function-name publishNewBark \
       --event-source streamARN  \
       --batch-size 1 \
       --starting-position TRIM_HORIZON
   ```

1. Testen Sie den Auslöser. Geben Sie dazu den folgenden Befehl ein, um `BarkTable` ein Element hinzuzufügen.

   ```
   aws dynamodb put-item \
       --table-name BarkTable \
       --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"}
   ```

   Sie erhalten in wenigen Minuten eine neue E-Mail-Nachricht.

1. Öffnen Sie die DynamoDB-Konsole und fügen Sie `BarkTable` weitere Elemente hinzu. Sie müssen Werte für die Attribute `Username` und `Timestamp` angeben. (Sie sollten auch einen Wert für `Message` angeben, auch wenn er nicht erforderlich ist.) Sie erhalten eine neue E-Mail-Nachricht für jedes Element, das Sie `BarkTable` hinzufügen.

   Die Lambda-Funktion verarbeitet nur neue Elemente, die Sie `BarkTable` hinzufügen. Wenn Sie ein Element in der Tabelle aktualisieren oder löschen, hat die Funktion keine Auswirkung.

**Anmerkung**  
AWS Lambda schreibt Diagnoseinformationen in Amazon CloudWatch Logs. Wenn Fehler mit Ihrer Lambda-Funktion auftreten, können Sie folgende Diagnoseverfahren zur Fehlerbehebung verwenden.  
Öffnen Sie die CloudWatch Konsole unter [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).
Wählen Sie im Navigationsbereich **Logs** (Logs) aus.
Wählen Sie die folgende Protokollgruppe aus: `/aws/lambda/publishNewBark`
Wählen Sie den aktuellen Protokoll-Stream aus, um die Ausgabe (und Fehler) der Funktion zu sehen.

# Tutorial 2: Verwenden von Filtern, um einige Ereignisse mit DynamoDB und Lambda zu verarbeiten
<a name="Streams.Lambda.Tutorial2"></a>

In diesem Tutorial erstellen Sie einen AWS Lambda Trigger, um nur einige Ereignisse in einem Stream aus einer DynamoDB-Tabelle zu verarbeiten.

**Topics**
+ [Alles zusammenfügen - CloudFormation](#Streams.Lambda.Tutorial2.Cloudformation)
+ [Zusammenführung – CDK](#Streams.Lambda.Tutorial2.CDK)

Über die [Lambda-Ereignisfilterung](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) können Sie mithilfe von Filterausdrücken steuern, welche Ereignisse Lambda zur Verarbeitung an Ihre Funktion sendet. Sie können bis zu 5 verschiedene Filter pro DynamoDB-Streams konfigurieren. Wenn Sie Batching-Fenster verwenden, wendet Lambda die Filterkriterien auf jedes neue Ereignis an, um festzustellen, ob es dem aktuellen Batch hinzugefügt werden soll.

Filter werden über Strukturen, sogenannte `FilterCriteria`, angewendet. Die 3 Hauptattribute von `FilterCriteria` sind `metadata properties`, `data properties` und `filter patterns`. 

Hier ist eine Beispielstruktur eines DynamoDB-Streams-Ereignisses:

```
{
  "eventID": "c9fbe7d0261a5163fcb6940593e41797",
  "eventName": "INSERT",
  "eventVersion": "1.1",
  "eventSource": "aws:dynamodb",
  "awsRegion": "us-east-2",
  "dynamodb": {
    "ApproximateCreationDateTime": 1664559083.0,
    "Keys": {
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" }
    },
    "NewImage": {
      "quantity": { "N": "50" },
      "company_id": { "S": "1000" },
      "fabric": { "S": "Florida Chocolates" },
      "price": { "N": "15" },
      "stores": { "N": "5" },
      "product_id": { "S": "1000" },
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" },
      "state": { "S": "FL" },
      "type": { "S": "" }
    },
    "SequenceNumber": "700000000000888747038",
    "SizeBytes": 174,
    "StreamViewType": "NEW_AND_OLD_IMAGES"
  },
  "eventSourceARN": "arn:aws:dynamodb:us-east-2:111122223333:table/chocolate-table-StreamsSampleDDBTable-LUOI6UXQY7J1/stream/2022-09-30T17:05:53.209"
}
```

`metadata properties` sind die Felder des Ereignisobjekts. Im Falle von DynamoDB-Streams sind `metadata properties` Felder wie `dynamodb` oder `eventName`. 

`data properties` sind die Felder des Ereignistexts. Um nach `data properties` zu filtern, müssen sie in `FilterCriteria` im richtigen Schlüssel eingeschlossen sein. Für DynamoDB-Ereignisquellen lautet der Datenschlüssel `NewImage` oder `OldImage`.

Schließlich definieren Filterregeln den Filterausdruck, den Sie auf eine bestimmte Eigenschaft anwenden möchten. Hier sind einige Beispiele:


| Vergleichsoperator | Beispiel | Regelsyntax (partiell) | 
| --- | --- | --- | 
|  Null  |  Der Produkttyp ist null.  |  `{ "product_type": { "S": null } } `  | 
|  Leer  |  Der Produktname ist leer.  |  `{ "product_name": { "S": [ ""] } } `  | 
|  Gleich  |  Der Bundesstaat ist Florida.  |  `{ "state": { "S": ["FL"] } } `  | 
|  Bedingung 2  |  Der Produktstatus ist Florida und die Produktkategorie „Chocolate“ (Schokolade).  |  `{ "state": { "S": ["FL"] } , "category": { "S": [ "CHOCOLATE"] } } `  | 
|  Oder  |  Der Produktstatus ist Florida oder Kalifornien.  |  `{ "state": { "S": ["FL","CA"] } } `  | 
|  Nicht  |  Der Produktstatus ist nicht Florida.  |  `{"state": {"S": [{"anything-but": ["FL"]}]}}`  | 
|  Vorhanden  |  Produkt „Homemade“ (Hausgemacht) ist vorhanden.  |  `{"homemade": {"S": [{"exists": true}]}}`  | 
|  Nicht vorhanden  |  Produkt „Homemade“ (Hausgemacht) ist nicht vorhanden.  |  `{"homemade": {"S": [{"exists": false}]}}`  | 
|  Beginnt mit  |  PK beginnt mit COMPANY (Unternehmen).  |  `{"PK": {"S": [{"prefix": "COMPANY"}]}}`  | 

Sie können bis zu 5 Ereignisfilterungsmuster für eine Lambda-Funktion angeben. Beachten Sie, dass jedes dieser 5 Ereignisse als logisches ODER ausgewertet wird. Wenn Sie also zwei Filter namens `Filter_One` und `Filter_Two` konfigurieren, führt die Lambda-Funktion `Filter_One` ODER `Filter_Two` aus.

**Anmerkung**  
Auf der Seite [Lambda-Ereignisfilterung](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) sind einige Optionen zum Filtern und Vergleichen numerischer Werte vorhanden. Im Falle von DynamoDB-Filterereignissen gelten diese jedoch nicht, da Zahlen in DynamoDB als Zeichenfolgen gespeichert werden. Bei ` "quantity": { "N": "50" }` beispielsweise wissen wir aufgrund der Eigenschaft `"N"`, dass es sich um eine Zahl handelt.

## Alles zusammenfügen - CloudFormation
<a name="Streams.Lambda.Tutorial2.Cloudformation"></a>

Um die Funktionalität der Ereignisfilterung in der Praxis zu demonstrieren, finden Sie hier eine CloudFormation Beispielvorlage. Diese Vorlage generiert eine einfache DynamoDB-Tabelle mit einem Partitionsschlüssel PK und einem Sortierschlüssel SK mit aktiviertem Amazon DynamoDB Streams. Sie erstellt eine Lambda-Funktion und eine einfache Lambda-Ausführungsrolle, die das Schreiben von Protokollen in Amazon Cloudwatch und das Lesen der Ereignisse aus dem Amazon-DynamoDB-Stream ermöglichen. Zudem fügt sie die Ereignisquellenzuordnung zwischen den DynamoDB-Streams und der Lambda-Funktion hinzu, sodass die Funktion bei jedem Ereignis im Amazon-DymamoDB-Stream ausgeführt werden kann.

```
AWSTemplateFormatVersion: "2010-09-09"

Description: Sample application that presents AWS Lambda event source filtering 
with Amazon DynamoDB Streams.

Resources:
  StreamsSampleDDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      StreamSpecification:
        StreamViewType: "NEW_AND_OLD_IMAGES"
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17",		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17",		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - dynamodb:DescribeStream
                  - dynamodb:GetRecords
                  - dynamodb:GetShardIterator
                  - dynamodb:ListStreams
                Resource: !GetAtt StreamsSampleDDBTable.StreamArn

  EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST

  ProcessEventLambda:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.7
      Timeout: 300
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import logging

          LOGGER = logging.getLogger()
          LOGGER.setLevel(logging.INFO)

          def handler(event, context):
            LOGGER.info('Received Event: %s', event)
            for rec in event['Records']:
              LOGGER.info('Record: %s', rec)

Outputs:
  StreamsSampleDDBTable:
    Description: DynamoDB Table ARN created for this example
    Value: !GetAtt StreamsSampleDDBTable.Arn
  StreamARN:
    Description: DynamoDB Table ARN created for this example
    Value: !GetAtt StreamsSampleDDBTable.StreamArn
```

Nachdem Sie diese Cloud-Formation-Vorlage bereitgestellt haben, können Sie das folgende Amazon-DynamoDB-Element einfügen:

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK",
 "company_id": "1000",
 "type": "",
 "state": "FL",
 "stores": 5,
 "price": 15,
 "quantity": 50,
 "fabric": "Florida Chocolates"
}
```

Dank der einfachen Lambda-Funktion, die direkt in dieser Cloud-Formation-Vorlage enthalten ist, sehen Sie die Ereignisse in den CloudWatch Amazon-Protokollgruppen für die Lambda-Funktion wie folgt:

```
{
  "eventID": "c9fbe7d0261a5163fcb6940593e41797",
  "eventName": "INSERT",
  "eventVersion": "1.1",
  "eventSource": "aws:dynamodb",
  "awsRegion": "us-east-2",
  "dynamodb": {
    "ApproximateCreationDateTime": 1664559083.0,
    "Keys": {
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" }
    },
    "NewImage": {
      "quantity": { "N": "50" },
      "company_id": { "S": "1000" },
      "fabric": { "S": "Florida Chocolates" },
      "price": { "N": "15" },
      "stores": { "N": "5" },
      "product_id": { "S": "1000" },
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" },
      "state": { "S": "FL" },
      "type": { "S": "" }
    },
    "SequenceNumber": "700000000000888747038",
    "SizeBytes": 174,
    "StreamViewType": "NEW_AND_OLD_IMAGES"
  },
  "eventSourceARN": "arn:aws:dynamodb:us-east-2:111122223333:table/chocolate-table-StreamsSampleDDBTable-LUOI6UXQY7J1/stream/2022-09-30T17:05:53.209"
}
```

**Filterbeispiele**
+ **Nur Produkte, die einem bestimmten Bundesstaat entsprechen**

In diesem Beispiel wird die CloudFormation Vorlage dahingehend geändert, dass sie einen Filter enthält, der allen Produkten aus Florida mit der Abkürzung „FL“ entspricht.

```
EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{ "dynamodb": { "NewImage": { "state": { "S": ["FL"] } } } }'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Wenn Sie den Stack erneut bereitstellen, können Sie das folgende DynamoDB-Element zur Tabelle hinzufügen. Beachten Sie, dass es nicht in den Lambda-Funktionsprotokollen angezeigt wird, da das Produkt in diesem Beispiel aus Kalifornien stammt.

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK#1000",
 "company_id": "1000",
 "fabric": "Florida Chocolates",
 "price": 15,
 "product_id": "1000",
 "quantity": 50,
 "state": "CA",
 "stores": 5,
 "type": ""
}
```
+ **Nur die Elemente, die mit einigen Werten im PK und SK beginnen**

In diesem Beispiel wird die CloudFormation Vorlage so geändert, dass sie die folgende Bedingung enthält:

```
EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{"dynamodb": {"Keys": {"PK": { "S": [{ "prefix": "COMPANY" }] },"SK": { "S": [{ "prefix": "PRODUCT" }] }}}}'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Beachten Sie Folgendes: Die AND-Bedingung erfordert, dass sich die Bedingung innerhalb des Musters befindet, wobei sich die Schlüssel PK und SK in demselben Ausdruck, durch ein Komma getrennt, befinden.

Entweder mit einigen Werten für PK und SK beginnen oder stammt aus bestimmten Bundesstaat.

In diesem Beispiel wird die CloudFormation Vorlage so geändert, dass sie die folgenden Bedingungen enthält:

```
  EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{"dynamodb": {"Keys": {"PK": { "S": [{ "prefix": "COMPANY" }] },"SK": { "S": [{ "prefix": "PRODUCT" }] }}}}'
          - Pattern: '{ "dynamodb": { "NewImage": { "state": { "S": ["FL"] } } } }'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Beachten Sie, dass die OR-Bedingung durch Einführung neuer Muster in den Filterabschnitt hinzugefügt wird.

## Zusammenführung – CDK
<a name="Streams.Lambda.Tutorial2.CDK"></a>

In der folgenden Beispielvorlage für die CDK-Projektbildung werden die Funktionen zum Filtern von Ereignissen veranschaulicht. Bevor Sie mit diesem CDK-Projekt arbeiten können, müssen Sie [die Voraussetzungen installieren](https://docs.aws.amazon.com/cdk/v2/guide/work-with.html). Dies beinhaltet auch die [Ausführung von Vorbereitungsskripten](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html).

**Erstellen eines CDK-Projekts**

Erstellen Sie zunächst ein neues AWS CDK Projekt, indem Sie es `cdk init` in einem leeren Verzeichnis aufrufen.

```
mkdir ddb_filters
cd ddb_filters
cdk init app --language python
```

Im Befehl `cdk init` wird der Name des Projektordners zur Benennung verschiedener Elemente des Projekts verwendet, einschließlich Klassen, Unterordnern und Dateien. Bindestriche im Ordnernamen werden in Unterstriche umgewandelt. Ansonsten sollte der Name dem Format eines Python-Bezeichners folgen. Er sollte beispielsweise nicht mit einer Zahl beginnen und keine Leerzeichen enthalten.

Um mit dem neuen Projekt zu arbeiten, aktivieren Sie seine virtuelle Umgebung. Dadurch können die Abhängigkeiten des Projekts lokal im Projektordner installiert werden und müssen nicht global installiert werden.

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

**Anmerkung**  
Möglicherweise erkennen Sie dies als den Mac/Linux Befehl zur Aktivierung einer virtuellen Umgebung. Die Python-Vorlagen enthalten eine Batch-Datei, `source.bat`, die die Verwendung desselben Befehls unter Windows ermöglicht. Der traditionelle Windows-Befehl `.venv\Scripts\activate.bat` funktioniert ebenfalls. Wenn Sie Ihr AWS CDK Projekt mit AWS CDK Toolkit v1.70.0 oder früher initialisiert haben, befindet sich Ihre virtuelle Umgebung im `.env` Verzeichnis statt. `.venv` 

**Grundlegende Infrastruktur**

Öffnen Sie die Datei `./ddb_filters/ddb_filters_stack.py` in einem Texteditor Ihrer Wahl. Diese Datei wurde auto generiert, als Sie das AWS CDK Projekt erstellt haben. 

Fügen Sie als Nächstes die Funktionen `_create_ddb_table` und `_set_ddb_trigger_function` hinzu. Diese Funktionen erstellen eine DynamoDB-Tabelle mit dem Partitionsschlüssel PK und dem Sortierschlüssel SK im Bereitstellungsmodus/On-Demand-Modus, wobei Amazon DynamoDB Streams standardmäßig aktiviert ist, um neue und alte Bilder anzuzeigen.

Die Lambda-Funktion wird im Ordner `lambda` unter der Datei `app.py` gespeichert. Diese Datei wird später erstellt. Sie wird eine Umgebungsvariable, `APP_TABLE_NAME`, enthalten. Hierbei wird es sich um den Namen der Amazon-DynamoDB-Tabelle handeln, die von diesem Stack erstellt wurde. In derselben Funktion werden wir der Lambda-Funktion Stream-Leseberechtigungen erteilen. Schließlich wird sie die DynamoDB Streams als Ereignisquelle für die Lambda-Funktion abonnieren. 

Am Ende der Datei, in der `__init__`-Methode, werden Sie die entsprechenden Konstrukte aufrufen, um sie im Stack zu initialisieren. Bei größeren Projekten, die zusätzliche Komponenten und Services erfordern, ist es möglicherweise am besten, diese Konstrukte außerhalb des Basis-Stacks zu definieren. 

```
import os
import json

import aws_cdk as cdk
from aws_cdk import (
    Stack,
    aws_lambda as _lambda,
    aws_dynamodb as dynamodb,
)
from constructs import Construct


class DdbFiltersStack(Stack):

    def _create_ddb_table(self):
        dynamodb_table = dynamodb.Table(
            self,
            "AppTable",
            partition_key=dynamodb.Attribute(
                name="PK", type=dynamodb.AttributeType.STRING
            ),
            sort_key=dynamodb.Attribute(
                name="SK", type=dynamodb.AttributeType.STRING),
            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
            stream=dynamodb.StreamViewType.NEW_AND_OLD_IMAGES,
            removal_policy=cdk.RemovalPolicy.DESTROY,
        )

        cdk.CfnOutput(self, "AppTableName", value=dynamodb_table.table_name)
        return dynamodb_table

    def _set_ddb_trigger_function(self, ddb_table):
        events_lambda = _lambda.Function(
            self,
            "LambdaHandler",
            runtime=_lambda.Runtime.PYTHON_3_9,
            code=_lambda.Code.from_asset("lambda"),
            handler="app.handler",
            environment={
                "APP_TABLE_NAME": ddb_table.table_name,
            },
        )

        ddb_table.grant_stream_read(events_lambda)

        event_subscription = _lambda.CfnEventSourceMapping(
            scope=self,
            id="companyInsertsOnlyEventSourceMapping",
            function_name=events_lambda.function_name,
            event_source_arn=ddb_table.table_stream_arn,
            maximum_batching_window_in_seconds=1,
            starting_position="LATEST",
            batch_size=1,
        )

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ddb_table = self._create_ddb_table()
        self._set_ddb_trigger_function(ddb_table)
```

Jetzt werden wir eine sehr einfache Lambda-Funktion erstellen, die die Protokolle in Amazon CloudWatch druckt. Erstellen Sie zu diesem Zweck einen neuen Ordner namens `lambda`.

```
mkdir lambda
touch app.py
```

Fügen Sie der Datei `app.py` über Ihren bevorzugten Texteditor den folgenden Inhalt hinzu:

```
import logging

LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)


def handler(event, context):
    LOGGER.info('Received Event: %s', event)
    for rec in event['Records']:
        LOGGER.info('Record: %s', rec)
```

Stellen Sie sicher, dass Sie sich im Ordner `/ddb_filters/` befinden, und geben Sie zum Erstellen der Beispielanwendung den folgenden Befehl ein:

```
cdk deploy
```

Irgendwann werden Sie aufgefordert, zu bestätigen, dass Sie die Lösung bereitstellen möchten. Akzeptieren Sie die Änderungen durch Eingabe von `Y`.

```
├───┼──────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${LambdaHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴──────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘

Do you wish to deploy these changes (y/n)? y

...

✨  Deployment time: 67.73s

Outputs:
DdbFiltersStack.AppTableName = DdbFiltersStack-AppTable815C50BC-1M1W7209V5YPP
Stack ARN:
arn:aws:cloudformation:us-east-2:111122223333:stack/DdbFiltersStack/66873140-40f3-11ed-8e93-0a74f296a8f6
```

Sobald die Änderungen bereitgestellt sind, öffnen Sie Ihre AWS Konsole und fügen Sie Ihrer Tabelle ein Element hinzu. 

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK",
 "company_id": "1000",
 "type": "",
 "state": "FL",
 "stores": 5,
 "price": 15,
 "quantity": 50,
 "fabric": "Florida Chocolates"
}
```

Die CloudWatch Protokolle sollten jetzt alle Informationen aus diesem Eintrag enthalten. 

**Filterbeispiele**
+ **Nur Produkte, die einem bestimmten Bundesstaat entsprechen**

Öffnen Sie die Datei `ddb_filters/ddb_filters/ddb_filters_stack.py` und ändern Sie sie so, dass sie den Filter enthält, der alle Produkte abgleicht, die gleich „FL“ sind. Dies kann direkt unter der `event_subscription` in Zeile 45 geändert werden.

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {"dynamodb": {"NewImage": {"state": {"S": ["FL"]}}}}
                )
            },
        ]
    },
)
```
+ **Nur die Elemente, die mit einigen Werten im PK und SK beginnen**

Ändern Sie das Python-Skript, um die folgende Bedingung aufzunehmen:

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {
                        {
                            "dynamodb": {
                                "Keys": {
                                    "PK": {"S": [{"prefix": "COMPANY"}]},
                                    "SK": {"S": [{"prefix": "PRODUCT"}]},
                                }
                            }
                        }
                    }
                )
            },
        ]
    },
```
+ **Entweder mit einigen Werten für PK und SK beginnen oder stammt aus bestimmten Bundesstaat.**

Ändern Sie das Python-Skript, um die folgenden Bedingungen aufzunehmen:

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {
                        {
                            "dynamodb": {
                                "Keys": {
                                    "PK": {"S": [{"prefix": "COMPANY"}]},
                                    "SK": {"S": [{"prefix": "PRODUCT"}]},
                                }
                            }
                        }
                    }
                )
            },
            {
                "Pattern": json.dumps(
                    {"dynamodb": {"NewImage": {"state": {"S": ["FL"]}}}}
                )
            },
        ]
    },
)
```

Beachten Sie, dass die OR-Bedingung durch Hinzufügen weiterer Elemente zum Filter-Array hinzugefügt wird.

**Bereinigen**

Suchen Sie den Filter-Stack in der Basis Ihres Arbeitsverzeichnisses und führen Sie `cdk destroy` aus. Sie werden aufgefordert, das Löschen der Ressource zu bestätigen:

```
cdk destroy
Are you sure you want to delete: DdbFiltersStack (y/n)? y
```

# Bewährte Methoden zur Verwendung von DynamoDB Streams mit Lambda
<a name="Streams.Lambda.BestPracticesWithDynamoDB"></a>

Eine AWS Lambda Funktion wird in einem *Container* ausgeführt — einer Ausführungsumgebung, die von anderen Funktionen isoliert ist. Wenn Sie eine Funktion zum ersten Mal ausführen, AWS Lambda wird ein neuer Container erstellt und mit der Ausführung des Codes der Funktion begonnen.

Eine Lambda-Funktion hat einen *Handler*, der einmal pro Aufruf ausgeführt wird. Der Handler enthält die Hauptgeschäftslogik für die Funktion. Die Lambda-Funktion in [Schritt 4: Erstellen und Testen einer Lambda-Funktion](Streams.Lambda.Tutorial.md#Streams.Lambda.Tutorial.LambdaFunction) verfügt z. B. über einen Handler, der Datensätze in einem DynamoDB-Stream verarbeiten kann. 

Sie können auch Initialisierungscode bereitstellen, der nur einmal ausgeführt wird — nachdem der Container erstellt wurde, aber bevor der Handler zum ersten Mal AWS Lambda ausgeführt wird. Die unter gezeigte Lambda-Funktion [Schritt 4: Erstellen und Testen einer Lambda-Funktion](Streams.Lambda.Tutorial.md#Streams.Lambda.Tutorial.LambdaFunction) hat einen Initialisierungscode, der das SDK für JavaScript in Node.js importiert und einen Client für Amazon SNS erstellt. Diese Objekte sollten nur einmal außerhalb des Handlers definiert werden.

Nachdem die Funktion ausgeführt wurde, AWS Lambda können Sie sich dafür entscheiden, den Container für nachfolgende Aufrufe der Funktion wiederzuverwenden. In diesem Fall kann Ihr Funktions-Handler die Ressourcen, die Sie in Ihrem Initialisierungscode definiert haben, erneut nutzen. (Sie können nicht steuern, wie lange AWS Lambda den Container beibehält oder ob der Container überhaupt wiederverwendet wird.)

Für die Verwendung AWS Lambda von DynamoDB-Triggern empfehlen wir Folgendes:
+ AWS Service-Clients sollten im Initialisierungscode instanziiert werden, nicht im Handler. Dies ermöglicht AWS Lambda die Wiederverwendung vorhandener Verbindungen für die Dauer der Lebensdauer des Containers.
+ Im Allgemeinen müssen Sie Verbindungen nicht explizit verwalten oder Verbindungspooling implementieren, da AWS Lambda dies für Sie erledigt wird.

Ein Lambda-Verbraucher für einen DynamoDB-Stream garantiert nicht genau eine Lieferung und kann gelegentlich zu Duplikaten führen. Stellen Sie sicher, dass Ihr Lambda-Funktionscode idempotent ist, um zu verhindern, dass unerwartete Probleme aufgrund doppelter Verarbeitung auftreten.

Weitere Informationen finden Sie im *AWS Lambda Entwicklerhandbuch* unter [Bewährte Methoden für die Arbeit mit AWS Lambda Funktionen](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html).

# DynamoDB Streams und Apache Flink
<a name="StreamsApacheFlink.xml"></a>

Sie können Amazon-DynamoDB-Streams-Datensätze mit Apache Flink aufnehmen. Mit [Amazon Managed Service für Apache Flink](https://aws.amazon.com/managed-service-apache-flink/) lassen sich Streaming-Daten mithilfe von Apache Flink in Echtzeit umwandeln und analysieren. Apache Flink ist ein Open-Source-Verarbeitungsframework für Streams, mit dem Echtzeitdaten verarbeitet werden können. Der Amazon-DynamoDB-Streams-Connector für Apache Flink vereinfacht die Erstellung und Verwaltung von Apache Flink-Workloads. Zudem ermöglicht er die Integration von Anwendungen in andere AWS-Services.

Amazon Managed Service für Apache Flink hilft Ihnen dabei, schnell end-to-end Stream-Verarbeitungsanwendungen für Protokollanalysen, Clickstream-Analysen, Internet der Dinge (IoT), Werbetechnologie, Spiele und mehr zu erstellen. Die vier häufigsten Anwendungsfälle sind Streaming extract-transform-load (ETL), ereignisgesteuerte Anwendungen, reaktionsschnelle Echtzeitanalysen und interaktive Abfragen von Datenströmen. Weitere Informationen dazu, wie Sie aus Amazon DynamoDB Streams in Apache Flink schreiben, finden Sie unter [Amazon DynamoDB Streams Connector](https://nightlies.apache.org/flink/flink-docs-master/docs/connectors/datastream/dynamodb/).