

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Index locaux secondaires
<a name="LSI"></a>

Certaines applications doivent uniquement interroger les données à l’aide de la clé primaire de la table de base. Cependant, il peut y avoir des situations où une clé de tri alternative serait utile. Pour donner à votre application un choix de clés de tri, vous pouvez créer un ou plusieurs index secondaires locaux sur une table Amazon DynamoDB, et émettre des demandes `Query` ou `Scan` par rapport à ces index.

**Topics**
+ [Étape 6 : Utilisation d’un index secondaire local](#LSI.Scenario)
+ [Projections d’attribut](#LSI.Projections)
+ [Création d’un index secondaire local](#LSI.Creating)
+ [Lecture de données à partir d’un index secondaire local](#LSI.Reading)
+ [Écritures d’élément et index secondaires locaux](#LSI.Writes)
+ [Considérations relatives au débit alloué pour les index secondaires locaux](#LSI.ThroughputConsiderations)
+ [Considérations relatives au stockage pour les index secondaires locaux](#LSI.StorageConsiderations)
+ [Collections d’articles dans les index secondaires locaux](#LSI.ItemCollections)
+ [Utilisation d'index secondaires locaux : Java](LSIJavaDocumentAPI.md)
+ [Utilisation d'index secondaires locaux : .NET](LSILowLevelDotNet.md)
+ [Utilisation d’index secondaires locaux dans la AWS CLI de DynamoDB](LCICli.md)

## Étape 6 : Utilisation d’un index secondaire local
<a name="LSI.Scenario"></a>

À titre d’exemple, considérez la table `Thread`. Cette table est utile pour une application telle que les [Forums de discussion AWS](https://forums.aws.amazon.com/). Le schéma suivant illustre la façon dont les éléments de la table seront organisés. (Tous les attributs ne sont pas affichés.)

![\[Table d’unités d’exécution contenant une liste de noms de forum, des sujets, une heure de dernière publication et un nombre de réponses.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/LSI_01.png)


DynamoDB stocke tous les éléments ayant la même valeur de clé de partition de manière continue. Dans cet exemple, étant donné un `ForumName` particulier, une opération `Query` pourrait localiser immédiatement toutes les unités d’exécution pour ce forum. Dans un groupe d’éléments ayant la même valeur de clé de partition, les éléments sont triés par valeur de clé de tri. Si la clé de tri (`Subject`) est également fournie dans la requête, DynamoDB peut réduire les résultats renvoyés, par exemple, en renvoyant toutes les unités d’exécution du forum « S3 » qui ont un `Subject` commençant par la lettre « a ».

Certaines demandes peuvent nécessiter des modèles d’accès aux données plus complexes. Par exemple : 
+ Quelles unités d’exécution de forum obtiennent le plus de vues et de réponses ?
+ Quelle unité d’exécution dans un forum particulier a le plus grand nombre de messages ?
+ Combien d’unités d’exécution ont été publiées dans un forum particulier au cours d’une période donnée ?

Pour répondre à ces questions, l’action `Query` ne serait pas suffisante. Au lieu de cela, vous devriez effectuer une opération `Scan` sur la table toute entière. Pour une table contenant des millions d’éléments, cette opération utiliserait une grande quantité de débit de lecture approvisionné et prendrait beaucoup de temps.

En revanche, vous pouvez spécifier un ou plusieurs index secondaires locaux sur des attributs autres que de clé, tels que `Replies` ou `LastPostDateTime`.

A *index secondaire local* gère une clé de tri alternative pour une valeur de clé de partition donnée. Un index secondaire local contient également une copie de tout ou partie des attributs de sa table de base. Vous spécifiez quels attributs sont projetés dans l’index secondaire local lorsque vous créez la table. Les données dans un index secondaire local sont organisées avec la même clé de partition que la table de base, mais une clé de tri différente. Cela vous permet d’accéder efficacement aux éléments de données dans cette dimension différente. Pour bénéficier d’une plus grande flexibilité de requête ou d’analyse, vous pouvez créer jusqu’à cinq index secondaires locaux par table. 

Supposons qu’une application ait besoin de trouver toutes les discussions publiées au cours des trois derniers mois dans un forum particulier. A défaut d’index secondaire local, l’application devrait effectuer une opération `Scan` sur la table `Thread` toute entière, et écarter les publications ne d’inscrivant pas dans la période spécifiée. Avec un index secondaire local, une opération `Query` pourrait utiliser `LastPostDateTime` comme clé de tri et trouver les données rapidement.

Le diagramme suivant illustre un index secondaire local nommé `LastPostIndex`. Notez que la clé de partition est la même que celle de la table `Thread`, mais la clé de tri est `LastPostDateTime`.

![\[LastPostIndex tableau contenant une liste des noms des forums, des sujets et de l'heure du dernier message.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/LSI_02.png)


Chaque index secondaire local doit remplir les conditions suivantes :
+ La clé de partition est la même que celle de sa table de base.
+ La clé de tri se compose exactement d’un attribut scalaire.
+ La clé de tri de la table de base est projetée dans l’index, où elle agit comme un attribut autre que de clé.

Dans cet exemple, la clé de partition est `ForumName` et la clé de tri de l’index secondaire local est `LastPostDateTime`. En outre, la valeur de clé de tri de la table de base (dans cet exemple, `Subject`) est projetée dans l’index, mais ne fait pas partie de la clé d’index. Si une application a besoin d’une liste basée sur `ForumName` et `LastPostDateTime`, elle peut émettre une demande `Query` par rapport à `LastPostIndex`. Les résultats de la requête sont triés par `LastPostDateTime`, et peuvent être renvoyés dans un ordre croissant ou décroissant. La requête peut également appliquer des conditions de clé, telles que renvoyer uniquement les éléments qui ont une valeur `LastPostDateTime` s’inscrivant dans une période particulière.

Chaque index secondaire local contient automatiquement les clés de partition et de tri de sa table de base. Vous pouvez éventuellement projeter des attributs autres que de clé dans l’index. Lorsque vous interrogez l’index, DynamoDB peut extraire ces attributs projetés de façon efficace. Quand vous interrogez un index secondaire local, la requête peut également extraire des attributs qui ne sont *pas* projetés dans l’index. DynamoDB extrait automatiquement ces attributs de la table de base, mais moyennant une latence et des coûts de débit approvisionné plus élevés.

Pour tout index secondaire local, vous pouvez stocker jusqu’à 10 Go de données par valeur de clé de partition. Cette figure inclut tous les éléments de la table de base, ainsi que tous les éléments des index, qui ont la même valeur de clé de partition. Pour de plus amples informations, veuillez consulter [Collections d’articles dans les index secondaires locaux](#LSI.ItemCollections).

## Projections d’attribut
<a name="LSI.Projections"></a>

Avec `LastPostIndex`, une application pourrait utiliser `ForumName` et `LastPostDateTime` en tant que critères de requête. Toutefois, pour récupérer des attributs supplémentaires, DynamoDB doit effectuer des opérations de lecture supplémentaires par rapport à la table `Thread`. Ces lectures supplémentaires appelées *extractions* peuvent augmenter le volume total de débit approvisionné requis pour une requête.

Supposons que vous souhaitiez remplir une page Web avec une liste de tous les sujets de « S3 » et le nombre de réponses pour chaque fil, triés selon la dernière réponse en date/time commençant par la réponse la plus récente. Pour remplir cette liste, vous avez besoin des attributs suivants :
+ `Subject`
+ `Replies`
+ `LastPostDateTime`

La manière la plus efficace d’interroger ces données et d’éviter les opérations d’extraction serait de projeter l’attribut `Replies` de la table vers l’index secondaire local, comme illustré dans ce diagramme.

![\[LastPostIndex tableau contenant une liste des noms des forums, des heures des derniers messages, des sujets et des réponses.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/LSI_03.png)




Une *projection* est l’ensemble d’attributs copié à partir d’une table dans un index secondaire. Les clés de partition et de tri de la table sont toujours projetées dans l’index. Vous pouvez projeter d’autres attributs en fonction des exigences de requête de votre application. Lorsque vous interrogez un index, Amazon DynamoDB peut accéder à n’importe quel attribut dans la projection, comme s’il se trouvait dans une table.

Lorsque vous créez un index secondaire, vous devez spécifier les attributs qui seront projetés dans celui-ci. Pour cela, DynamoDB propose trois options :
+ *KEYS\$1ONLY* – Chaque élément de l’index se compose uniquement des valeurs de clé de partition et de tri de la table, ainsi que des valeurs de clé d’index. L’option `KEYS_ONLY` produit l’index secondaire le plus petit possible.
+ *INCLUDE* – En plus des attributs décrits dans `KEYS_ONLY`, l’index secondaire inclut des attributs autres que de clé, que vous spécifiez.
+ *ALL* – L’index secondaire inclut tous les attributs de la table source. Toutes les données de la table étant dupliquées dans l’index, une projection `ALL` produit l’index secondaire le plus grand possible.

Dans le diagramme précédent, l’attribut autre que de clé `Replies` est projeté dans `LastPostIndex`. Une application peut interroger `LastPostIndex` au lieu de la table `Thread` toute entière pour remplir une page avec des sujets (`Subject`), réponses (`Replies`) et horodatages de dernière publication `LastPostDateTime`. Si d’autres attributs autres que de clé sont demandés, DynamoDB doit les extraire de la table `Thread`. 

Du point de vue d’une application, l’extraction d’attributs supplémentaires à partir de la table de base est automatique et transparente. Il n’est donc pas nécessaire de réécrire une logique d’application. Cependant, une telle récupération peut réduire considérablement l’avantage en termes de performances de l’utilisation d’un index secondaire local.

Lorsque vous choisissez les attributs à projeter sur un index secondaire local, vous devez prendre en compte le compromis entre les coûts de débit approvisionné et les coûts de stockage :
+ Si vous n’avez besoin d’accéder qu’à quelques attributs avec la plus faible latence possible, envisagez de projeter ces seuls attributs dans un index secondaire local. Plus l’index est petit, moins les coûts d’écriture et de stockage sont élevés. S’il existe des attributs que vous devez extraire occasionnellement, le coût du débit approvisionné risque d’être supérieur au coût à plus long terme du stockage de ces attributs.
+ Si votre application accède fréquemment à certains attributs autres que de clé, vous devez envisager de projeter ces attributs dans un index secondaire local. Les coûts de stockage supplémentaires de l’index secondaire local compensent le coût d’exécution d’analyses de table fréquentes.
+ Si vous avez besoin d’accéder fréquemment à la plupart des attributs autres que de clé, vous pouvez projeter ceux-ci (voire la table de base toute entière) dans un index secondaire local. Vous bénéficiez ainsi d’une flexibilité maximale et d’une consommation de débit approvisionné minimale, car aucune extraction n’est requise. Cependant, vos coûts de stockage augmentent, voire doublent, si vous projetez tous les attributs.
+ Si votre application doit interroger une table peu fréquemment, mais doit effectuer un grand nombre d’écritures ou de mises à jour de données dans la table, pensez à projeter *KEYS\$1ONLY*. L’index secondaire local sera d’une taille minimum, mais continuera d’être disponible chaque fois que ce sera nécessaire pour une activité de requête. 

## Création d’un index secondaire local
<a name="LSI.Creating"></a>

Pour créer un ou plusieurs index secondaires locaux sur une table, utilisez le paramètre `LocalSecondaryIndexes` de l’opération `CreateTable`. Des index secondaires locaux sur une table sont créés lors de la création de celle-ci. Lorsque vous supprimez une table, tous les index secondaires globaux sur celle-ci sont également supprimés.

Vous devez spécifier un attribut autre que de clé pour agir en tant que clé de tri de l’index secondaire local. L’attribut que vous choisissez doit être un scalaire `String`, `Number` ou `Binary`. Les autres types scalaires, types de document et types d’ensemble ne sont pas autorisés. Pour obtenir la liste complète des types de données, consultez [Types de données](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes).

**Important**  
Pour les tables avec des index secondaires locaux, il existe une limite de taille de 10 Go par valeur de clé de partition. Une table avec des index secondaires locaux peut stocker n’importe quel nombre d’éléments, à condition qu’aucune valeur de clé de partition n’ait une taille supérieure à 10 Go. Pour de plus amples informations, veuillez consulter [Taille limite de collection d’éléments](#LSI.ItemCollections.SizeLimit).

Vous pouvez projeter des attributs de tout type de données dans un index secondaire local. Celui-ci inclut des scalaires, des documents et des ensembles. Pour obtenir la liste complète des types de données, consultez [Types de données](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes).

## Lecture de données à partir d’un index secondaire local
<a name="LSI.Reading"></a>

Vous pouvez extraire des éléments d’un index secondaire local à l’aide des opérations `Query` et `Scan`. Vous ne pouvez pas utiliser les opérations `GetItem` et `BatchGetItem` sur un index secondaire local.

### Interrogation d’un index secondaire local
<a name="LSI.Querying"></a>

Dans une table DynamoDB, les valeurs combinées des clés de partition et de tri pour chaque élément doivent être uniques. Cependant, dans un index secondaire local, la valeur de clé de tri n’a pas besoin d’être unique pour une valeur de clé de partition donnée. Si plusieurs éléments dans l’index secondaire local ont la même valeur de clé de tri, une opération `Query` renvoie tous les éléments ayant la même valeur de clé de partition. Dans la réponse, les éléments correspondants ne sont pas renvoyés dans un ordre particulier.

Vous pouvez interroger un index secondaire local en utilisant des lectures éventuellement ou fortement cohérentes. Pour spécifier le type de cohérence que vous souhaitez, utilisez le paramètre `ConsistentRead` de l’opération `Query`. Une lecture fortement cohérente d’un index secondaire local renvoie toujours les dernières valeurs mises à jour. Si la requête doit extraire des attributs supplémentaires de la table de base, ces attributs sont cohérents par rapport à l’index.

**Example**  
Considérez les données suivantes renvoyées par une opération `Query` qui demande des données des unités d’exécution de discussion dans un forum particulier.  

```
{
    "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"}
    }
}
```
Dans cette requête :  
+ DynamoDB accède à `LastPostIndex` en utilisant la clé de partition `ForumName` afin de localiser les éléments d’index pour « EC2 ». Tous les éléments d’index avec cette clé sont stockés les uns à côté des autres pour une récupération rapide.
+ Dans ce forum, DynamoDB utilise l’index pour rechercher les clés correspondant à la condition `LastPostDateTime` spécifiée.
+ L’attribut `Replies` étant projeté dans l’index, DynamoDB peut extraire cet attribut sans utiliser de débit approvisionné supplémentaire.
+ L’attribut `Tags` n’étant pas projeté dans l’index, DynamoDB doit accéder à la table `Thread` pour l’en extraire.
+ Les résultats sont renvoyés, triés par `LastPostDateTime`. Les entrées d’index sont triées par valeur de clé de partition, puis par valeur de clé de tri, et `Query` les renvoie dans l’ordre de leur stockage (vous pouvez utiliser le paramètre `ScanIndexForward` pour renvoyer les résultats dans l’ordre décroissant).
L’attribut `Tags` n’étant pas projeté dans l’index secondaire local, DynamoDB doit utiliser des unités de capacité de lecture supplémentaires pour l’extraire de la table de base. Si vous devez exécuter cette requête souvent, nous vous recommandons de projeter `Tags` dans `LastPostIndex` pour éviter une extraction à partir de la table de base. Toutefois, si vous n’avez besoin d’accéder à `Tags` qu’occasionnellement, il se peut que le coût de stockage supplémentaire lié à la projection de `Tags` dans l’index n’en vaille pas la peine.

### Analyse d’un index secondaire local
<a name="LSI.Scanning"></a>

Vous pouvez utiliser l’opération `Scan` pour extraire toutes les données d’un index secondaire local. Vous devez fournir le nom de la table de base et le nom de l’index dans la demande. Avec une opération `Scan`, DynamoDB lit toutes les données de l’index et les renvoie à l’application. Vous pouvez également demander que seules quelques données soient retournées, et que les données restantes soient ignorées. Pour ce faire, utilisez le paramètre `FilterExpression` de l’API `Scan`. Pour de plus amples informations, veuillez consulter [Filtrer les expressions à des fins d’analyse](Scan.md#Scan.FilterExpression).

## Écritures d’élément et index secondaires locaux
<a name="LSI.Writes"></a>

DynamoDB conserve automatiquement tous les index secondaires locaux synchronisés avec leurs tables de base respectives. Les applications n’écrivent jamais directement sur un index. Cependant, il est important de comprendre les implications de la façon dont DynamoDB gère ces index.

Lorsque vous créez un index secondaire local, vous spécifiez un attribut qui servira de clé de tri pour l’index. Vous spécifiez également un type de données pour cet attribut. Cela signifie que, chaque fois que vous écrivez un élément dans la table de base, si l’élément définit un attribut de clé d’index, son type doit correspondre au type de données du schéma de clé d’index. Dans le cas de `LastPostIndex`, la clé de tri `LastPostDateTime` dans l’index est définie comme un type de données `String`. Si vous essayez d’ajouter un élément à la table `Thread` et spécifiez un type de données différent pour `LastPostDateTime` (par exemple, `Number`), DynamoDB renvoie une `ValidationException` en raison de la discordance des types de données.

Il n'est pas nécessaire d' one-to-oneétablir une relation entre les éléments d'une table de base et ceux d'un index secondaire local. En fait, ce comportement peut être avantageux pour de nombreuses applications. 

Une table avec de nombreux index secondaires locaux s’expose à des coûts plus élevés pour l’activité d’écriture qu’une table ayant moins d’index. Pour de plus amples informations, veuillez consulter [Considérations relatives au débit alloué pour les index secondaires locaux](#LSI.ThroughputConsiderations).

**Important**  
Pour les tables avec des index secondaires locaux, il existe une limite de taille de 10 Go par valeur de clé de partition. Une table avec des index secondaires locaux peut stocker n’importe quel nombre d’éléments, à condition qu’aucune valeur de clé de partition n’ait une taille supérieure à 10 Go. Pour de plus amples informations, veuillez consulter [Taille limite de collection d’éléments](#LSI.ItemCollections.SizeLimit).

## Considérations relatives au débit alloué pour les index secondaires locaux
<a name="LSI.ThroughputConsiderations"></a>

Lorsque vous créez une table dans DynamoDB, vous approvisionnez des unités de capacité de lecture et d’écriture pour la charge de travail prévue de la table. Cette charge de travail inclut l’activité de lecture et d’écriture sur les index secondaires locaux de la table.

Pour voir les prix actuels de capacité de débit approvisionnée, consultez [Tarification Amazon DynamoDB](https://aws.amazon.com/dynamodb/pricing).

### Unités de capacité de lecture
<a name="LSI.ThroughputConsiderations.Reads"></a>

Lorsque vous interrogez un index secondaire local, le nombre d’unités de capacité de lecture consommées dépend du mode d’accès aux données.

Comme une interrogation de table, une interrogation d’index peut utiliser des lectures éventuellement ou fortement cohérentes en fonction de la valeur de `ConsistentRead`. Une lecture fortement cohérente utilise une unité de capacité de lecture ; une lecture éventuellement cohérente n’en utilise que la moitié. Ainsi, en choisissant des lectures éventuellement cohérentes, vous pouvez réduire vos coûts d’unités de capacité de lecture.

Pour les interrogations d’index qui demandent uniquement des clés d’index et des attributs projetés, DynamoDB calcule l’activité de lecture approvisionnée de la même façon que pour des requêtes sur des tables. La seule différence est que le calcul est basé sur les tailles des entrées d’index, plutôt que sur la taille de l’élément de la table de base. Le nombre d’unités de capacité de lecture est la somme des tailles de tous les attributs projetés de tous les éléments renvoyés. Le résultat est ensuite arrondi à la limite de 4 Ko suivante. Pour plus d’informations sur la façon dont DynamoDB calcule l’utilisation du débit approvisionné, consultez [Mode de capacité provisionnée DynamoDB](provisioned-capacity-mode.md).

Pour les interrogations d’index qui lisent des attributs qui ne sont pas projetés dans l’index secondaire local, DynamoDB doit extraire ces attributs de la table de base, en plus de lire les attributs projetés à partir de l’index. Ces extractions se produisent lorsque vous incluez des attributs non projetés dans les paramètres `Select` ou `ProjectionExpression` de l’opération `Query`. L’extraction entraîne une latence supplémentaire des réponses aux requêtes, ainsi qu’un surcoût de débit approvisionné. En plus des lectures de l’index secondaire local décrites précédemment, vous êtes facturé pour les unités de capacité de lecture utilisées pour extraire chaque élément de la table de base. Ces frais ont trait à la lecture de chaque élément entier de la table, pas seulement des attributs demandés.

La taille maximum des résultats renvoyés par une opération `Query` est de 1 Mo. Cela inclut les tailles de tous les noms et valeurs d’attribut à travers l’ensemble des éléments retournés. Toutefois, si une requête sur un index secondaire local amène DynamoDB à extraire des attributs d’élément de la table de base, la taille maximum des données dans les résultats peut être inférieure. Dans ce cas, la taille du résultat est la somme de :
+ La taille des éléments correspondants dans l’index, arrondie à la limite de 4 Ko suivante.
+ La taille de chaque élément correspondant dans la table de base, chaque élément étant arrondi individuellement à la limite de 4 Ko suivante.

Avec cette formule, la taille maximum des résultats renvoyés par une opération Query est toujours de 1 Mo.

Par exemple, considérons une table où la taille de chaque élément est de 300 octets. Il existe un index secondaire local sur cette table, mais seuls 200 octets de chaque élément sont projetés dans l’index. Supposons à présent que vous effectuez une opération `Query` sur cet index, que la requête nécessite une extraction de table pour chaque élément, et que la requête renvoie 4 éléments. DynamoDB additionne les valeurs suivantes :
+ La taille des éléments correspondants dans l’index : 200 octets × 4 éléments = 800 octets, valeur ensuite arrondie à 4 Ko.
+ La taille de chaque élément correspondant dans la table de base : (300 octets, arrondis à 4 Ko) × 4 éléments = 16 Ko.

La taille totale des données dans le résultat est donc de 20 Ko.

### Unités de capacité d’écriture
<a name="LSI.ThroughputConsiderations.Writes"></a>

Quand un élément d’une table est ajouté, mis à jour ou supprimé, la mise à jour des index secondaires locaux utilise des unités de capacité d’écriture approvisionnée pour la table. Le coût total du débit alloué pour une écriture est la somme des unités de capacité d’écriture consommées par l’écriture dans la table de base, et de celles consommées par la mise à jour des index secondaires locaux.

Le coût d’écriture d’un élément dans un index secondaire local dépend de plusieurs facteurs :
+ Si vous écrivez un nouvel élément sur la table qui définit un attribut indexé, ou que vous mettez à jour un élément existant pour définir un attribut indexé précédemment non défini, une opération d’écriture est nécessaire pour insérer l’élément dans l’index.
+ Si une mise à jour de la table change la valeur d’un attribut de clé indexé (de A en B), deux écritures sont requises, une pour supprimer l’élément précédent de l’index et une autre pour insérer le nouvel élément dans l’index.  
+ Si un élément était présent dans l’index, mais qu’une écriture sur la table a entraîné la suppression de l’attribut indexé, une écriture est nécessaire pour supprimer de l’index la projection de l’ancien élément.
+ Si un élément n’est pas présent dans l’index avant ou après la mise à jour de l’élément, il n’y a aucun coût d’écriture supplémentaire pour l’index.

Tous ces facteurs partent du principe que la taille de chaque élément dans l’index est inférieure ou égale à la taille d’élément de 1 Ko pour le calcul des unités de capacité d’écriture. Les plus grandes entrées d’index nécessitent des unités de capacité en écriture supplémentaires. Vous pouvez réduire vos coûts d’écriture en considérant les attributs que vos requêtes ont besoin de renvoyer et en projetant uniquement ces attributs dans l’index.

## Considérations relatives au stockage pour les index secondaires locaux
<a name="LSI.StorageConsiderations"></a>

Quand une application écrit un élément dans une table, DynamoDB copie automatiquement le sous-ensemble approprié d’attributs vers les index secondaires locaux où ces attributs doivent apparaître. Votre AWS compte est débité pour le stockage de l'article dans la table de base ainsi que pour le stockage des attributs dans les index secondaires locaux de cette table.

La quantité d’espace utilisée par un élément de l’index est la somme des éléments suivants :
+ La taille en octets de la clé primaire de la table de base (clé de partition et clé de tri)
+ La taille en octets de l’attribut de clé d’index
+ La taille en octets des attributs projetés (le cas échéant)
+ 100 octets de surcharge par élément d’index

Pour estimer les besoins en stockage d’un index secondaire local, vous pouvez estimer la taille moyenne d’un élément de l’index, puis multiplier cette valeur par le nombre d’éléments présents dans l’index.

Si une table contient un élément dans lequel un attribut particulier n’est pas défini, tandis que cet attribut est défini en tant que clé de tri d’index, DynamoDB n’écrit aucune donnée pour cet élément dans l’index. 

## Collections d’articles dans les index secondaires locaux
<a name="LSI.ItemCollections"></a>

**Note**  
Cette section concerne uniquement les tables qui ont des index secondaires locaux.

Dans DynamoDB, une *collection d’éléments* est un groupe quelconque d’éléments ayant la même valeur de clé de partition dans une table, ainsi que de tous leurs index secondaires locaux. Dans les exemples utilisés tout au long de cette section, la clé de partition pour la table `Thread` est `ForumName`, et la clé de partition pour `LastPostIndex` est également `ForumName`. Tous les éléments de table et d’index ayant le même `ForumName` font partie de la même collection d’éléments. Par exemple, la table `Thread` et l’index secondaire local `LastPostIndex` contiennent une collection d’éléments pour le forum `EC2`, et une autre pour le forum `RDS`.

Le diagramme suivant illustre la collection d’éléments pour le forum `S3`.

![\[Collection d’éléments DynamoDB comportant des éléments d’index secondaire global ayant la même valeur de clé de partition S3.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/LSI_04.png)


Dans ce diagramme, la collection d’éléments se compose de tous les éléments figurant dans `Thread` et `LastPostIndex`, où la valeur de clé de partition `ForumName` est « S3 ». S’il y avait d’autres index secondaires locaux sur la table, tous les éléments dans ces index dont la valeur de `ForumName` est « S3 » feraient également partie de la collection d’éléments.

Vous pouvez utiliser n’importe laquelle des opérations suivantes dans DynamoDB pour renvoyer des informations sur les collections d’éléments :
+ `BatchWriteItem`
+ `DeleteItem`
+ `PutItem`
+ `UpdateItem`
+ `TransactWriteItems`

Chacune de ces opérations prend en charge le paramètre `ReturnItemCollectionMetrics`. Lorsque vous définissez ce paramètre sur `SIZE`, vous pouvez afficher des informations sur la taille de chaque collection d’éléments dans l’index.

**Example**  
Voici un exemple de sortie d’une opération `UpdateItem` sur la table `Thread`, avec la valeur `ReturnItemCollectionMetrics` définie sur `SIZE`. L’élément mis à jour avait une valeur `ForumName` de « EC2 », de sorte que la sortie inclut des informations sur cette collection d’éléments.  

```
{
    ItemCollectionMetrics: {
        ItemCollectionKey: {
            ForumName: "EC2"
        },
        SizeEstimateRangeGB: [0.0, 1.0]
    }
}
```
L’objet `SizeEstimateRangeGB` montre que la taille de cette collection d’éléments est comprise entre 0 et 1 Go. DynamoDB mettant régulièrement à jour cette estimation de taille, les nombres pourraient être différents lors de la prochaine modification de l’élément.

### Taille limite de collection d’éléments
<a name="LSI.ItemCollections.SizeLimit"></a>

La taille maximale de toute collection d’éléments pour une table possédant un ou plusieurs index secondaires locaux est de 10 Go. Cela ne s’applique pas aux collections d’éléments des tables sans index secondaires locaux, ni aux collections d’éléments dans des index secondaires globaux. Seules les tables ayant un ou plusieurs index secondaires locaux sont concernées.

Si une collection d'articles dépasse la limite de 10 Go, DynamoDB peut renvoyer `ItemCollectionSizeLimitExceededException` un, et vous ne pourrez peut-être pas ajouter d'autres articles à la collection d'articles ou augmenter la taille des éléments qui se trouvent dans la collection d'articles. (les opérations de lecture et d’écriture qui réduisent la taille de la collection d’éléments restent autorisées). Vous pouvez toujours ajouter des éléments à d’autres collections d’éléments.

Pour réduire la taille d’une collection d’éléments, vous pouvez effectuer l’une des opérations suivantes :
+ Supprimer tous les éléments inutiles avec la valeur de clé de partition en question. Lorsque vous supprimez ces éléments de la table de base, DynamoDB supprime également toutes les entrées d’index ayant la même valeur de clé de partition.
+ Mettre à jour les éléments en supprimant des attributs ou en réduisant la taille des attributs. Si ces attributs sont projetés dans des index secondaires locaux, DynamoDB réduit également la taille des entrées d’index correspondantes.
+ Créer une table avec les mêmes clés de partition et de tri, puis déplacer les éléments de l’ancienne table vers la nouvelle. Cela peut être une bonne approche si une table contient des données historiques rarement utilisées. Vous pouvez également envisager d’archiver ces données historiques sur Amazon Simple Storage Service (Amazon S3).

Lorsque la taille totale de la collection d’éléments passe sous le seuil de 10 Go, vous pouvez à nouveau ajouter des éléments avec la même valeur de clé de partition.

En guise de bonne pratique, nous vous recommandons d’instrumenter votre application pour contrôler les tailles de vos collections d’éléments. Une façon de le faire consiste à définir le paramètre `ReturnItemCollectionMetrics` sur `SIZE` chaque fois que vous utilisez `BatchWriteItem`, `DeleteItem`, `PutItem` ou `UpdateItem`. Votre application doit examiner l’objet `ReturnItemCollectionMetrics` dans la sortie et journaliser un message d’erreur chaque fois qu’une collection d’éléments dépasse une limite de taille définie par l’utilisateur (par exemple, 8 Go). Définir une limite inférieure à 10 Go fournirait un système d’avertissement précoce qui vous permettrait de savoir qu’une collection d’éléments approche de la limite dans le temps pour faire quelque chose à ce sujet.

### Collections et partitions d’éléments
<a name="LSI.ItemCollections.OnePartition"></a>

Dans une table avec un ou plusieurs index secondaires locaux, chaque collection d’éléments est stockée dans une partition. La taille totale d’une collection d’éléments de ce type est limitée à la capacité de cette partition, soit 10 Go. Pour une application dans laquelle le modèle de données inclut des collections d’éléments de taille illimitée, ou dans laquelle vous pouvez raisonnablement vous attendre à ce que certaines collections d’éléments dépassent 10 Go à l’avenir, envisagez plutôt d’utiliser un index secondaire global.

Vous devez concevoir vos applications de sorte que les données de table soient réparties uniformément entre des valeurs de clé de partition distinctes. Pour les tables avec des index secondaires locaux, vos applications ne doivent pas créer de « points chauds » d’activité de lecture et d’écriture au sein d’une seule collection d’éléments sur une seule partition. 

# Utilisation d'index secondaires locaux : Java
<a name="LSIJavaDocumentAPI"></a>

Vous pouvez utiliser l'API AWS SDK pour Java Document pour créer une table Amazon DynamoDB avec un ou plusieurs index secondaires locaux, décrire les index de la table et effectuer des requêtes à l'aide des index.

Les étapes les plus courantes pour les opérations sur les tables à l'aide de l'API AWS SDK pour Java Document sont les suivantes.

1. Créez une instance de la classe `DynamoDB`.

1. Fournissez les paramètres obligatoires et facultatifs pour l'opération en créant les objets de requête correspondants. 

1. Appelez la méthode appropriée fournie par le client, que vous avez créée à l'étape précédente. 

**Topics**
+ [Créer une table avec un index secondaire local](#LSIJavaDocumentAPI.CreateTableWithIndex)
+ [Décrire une table avec un index secondaire local](#LSIJavaDocumentAPI.DescribeTableWithIndex)
+ [Interroger un index secondaire local](#LSIJavaDocumentAPI.QueryAnIndex)
+ [Exemple : index secondaires locaux utilisant l'API de document de Java](LSIJavaDocumentAPI.Example.md)

## Créer une table avec un index secondaire local
<a name="LSIJavaDocumentAPI.CreateTableWithIndex"></a>

Vous devez créer des index secondaires locaux au moment où vous créez une table. Pour ce faire, utilisez la méthode `createTable` et fournissez vos spécifications pour un ou plusieurs index secondaires locaux. L'exemple de code Java suivant crée une table destinée à accueillir des informations sur des chansons dans une collection musicale. La clé de partition est `Artist`, et la clé de tri `SongTitle`. Un index secondaire, `AlbumTitleIndex`, facilite les requêtes par titre d'album. 

Voici les étapes à suivre pour créer une table avec un index secondaire local à l'aide de l'API Document DynamoDB. 

1. Créez une instance de la classe `DynamoDB`.

1. Créez une instance de la classe `CreateTableRequest` pour fournir l'information de requête. 

   Vous devez fournir le nom de la table, sa clé primaire et les valeurs de débit approvisionné. Pour l'index secondaire local, vous devez fournir le nom d'index, le nom et le type de données pour la clé de tri d'index, le schéma de clé pour l'index et la projection d'attribut.

1. Appelez la méthode `createTable` en fournissant l'objet de demande comme paramètre.

L’exemple de code Java suivant illustre les tâches précédentes. Le code crée une table (`Music`) avec un index secondaire sur l'attribut `AlbumTitle`. Les clés de partition et de tri de table, ainsi que la clé de tri d'index, sont les seuls attributs projetés dans l'index.

```
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());
```

Vous devez attendre que DynamoDB crée la table et définisse l'état de celle-ci sur `ACTIVE`. Après cela, vous pouvez commencer à insérer des éléments de données dans la table.

## Décrire une table avec un index secondaire local
<a name="LSIJavaDocumentAPI.DescribeTableWithIndex"></a>

Pour obtenir des informations concernant les index secondaires locaux sur une table, utilisez la méthode `describeTable`. Pour chaque index, vous pouvez accéder à son nom, à son schéma de clé et aux attributs projetés.

Voici les étapes à suivre pour accéder aux informations d'index secondaire local sur une table à l'aide de l'API Document AWS SDK pour Java .

1. Créez une instance de la classe `DynamoDB`.

1. Créez une instance de la classe `Table`. Vous devez fournir le nom de la table.

1. Appelez la méthode `describeTable` sur l'objet `Table`.

L’exemple de code Java suivant illustre les tâches précédentes.

**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());
    }
}
```

## Interroger un index secondaire local
<a name="LSIJavaDocumentAPI.QueryAnIndex"></a>

Vous pouvez utiliser l'opération `Query` sur un index secondaire local de la même manière que vous utilisez l'opération `Query` sur une table. Vous devez spécifier le nom d’index, les critères de requête pour la clé de tri d’index et les attributs que vous souhaitez renvoyer. Dans cet exemple, l’index est `AlbumTitleIndex` et la clé de tri d’index est `AlbumTitle`. 

Les seuls attributs renvoyés sont ceux qui ont été projetés dans l’index. Vous pourriez également modifier cette requête pour sélectionner des attributs autres que de clé, mais cela nécessiterait une activité d’extraction de table relativement coûteuse. Pour plus d’informations sur les extractions de table, consultez [Projections d’attribut](LSI.md#LSI.Projections).

Voici les étapes à suivre pour interroger un index secondaire local à l'aide de l'API AWS SDK pour Java Document. 

1. Créez une instance de la classe `DynamoDB`.

1. Créez une instance de la classe `Table`. Vous devez fournir le nom de la table.

1. Créez une instance de la classe `Index`. Vous devez fournir le nom d'index.

1. Appelez la méthode `query` de la classe `Index`.

L’exemple de code Java suivant illustre les tâches précédentes.

**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());
}
```

### Lectures cohérentes sur un index secondaire local
<a name="LSIJavaDocumentAPI.ConsistentReads"></a>

Contrairement aux index secondaires globaux, qui ne prennent en charge que les lectures finalement cohérentes, un index secondaire local prend en charge à la fois les lectures cohérentes et les lectures fortement cohérentes. Une lecture fortement cohérente d’un index secondaire local renvoie toujours les dernières valeurs mises à jour. Si la requête doit extraire des attributs supplémentaires de la table de base, ces attributs extraits sont également cohérents par rapport à l'index.

Par défaut, `Query` utilise éventuellement des lectures cohérentes. Pour demander une lecture très cohérente, réglez `ConsistentRead` sur `true` dans le`QuerySpec`. Les exemples de requêtes suivants `AlbumTitleIndex` utilisant une lecture très cohérente :

**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);
```

**Note**  
Une lecture très cohérente consomme une unité de capacité de lecture pour 4 Ko de données renvoyées (arrondies au chiffre supérieur), alors qu'une lecture finalement cohérente en consomme la moitié. Par exemple, une lecture hautement cohérente qui renvoie 9 Ko de données consomme 3 unités de capacité de lecture (9 Ko/4 Ko = 2,25, arrondi à 3), tandis que la même requête utilisant une lecture finalement cohérente consomme 1,5 unité de capacité de lecture. Si votre application peut tolérer la lecture de données légèrement périmées, utilisez éventuellement des lectures cohérentes afin de réduire l'utilisation de votre capacité de lecture. Pour de plus amples informations, veuillez consulter [Unités de capacité de lecture](LSI.md#LSI.ThroughputConsiderations.Reads).

# Exemple : index secondaires locaux utilisant l'API de document de Java
<a name="LSIJavaDocumentAPI.Example"></a>

L'exemple de code Java suivant montre comment utiliser les index secondaires locaux dans Amazon DynamoDB. L'exemple crée une table nommée `CustomerOrders` avec une clé de partition `CustomerId` et une clé de tri `OrderId`. Il y a deux index secondaires locaux sur cette table :
+ `OrderCreationDateIndex` – La clé de tri est.`OrderCreationDate`, et les attributs suivants sont projetés dans l'index :
  + `ProductCategory`
  + `ProductName`
  + `OrderStatus`
  + `ShipmentTrackingId`
+ `IsOpenIndex` – La clé de tri est `IsOpen` et tous les attributs de table sont projetés dans l'index.

Une fois la table `CustomerOrders` créée, le programme charge la table avec des données représentant des commandes de clients. Il interroge ensuite les données à l'aide d'index secondaires locaux. Enfin, le programme supprime la table `CustomerOrders`.

Pour step-by-step obtenir des instructions sur le test de l'échantillon suivant, reportez-vous à[Exemples de code Java](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());
    }
}
```

# Utilisation d'index secondaires locaux : .NET
<a name="LSILowLevelDotNet"></a>

**Topics**
+ [Créer une table avec un index secondaire local](#LSILowLevelDotNet.CreateTableWithIndex)
+ [Décrire une table avec un index secondaire local](#LSILowLevelDotNet.DescribeTableWithIndex)
+ [Interroger un index secondaire local](#LSILowLevelDotNet.QueryAnIndex)
+ [Exemple : index secondaires locaux utilisant l'API de AWS SDK pour .NET bas niveau](LSILowLevelDotNet.Example.md)

Vous pouvez utiliser l'API de AWS SDK pour .NET bas niveau pour créer une table Amazon DynamoDB avec un ou plusieurs index secondaires locaux, décrire les index de la table et effectuer des requêtes à l'aide des index. Ces opérations sont mappées aux actions de l'API de bas niveau DynamoDB correspondantes. Pour de plus amples informations, veuillez consulter [Exemples de code .NET](CodeSamples.DotNet.md). 

Voici les étapes courantes pour les opérations de table à l'aide de l'API de bas niveau .NET. 

1. Créez une instance de la classe `AmazonDynamoDBClient`.

1. Fournissez les paramètres obligatoires et facultatifs pour l'opération en créant les objets de requête correspondants.

   Par exemple, créez un objet `CreateTableRequest` pour créer une table, et un objet `QueryRequest` pour interroger une table ou un index. 

1. Exécutez la méthode appropriée fournie par le client, que vous avez créée à l'étape précédente. 

## Créer une table avec un index secondaire local
<a name="LSILowLevelDotNet.CreateTableWithIndex"></a>

Vous devez créer des index secondaires locaux au moment où vous créez une table. Pour ce faire, utilisez `CreateTable` et fournissez vos spécifications pour un ou plusieurs index secondaires locaux. L'exemple de code C\$1 suivant crée une table destinée à accueillir des informations sur des chansons dans une collection musicale. La clé de partition est `Artist`, et la clé de tri `SongTitle`. Un index secondaire, `AlbumTitleIndex`, facilite les requêtes par titre d'album. 

Voici les étapes à suivre pour créer une table avec un index secondaire local à l'aide de l'API de bas niveau .NET. 

1. Créez une instance de la classe `AmazonDynamoDBClient`.

1. Créez une instance de la classe `CreateTableRequest` pour fournir l'information de requête. 

   Vous devez fournir le nom de la table, sa clé primaire et les valeurs de débit approvisionné. Pour l'index secondaire local, vous devez fournir le nom d'index, le nom et le type de données de la clé de tri d'index, le schéma de clé pour l'index et la projection d'attribut.

1. Exécutez la méthode `CreateTable` en fournissant l'objet de demande comme paramètre.

L’exemple de code C\$1 suivant illustre les étapes précédentes. Le code crée une table (`Music`) avec un index secondaire sur l'attribut `AlbumTitle`. Les clés de partition et de tri de table, ainsi que la clé de tri d'index, sont les seuls attributs projetés dans l'index.

```
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);
```

Vous devez attendre que DynamoDB crée la table et définisse l'état de celle-ci sur `ACTIVE`. Après cela, vous pouvez commencer à insérer des éléments de données dans la table.

## Décrire une table avec un index secondaire local
<a name="LSILowLevelDotNet.DescribeTableWithIndex"></a>

Pour obtenir des informations concernant les index secondaires locaux sur une table, utilisez l'API `DescribeTable`. Pour chaque index, vous pouvez accéder à son nom, à son schéma de clé et aux attributs projetés.

Voici les étapes à suivre pour accéder aux informations d'index secondaire local pour une table à l'aide de l'API de bas niveau .NET. 

1. Créez une instance de la classe `AmazonDynamoDBClient`.

1. Créez une instance de la classe `DescribeTableRequest` pour fournir l'information de requête. Vous devez fournir le nom de la table.

1. Exécutez la méthode `describeTable` en fournissant l'objet de demande comme paramètre.

L’exemple de code C\$1 suivant illustre les étapes précédentes.

**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);
        }

    }
}
```

## Interroger un index secondaire local
<a name="LSILowLevelDotNet.QueryAnIndex"></a>

Vous pouvez utiliser l'opération `Query` sur un index secondaire local de la même manière que vous utilisez l'opération `Query` sur une table. Vous devez spécifier le nom d'index, les critères de requête pour la clé de tri d'index et les attributs que vous souhaitez renvoyer. Dans cet exemple, l'index est `AlbumTitleIndex` et la clé de tri d'index est `AlbumTitle`. 

Les seuls attributs renvoyés sont ceux qui ont été projetés dans l'index. Vous pourriez également modifier cette requête pour sélectionner des attributs autres que de clé, mais cela nécessiterait une activité d'extraction de table relativement coûteuse. Pour plus d'informations sur les extractions de table, consultez [Projections d’attribut](LSI.md#LSI.Projections)

Voici les étapes à suivre pour interroger un index secondaire local à l'aide de l'API de bas niveau .NET. 

1. Créez une instance de la classe `AmazonDynamoDBClient`.

1. Créez une instance de la classe `QueryRequest` pour fournir l'information de requête.

1. Exécutez la méthode `query` en fournissant l'objet de demande comme paramètre.

L’exemple de code C\$1 suivant illustre les étapes précédentes.

**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();
}
```

# Exemple : index secondaires locaux utilisant l'API de AWS SDK pour .NET bas niveau
<a name="LSILowLevelDotNet.Example"></a>

L'exemple de code C\$1 suivant montre comment utiliser les index secondaires locaux dans Amazon DynamoDB. L'exemple crée une table nommée `CustomerOrders` avec une clé de partition `CustomerId` et une clé de tri `OrderId`. Il y a deux index secondaires locaux sur cette table :
+ `OrderCreationDateIndex` – La clé de tri est.`OrderCreationDate`, et les attributs suivants sont projetés dans l'index :
  + `ProductCategory`
  + `ProductName`
  + `OrderStatus`
  + `ShipmentTrackingId`
+ `IsOpenIndex` – La clé de tri est `IsOpen` et tous les attributs de table sont projetés dans l'index.

Une fois la table `CustomerOrders` créée, le programme charge la table avec des données représentant des commandes de clients. Il interroge ensuite les données à l'aide d'index secondaires locaux. Enfin, le programme supprime la table `CustomerOrders`.

Pour step-by-step obtenir des instructions sur le test de l'exemple suivant, reportez-vous à[Exemples de code .NET](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;
                }
            }
        }
    }
}
```

# Utilisation d’index secondaires locaux dans la AWS CLI de DynamoDB
<a name="LCICli"></a>

Vous pouvez utiliser AWS CLI pour créer une table Amazon DynamoDB avec un ou plusieurs index secondaires locaux, décrire les index sur la table, et effectuer des requêtes à l’aide des index.

**Topics**
+ [Créer une table avec un index secondaire local](#LCICli.CreateTableWithIndex)
+ [Décrire une table avec un index secondaire local](#LCICli.DescribeTableWithIndex)
+ [Interroger un index secondaire local](#LCICli.QueryAnIndex)

## Créer une table avec un index secondaire local
<a name="LCICli.CreateTableWithIndex"></a>

Vous devez créer des index secondaires locaux au moment où vous créez une table. Pour ce faire, utilisez le paramètre `create-table` et fournissez vos spécifications pour un ou plusieurs index secondaires locaux. L’exemple suivant crée une table (`Music`) destinée à accueillir des données informations sur des chansons dans une collection musicale. La clé de partition est `Artist`, et la clé de tri `SongTitle`. Un index secondaire, `AlbumTitleIndex`, sur l’attribut `AlbumTitle` facilite les requêtes par titre d’album. 

```
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\"]}}]"
```

Vous devez attendre que DynamoDB crée la table et définisse l’état de celle-ci sur `ACTIVE`. Après cela, vous pouvez commencer à insérer des éléments de données dans la table. Vous pouvez utiliser la commande [describe-table](https://docs.aws.amazon.com/cli/latest/reference/dynamodb/describe-table.html) pour déterminer l’état de la création de table. 

## Décrire une table avec un index secondaire local
<a name="LCICli.DescribeTableWithIndex"></a>

Pour obtenir des informations concernant les index secondaires locaux sur une table, utilisez le paramètre `describe-table`. Pour chaque index, vous pouvez accéder à son nom, à son schéma de clé et aux attributs projetés.

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

## Interroger un index secondaire local
<a name="LCICli.QueryAnIndex"></a>

Vous pouvez utiliser l’opération `query` sur un index secondaire local de la même manière que vous utilisez l’opération `query` sur une table. Vous devez spécifier le nom d’index, les critères de requête pour la clé de tri d’index et les attributs que vous souhaitez renvoyer. Dans cet exemple, l’index est `AlbumTitleIndex` et la clé de tri d’index est `AlbumTitle`. 

Les seuls attributs renvoyés sont ceux qui ont été projetés dans l’index. Vous pourriez également modifier cette requête pour sélectionner des attributs autres que de clé, mais cela nécessiterait une activité d’extraction de table relativement coûteuse. Pour plus d’informations sur les extractions de table, consultez [Projections d’attribut](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"} }'
```