

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.

# 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"} }'
```