

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.

# Utilisation de tables, d’éléments, de requêtes, d’analyses et d’index
<a name="WorkingWithDynamo"></a>

Cette section fournit des détails sur l’utilisation de tables, d’éléments, de requêtes et bien plus dans Amazon DynamoDB.

**Topics**
+ [Utilisation de tables et de données dans DynamoDB](WorkingWithTables.md)
+ [Tables globales : réplication multi-active, multirégion](GlobalTables.md)
+ [Utilisation d’éléments et d’attributs dans DynamoDB](WorkingWithItems.md)
+ [Amélioration de l’accès aux données avec les index secondaires dans DynamoDB](SecondaryIndexes.md)
+ [Gestion des flux complexes avec des transactions Amazon DynamoDB](transactions.md)
+ [Récupération de données de modification avec Amazon DynamoDB](streamsmain.md)

# Utilisation de tables et de données dans DynamoDB
<a name="WorkingWithTables"></a>

Cette section explique comment utiliser le AWS Command Line Interface (AWS CLI) et le AWS SDKs pour créer, mettre à jour et supprimer des tables dans Amazon DynamoDB.

**Note**  
Vous pouvez également effectuer ces tâches à l’aide de AWS Management Console. Pour de plus amples informations, veuillez consulter [Utilisation de la console](AccessingDynamoDB.md#ConsoleDynamoDB).

Cette section fournit également des informations supplémentaires sur la capacité de débit, l’utilisation de l’autoscaling de DynamoDB ou le paramétrage manuel du débit alloué.

**Topics**
+ [Opérations de base sur les tables DynamoDB](WorkingWithTables.Basics.md)
+ [Points à prendre en considération lors du choix d’une classe de tables dans DynamoDB](WorkingWithTables.tableclasses.md)
+ [Ajout de balises et d’étiquettes aux ressources dans DynamoDB](Tagging.md)

# Opérations de base sur les tables DynamoDB
<a name="WorkingWithTables.Basics"></a>

Comme d’autres systèmes de base de données, Amazon DynamoDB stocke les données dans des tables. Vous pouvez gérer vos tables à l’aide de quelques opérations de base.

**Topics**
+ [Création d’une table](#WorkingWithTables.Basics.CreateTable)
+ [Description d’une table](#WorkingWithTables.Basics.DescribeTable)
+ [Mise à jour d’une table](#WorkingWithTables.Basics.UpdateTable)
+ [Suppression d’une table](#WorkingWithTables.Basics.DeleteTable)
+ [Utilisation de la protection contre la suppression](#WorkingWithTables.Basics.DeletionProtection)
+ [Liste des noms de table](#WorkingWithTables.Basics.ListTables)
+ [Description des quotas de débit alloué](#WorkingWithTables.Basics.DescribeLimits)

## Création d’une table
<a name="WorkingWithTables.Basics.CreateTable"></a>

L’opération `CreateTable` vous permet de créer une table dans Amazon DynamoDB. Pour créer la table, vous devez fournir les informations suivantes :
+ **Nom de la table.** Le nom doit être conforme aux règles de dénomination DynamoDB et doit être unique pour le compte AWS actuel et la région. Par exemple, vous pouvez créer une table `People` dans la région USA Est (Virginie du Nord), et une autre table `People` en Europe (Irlande). Ces deux tables seraient toutefois entièrement différentes l’une de l’autre. Pour de plus amples informations, veuillez consulter [Types de données et règles de dénomination pris en charge dans Amazon DynamoDB](HowItWorks.NamingRulesDataTypes.md).
+ **Clé primaire.** La clé primaire peut se composer d’un attribut (clé de partition) ou de deux attributs (clé de partition et clé de tri). Vous devez indiquer les noms d’attribut, les types de données et le rôle de chaque attribut : `HASH` (pour une clé de partition) et `RANGE` (pour une clé de tri). Pour de plus amples informations, veuillez consulter [Clé primaire](HowItWorks.CoreComponents.md#HowItWorks.CoreComponents.PrimaryKey).
+ **Paramètres de débit (pour les tables allouées)** Si vous utilisez le mode alloué, vous devez spécifier les paramètres de débit initial de lecture et d’écriture pour la table. Vous pouvez modifier ces paramètres ultérieurement ou activer l’autoscaling de DynamoDB afin que les paramètres soient gérés pour vous. Pour en savoir plus, consultez [Mode de capacité provisionnée DynamoDB](provisioned-capacity-mode.md) et [Gestion automatique de la capacité de débit avec la scalabilité automatique de DynamoDB](AutoScaling.md).

### Exemple 1 : créer une table à la demande
<a name="create-payperrequest-example"></a>

Pour créer la même table `Music` en mode à la demande.

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

L’opération `CreateTable` renvoie des métadonnées pour la table, comme illustré ci-dessous.

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

**Important**  
 Lorsque vous appelez `DescribeTable` sur une table à la demande, les unités de capacité de lecture et d'écriture sont remises à 0. 

### Exemple 2 : créer une table allouée
<a name="create-provisioned-example"></a>

L' AWS CLI exemple suivant montre comment créer une table (`Music`). La clé primaire se compose de `Artist` (clé de partition) et de `SongTitle` (clé de tri), chacune d’elles ayant le type de données `String`. Le débit maximum pour cette table est de 10 unités de capacité de lecture et 5 unités de capacité d’écriture.

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

L’opération `CreateTable` renvoie des métadonnées pour la table, comme illustré ci-dessous.

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

L’élément `TableStatus` indique l’état réel de la table (`CREATING`). La création de la table peut prendre un certain temps, selon les valeurs que vous spécifiez pour `ReadCapacityUnits` et `WriteCapacityUnits`. Plus ces valeurs sont élevées, plus DynamoDB doit allouer des ressources à la table.

### Exemple 3 : créer une table à l’aide de la classe de tables DynamoDB Standard-Infrequent Access
<a name="create-infrequent-access-example"></a>

Pour créer la même table `Music` à l’aide de la classe de tables DynamoDB Standard-Infrequent Access.

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

L’opération `CreateTable` renvoie des métadonnées pour la table, comme illustré ci-dessous.

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

## Description d’une table
<a name="WorkingWithTables.Basics.DescribeTable"></a>

Affichez les détails d’une table à l’aide de l’opération `DescribeTable`. Vous devez fournir le nom de la table. La sortie de `DescribeTable` est au même format que celle de `CreateTable`. Elle inclut l’horodatage de la création de la table, son schéma de clé, ses paramètres de débit alloué, sa taille estimée et tout index secondaire présent.

**Important**  
 Lorsque vous appelez `DescribeTable` sur une table à la demande, les unités de capacité de lecture et d’écriture sont remises à 0. 

**Example**  

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

La table est prête à l’emploi lorsque `TableStatus` passe de `CREATING` à `ACTIVE`.

**Note**  
Si vous exécutez une demande `DescribeTable` immédiatement après une demande `CreateTable`, DynamoDB peut renvoyer une erreur (`ResourceNotFoundException`). En effet, `DescribeTable` utilise une demande à cohérence à terme et les métadonnées pour votre table peuvent ne pas être disponibles à ce moment-là. Attendez quelques secondes, puis réessayez d’envoyer la demande `DescribeTable`.  
À des fins de facturation, vos coûts de stockage DynamoDB incluent une surcharge par élément de 100 octets. (Pour en savoir plus, consultez [Tarification DynamoDB](https://aws.amazon.com/dynamodb/pricing/).) Ces 100 octets supplémentaires par élément ne sont pas utilisés dans les calculs d’unité de capacité ou par l’opération `DescribeTable`. 

## Mise à jour d’une table
<a name="WorkingWithTables.Basics.UpdateTable"></a>

L’opération `UpdateTable` vous permet d’exécuter l’une des actions suivantes :
+ Modifier les paramètres de débit alloué d’une table (pour les tables en mode alloué)
+ Modifiez le mode de read/write capacité de la table.
+ Manipuler des index secondaires globaux dans la table (voir [Utilisation d’index secondaires globaux dans DynamoDB](GSI.md))
+ Activer ou désactiver DynamoDB Streams sur la table (voir [Modifier la récupération de données pour DynamoDB Streams](Streams.md)).

**Example**  
L' AWS CLI exemple suivant montre comment modifier les paramètres de débit provisionné d'une table.  

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

**Note**  
Lorsque vous émettez une demande `UpdateTable`, le statut de la table passe de `AVAILABLE` à `UPDATING`. La table reste entièrement utilisable pendant sa `UPDATING`. Lorsque ce processus est terminé, le statut de la table passe de `UPDATING` à `AVAILABLE`.

**Example**  
L' AWS CLI exemple suivant montre comment modifier le mode de read/write capacité d'une table en mode à la demande.  

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

## Suppression d’une table
<a name="WorkingWithTables.Basics.DeleteTable"></a>

Vous pouvez supprimer une table non utilisée avec l’opération `DeleteTable`. Une fois supprimée, une table est irrécupérable. Pour supprimer une table à l’aide d’ AWS Management Console, consultez [Étape 6 : (Facultatif) supprimer votre table DynamoDB pour nettoyer les ressources](getting-started-step-6.md).

**Example**  
L' AWS CLI exemple suivant montre comment supprimer une table.  

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

Lorsque vous émettez une demande `DeleteTable`, le statut de la table passe de `ACTIVE` à `DELETING`. La suppression de la table peut prendre un certain temps, selon les ressources utilisées (par exemple les données stockées dans la table ou les flux ou index sur la table).

Une fois l’opération `DeleteTable` terminée, la table n’existe plus dans DynamoDB.

## Utilisation de la protection contre la suppression
<a name="WorkingWithTables.Basics.DeletionProtection"></a>

Vous pouvez protéger une table contre toute suppression accidentelle grâce à la propriété de protection contre la suppression. L’activation de cette propriété pour les tables permet de s’assurer que celles-ci ne seront pas supprimées accidentellement lors des opérations classiques de gestion des tables par vos administrateurs. Cela vous aidera à éviter toute interruption de vos activités métier normales.

 Le propriétaire de la table ou un administrateur autorisé contrôle la propriété de protection contre la suppression pour chaque table. La propriété de protection contre la suppression pour chaque table est désactivée par défaut. Cela inclut les répliques globales et les tables restaurées à partir de sauvegardes. Lorsque la protection contre la suppression est désactivée pour une table, celle-ci peut être supprimée par tous les utilisateurs autorisés par une stratégie Identity and Access Management (IAM). Lorsque la protection contre la suppression est activée pour une table, personne ne peut la supprimer. 

Pour modifier ce paramètre, accédez aux **Paramètres supplémentaires** de la table, puis au volet **Protection contre la suppression** et sélectionnez **Activer la protection contre la suppression**. 

La propriété de protection contre la suppression est prise en charge par la console DynamoDB, l’API, CLI/SDK et CloudFormation. L’API `CreateTable` prend en charge la propriété de protection contre la suppression lors de la création de la table, et l’API `UpdateTable` prend en charge la modification de la propriété de protection contre la suppression pour les tables existantes.

**Note**  
Si un AWS compte est supprimé, toutes les données de ce compte, y compris les tables, sont toujours supprimées dans les 90 jours.
Si DynamoDB perd l’accès à une clé gérée par le client ayant permis de chiffrer une table, il archive tout de même la table. L’archivage implique la création d’une sauvegarde de la table et la suppression de l’original.

## Liste des noms de table
<a name="WorkingWithTables.Basics.ListTables"></a>

L'`ListTables`opération renvoie les noms des tables DynamoDB pour le compte AWS courant et la région.

**Example**  
L' AWS CLI exemple suivant montre comment répertorier les noms des tables DynamoDB.  

```
aws dynamodb list-tables
```

## Description des quotas de débit alloué
<a name="WorkingWithTables.Basics.DescribeLimits"></a>

L'`DescribeLimits`opération renvoie les quotas de capacité de lecture et d'écriture actuels pour le AWS compte courant et la région.

**Example**  
L' AWS CLI exemple suivant montre comment décrire les quotas de débit actuellement provisionnés.  

```
aws dynamodb describe-limits
```
La sortie indique les quotas supérieurs d'unités de capacité de lecture et d'écriture pour le AWS compte courant et la région.

Pour en savoir plus sur ces quotas et la procédure à suivre pour demander une augmentation des quotas, consultez [Quotas de débit par défaut](ServiceQuotas.md#default-limits-throughput).

# Points à prendre en considération lors du choix d’une classe de tables dans DynamoDB
<a name="WorkingWithTables.tableclasses"></a>

DynamoDB propose deux classes de tables conçues pour vous aider à optimiser vos coûts. La classe de tables DynamoDB Standard est la classe par défaut. Elle est recommandée pour la grande majorité des charges de travail. La classe de tables DynamoDB Standard-Infrequent Access (DynamoDB Standard-IA) est optimisée pour les tables où le stockage est le coût dominant. Par exemple, les tables qui stockent des données rarement consultées, comme les journaux d’applications, les anciennes publications sur les réseaux sociaux, l’historique des commandes d’e-commerce et les exploits de jeux passés, sont de bons candidats pour la classe de tables Standard-IA.

Chaque table DynamoDB est associée à une classe de tables. Tous les index secondaires associés à la table utilisent la même classe de table. Vous pouvez définir votre classe de table lors de la création de votre table (DynamoDB Standard par défaut) et mettre à jour la classe de table d'une table existante à l'aide de la AWS Management Console AWS CLI ou du SDK. AWS DynamoDB prend également en charge la gestion de votre classe de table à AWS CloudFormation l'aide de tables à région unique (tables qui ne sont pas des tables globales). Chaque classe de tables offre une tarification différente pour le stockage de données, ainsi que pour les demandes de lecture et d’écriture. Lorsque vous choisissez une classe de tables pour votre table, gardez à l’esprit les points suivants :
+ La classe de tables DynamoDB Standard offre des coûts de débit inférieurs à ceux de DynamoDB Standard-IA et constitue l’option la plus économique pour les tables dont le débit est le coût dominant. 
+ La classe de tables DynamoDB Standard-IA offre des coûts de stockage inférieurs à ceux de DynamoDB Standard et constitue l’option la plus économique pour les tables dont le stockage est le coût dominant. Lorsque le stockage dépasse 50 % du coût de débit (lectures et écritures) d’une table utilisant la classe de tables DynamoDB Standard, la classe de tables DynamoDB Standard-IA peut vous aider à réduire le coût total de votre table. 
+ Les tables DynamoDB Standard-IA offrent les mêmes performances, durabilité et disponibilité que les tables DynamoDB Standard. 
+ Basculer entre les classes de tables DynamoDB Standard et DynamoDB Standard-IA ne nécessite pas de modification du code de votre application. Vous utilisez les mêmes points de terminaison APIs DynamoDB et de service, quelle que soit la classe de table utilisée par vos tables. 
+ Les tables DynamoDB Standard-IA sont compatibles avec toutes les fonctionnalités DynamoDB existantes, telles que le dimensionnement automatique, le time-to-live mode à la demande (TTL), les point-in-time sauvegardes à la demande, la restauration (PITR) et les index secondaires globaux.

La classe de tables la plus économique pour votre table dépend des modèles de stockage et d’utilisation du débit attendus de votre table. Vous pouvez consulter l'historique des coûts et de l'utilisation du stockage et du débit de votre table à l'aide des rapports sur les AWS coûts et d'utilisation et du AWS Cost Explorer. Ces données historiques vous permettent de déterminer la classe de tables la plus économique pour votre table. Pour en savoir plus sur l'utilisation de AWS Cost and Usage Reports et du AWS Cost Explorer, consultez la [documentation AWS Billing and Cost Management](https://docs.aws.amazon.com/account-billing/index.html). Pour en savoir plus sur la tarification des classes de tables, consultez [Tarification Amazon DynamoDB](https://aws.amazon.com/dynamodb/pricing/on-demand/).

**Note**  
Une mise à jour de classe de tables est un processus d’arrière-plan. Lors de la mise à jour d’une classe de tables, vous pouvez toujours accéder normalement à votre table. La durée de mise à jour de votre classe de tables dépend du trafic de votre table, de la taille de stockage et d’autres variables associées. Sur une période de 30 jours, jusqu’à deux mises à jour de classe de tables sont autorisées sur votre table.

# Ajout de balises et d’étiquettes aux ressources dans DynamoDB
<a name="Tagging"></a>

Vous pouvez libeller des ressources Amazon DynamoDB à l’aide d’*étiquettes*. Les balises vous permettent de classer vos ressources de différentes manières, par exemple, par objectif, par propriétaire, par environnement ou selon d’autres critères. Les balises vous permettent d’effectuer les actions suivantes :
+ Identifier rapidement une ressource en fonction des balises que vous lui avez attribuées.
+ Voir AWS les factures ventilées par tags.
**Note**  
Les index secondaires locaux (LSI) et les index secondaires globaux (GSI) associés aux tables balisées sont étiquetés avec les mêmes balises automatiquement. Actuellement, l’utilisation DynamoDB Streams ne peut pas être étiquetée.

Le balisage est pris en charge par AWS des services tels qu'Amazon EC2, Amazon S3, DynamoDB, etc. Un balisage efficace peut fournir un aperçu sur les coûts en vous permettant de créer des rapports sur les services associés à une balise spécifique.

Pour commencer le balisage, procédez comme suit :

1. Comprendre [Restrictions d’étiquetage dans DynamoDB](#TaggingRestrictions).

1. Créer des balises en utilisant [Étiquetage de ressources dans DynamoDB](Tagging.Operations.md).

1. [Utilisation des balises DynamoDB pour créer des rapports de répartition des coûts](#CostAllocationReports)À utiliser pour suivre vos AWS coûts par tag actif.

En dernier lieu, il est conseillé de suivre les politique de balisage optimales. Pour plus d’informations, consultez [Politiques d’étiquetage AWS](https://d0.awsstatic.com/aws-answers/AWS_Tagging_Strategies.pdf).

## Restrictions d’étiquetage dans DynamoDB
<a name="TaggingRestrictions"></a>

 Chaque étiquette est constituée d’une clé et d’une valeur, que vous définissez. Les restrictions suivantes s’appliquent : 
+  Chaque table DynamoDB ne peut avoir qu’une seule étiquette avec la même clé. Si vous tentez d’ajouter une balise existante (même clé), la valeur de la balise existante est mise à jour avec la nouvelle valeur. 
+  Les clés et les valeurs des balises distinguent les majuscules et minuscules. 
+  La longueur de clé maximale est de 128 caractères Unicode. 
+ La longueur de valeur maximale est de 256 caractères Unicode. 
+  Les caractères autorisés sont les lettres, les espaces blancs et les chiffres, ainsi que les caractères spéciaux suivants : `+ - = . _ : /` 
+  Le nombre maximum d’identifications par ressource est de 50.
+ La taille maximale prise en charge pour toutes les balises d’une table est de 10 Ko.
+ AWS-les noms et valeurs des balises assignés reçoivent automatiquement le `aws:` préfixe, que vous ne pouvez pas attribuer. AWS-les noms de balises attribués ne sont pas pris en compte dans la limite de 50 balises ni dans la limite de taille maximale de 10 Ko. Les noms des balises attribuées par l’utilisateur ont le préfixe `user:` dans le rapport de répartition des coûts. 
+  Vous ne pouvez pas antidater l’application d’une balise. 

# Étiquetage de ressources dans DynamoDB
<a name="Tagging.Operations"></a>

Vous pouvez utiliser la console Amazon DynamoDB ou AWS Command Line Interface le AWS CLI() pour ajouter, répertorier, modifier ou supprimer des balises. Vous pouvez ensuite activer ces balises définies par l’utilisateur afin de les faire apparaître sur la console AWS Billing and Cost Management pour le suivi de la répartition des coûts. Pour de plus amples informations, veuillez consulter [Utilisation des balises DynamoDB pour créer des rapports de répartition des coûts](Tagging.md#CostAllocationReports). 

 Pour la modification en bloc, vous pouvez également utiliser l’éditeur d’étiquettes sur l’ AWS Management Console. Pour plus d’informations, consultez [Utilisation de Tag Editor](https://docs.aws.amazon.com/awsconsolehelpdocs/latest/gsg/tag-editor.html).

 Pour utiliser l’API DynamoDB à la place, découvrez les opérations suivantes dans la [Référence d’API Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/) :
+ [TagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TagResource.html)
+ [UntagResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UntagResource.html)
+ [ListTagsOfResource](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListTagsOfResource.html)

**Topics**
+ [Définition d’autorisations pour filtrer par étiquettes](#Tagging.Operations.permissions)
+ [Ajout d’étiquettes à des tables nouvelles ou existantes (AWS Management Console)](#Tagging.Operations.using-console)
+ [Ajout d'étiquettes à des tables nouvelles ou existantes (AWS CLI)](#Tagging.Operations.using-cli)

## Définition d’autorisations pour filtrer par étiquettes
<a name="Tagging.Operations.permissions"></a>

Pour utiliser des étiquettes afin de filtrer votre liste de tables dans la console DynamoDB, assurez-vous que les politiques de votre utilisateur incluent l’accès aux opérations suivantes :
+ `tag:GetTagKeys`
+ `tag:GetTagValues`

Pour accéder à ces opérations en attachant une nouvelle politique IAM à votre utilisateur, suivez les étapes ci-dessous.

1. Accédez à la [console IAM](https://console.aws.amazon.com/iam/) avec un utilisateur administrateur.

1. Dans le menu de navigation à gauche, sélectionnez « Policies (politiques) ».

1. Sélectionnez « Create Policy (Créer une politique) ».

1. Collez le politique suivante dans l’éditeur JSON.

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

****  

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

------

1. Suivez la procédure de l’Assistant et attribuez un nom à la politique (par exemple, `TagKeysAndValuesReadAccess`).

1. Dans le menu de navigation de gauche, sélectionnez « Users (Utilisateurs) ».

1. Dans la liste, sélectionnez l’utilisateur que vous utilisez normalement pour accéder à la console DynamoDB.

1. Sélectionnez « Add permissions (Ajouter des autorisations) ».

1. Sélectionnez « Attach existing policies directly (Attacher directement des politiques existantes) ».

1. Dans la liste, sélectionnez la politique que vous avez créée précédemment.

1. Exécutez l’assistant.

## Ajout d’étiquettes à des tables nouvelles ou existantes (AWS Management Console)
<a name="Tagging.Operations.using-console"></a>

Vous pouvez utiliser la console DynamoDB pour ajouter des étiquettes à de nouvelles tables lors de leur création, ou ajouter, modifier ou supprimer des étiquettes pour des tables existantes.

**Pour baliser des ressources lors de leur création (console)**

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le panneau de navigation, choisissez **Tables**, puis **Create table (Créer une table)**.

1. Sur la page **Create DynamoDB table (Créer une table DynamoDB)**, fournissez un nom et une clé primaire. Dans **Identifications**, choisissez **Ajouter une nouvelle identification** et saisissez les identifications que vous souhaitez utiliser.

   Pour plus d’informations sur la structure des balises, consultez [Restrictions d’étiquetage dans DynamoDB](Tagging.md#TaggingRestrictions). 

   Pour plus d’informations sur la création de tables, consultez [Opérations de base sur les tables DynamoDB](WorkingWithTables.Basics.md).

**Pour baliser des ressources existantes (console)**

Ouvrez la console DynamoDB à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le volet de navigation, choisissez **Tables**.

1. Choisissez une table dans la liste, puis choisissez l’onglet **Paramètres supplémentaires**. Vous pouvez ajouter, modifier ou supprimer vos identifications dans la section **Identifications** en bas de la page.

## Ajout d'étiquettes à des tables nouvelles ou existantes (AWS CLI)
<a name="Tagging.Operations.using-cli"></a>

Les exemples suivants montrent comment utiliser le AWS CLI pour spécifier des balises lorsque vous créez des tables et des index, et pour étiqueter des ressources existantes.

**Pour baliser des ressources lors de leur création (AWS CLI)**
+ L’exemple suivant crée une nouvelle table `Movies` et ajoute la balise `Owner` avec la valeur `blueTeam` : 

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

**Pour baliser des ressources existantes (AWS CLI)**
+ L’exemple suivant ajoute la table `Owner` avec la valeur `blueTeam` pour la table `Movies` : 

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

**Pour répertorier toutes les balises pour une table (AWS CLI)**
+ L’exemple suivant répertorie toutes les balises associées à la table `Movies` :

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

## Utilisation des balises DynamoDB pour créer des rapports de répartition des coûts
<a name="CostAllocationReports"></a>

AWS utilise des balises pour organiser les coûts des ressources dans votre rapport de répartition des coûts. AWS fournit deux types de balises de répartition des coûts :
+ Une balise AWS générée. AWS définit, crée et applique cette balise pour vous.
+ Etiquettes définies par l’utilisateur Vous définissez, créez et appliquez ces étiquettes.

Vous devez activer les deux types d’étiquettes séparément pour qu’elles apparaissent dans Cost Explorer ou sur un rapport de répartition des coûts. 

 Pour activer les balises AWS générées : 

1.  Connectez-vous à la console Billing AWS Management Console and Cost Management et ouvrez-la à l'adresse [https://console.aws.amazon.com/billing/home\$1/](https://console.aws.amazon.com/billing/home#/.). 

1.  Dans le volet de navigation, choisissez **Balises de répartition des coûts**. 

1.  Sous **Identifications de répartition des coûts générées par AWS**, choisissez **Activer**. 

 Pour activer les étiquettes définies par l’utilisateur : 

1.  Connectez-vous à la console Billing AWS Management Console and Cost Management et ouvrez-la à l'adresse [https://console.aws.amazon.com/billing/home\$1/](https://console.aws.amazon.com/billing/home#/.). 

1.  Dans le volet de navigation, choisissez **Balises de répartition des coûts**. 

1.  Sous **User-Defines Cost Allocation Tags (Etiquettes de répartition des coûts définies par l’utilisateur)**, choisissez **Activer**. 

 Après avoir créé et activé les balises, AWS génère un rapport de répartition des coûts avec votre utilisation et vos coûts regroupés en fonction de vos balises actives. Le rapport de répartition des coûts inclut tous vos AWS coûts pour chaque période de facturation. Ce rapport inclut les ressources balisées et non balisées, afin que vous puissiez organiser clairement les frais pour les ressources. 

**Note**  
 Actuellement, les données transférées à partir de DynamoDB ne sont pas réparties par étiquettes sur les rapports de répartition des coûts. 

 Pour plus d’informations, consultez [Utilisation des étiquettes d’allocation des coûts](https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/cost-alloc-tags.html). 

# Tables globales : réplication multi-active, multirégion
<a name="GlobalTables"></a>

Les *tables globales d’Amazon DynamoDB* sont une fonctionnalité de base de données entièrement gérée, à plusieurs régions et à multiples activités, qui permet une réplication facile des données et offre des performances de lecture et d’écriture élevées pour les applications mises à l’échelle de manière globale.

Les tables globales répliquent automatiquement les données de vos tables DynamoDB entre les comptes et éventuellement Régions AWS AWS entre eux sans que vous ayez à créer et à gérer votre propre solution de réplication. Les tables globales sont idéales pour les applications nécessitant une continuité des activités et une haute disponibilité grâce à un déploiement multirégional. Tout réplica de table globale peut être utilisé en lecture et en écriture. Les applications peuvent atteindre une résilience élevée avec un objectif de point de reprise (RPO) faible ou nul en transférant le trafic vers une autre région si le traitement des demandes est interrompu dans une région. Les tables globales sont disponibles dans toutes les régions où DynamoDB est disponible.

## Modes de cohérence
<a name="GlobalTables.consistency-modes"></a>

Lorsque vous créez une table globale, vous pouvez configurer son mode de cohérence. Les tableaux globaux prennent en charge deux modes de cohérence : cohérence finale multirégionale (MREC) et cohérence forte multirégionale (MRSC).

Si vous ne spécifiez pas de mode de cohérence lors de la création d’une table globale, la table globale est définie par défaut sur la cohérence à terme multirégionale (MREC). Une table globale ne peut pas contenir de réplicas configurés avec différents modes de cohérence. Vous ne pouvez pas modifier le mode de cohérence d’une table globale après sa création.

## Configurations de compte
<a name="GlobalTables.account-configurations"></a>

DynamoDB prend désormais en charge deux modèles de tables globales, chacun étant conçu pour différents modèles architecturaux :
+ **Tables globales pour le même compte** : toutes les répliques sont créées et gérées au sein d'un seul compte. AWS 
+ **Tables globales multicomptes : les** répliques sont déployées sur plusieurs AWS comptes tout en participant à un groupe de réplication partagé.

Les modèles à comptes identiques et à comptes multiples prennent en charge les écritures multirégionales, la réplication asynchrone, la résolution des last-writer-wins conflits et le même modèle de facturation. Cependant, ils diffèrent dans la manière dont les comptes, les autorisations, le chiffrement et la gouvernance des tables sont gérés de différentes manières.

Les tables globales configurées pour MRSC ne prennent en charge que les configurations de même compte.

Vous pouvez configurer une table globale à l'aide de la console AWS de gestion. Les tables globales utilisent DynamoDB APIs existant pour lire et écrire des données dans vos tables. Aucune modification de l'application n'est donc requise. Vous payez uniquement les ressources provisionnées sans frais à l’avance ni engagement.


| **Propriétés** | **Tableaux globaux pour le même compte** | **Tableaux globaux multi-comptes** | 
| --- | --- | --- | 
| Cas d'utilisation principal | Résilience multirégionale pour les applications au sein d'un seul compte AWS  | Réplication multirégionale et multicompte pour les applications appartenant à différentes équipes, à des unités commerciales distinctes ou à des limites de sécurité strictes entre les comptes | 
| Modèle de compte | Toutes les répliques créées et gérées dans un seul compte AWS  | Répliques créées sur plusieurs AWS comptes dans le cadre d'un même déploiement | 
| Propriété des ressources | Un seul compte possède la table et toutes les répliques | Chaque compte possède sa réplique locale ; le groupe de réplication couvre plusieurs comptes | 
| Version prise en charge | Tables globales version 2019.11.21 (actuelle) et version 2017.11.29 (ancienne version) | Tables globales version 2019.11.21 (actuelle) | 
| Opérations du plan de contrôle | Créez, modifiez et supprimez des répliques via le compte du propriétaire de la table | Opérations du plan de contrôle distribué : les comptes rejoignent ou quittent le groupe de réplication | 
| Opérations du plan de données | Points de terminaison DynamoDB standard par région | Accès au plan de données par compte/région ; routage via un groupe de réplication | 
| Limite de sécurité | Une seule limite IAM et KMS | IAM, KMS CloudTrail, facturation et gouvernance distincts par compte | 
| Ajustement optimal | Organisations dont la propriété des tables est centralisée | Organisations dotées d'équipes fédérées, de limites de gouvernance ou de configurations multi-comptes | 

**Topics**
+ [Modes de cohérence](#GlobalTables.consistency-modes)
+ [Configurations de compte](#GlobalTables.account-configurations)
+ [Concepts fondamentaux des tables globales](globaltables-CoreConcepts.md)
+ [Table globale DynamoDB pour le même compte](globaltables-SameAccount.md)
+ [Tableaux globaux multicomptes DynamoDB](globaltables-MultiAccount.md)
+ [Présentation de la facturation Amazon DynamoDB pour les tables globales](global-tables-billing.md)
+ [Versions des tables globales DynamoDB](V2globaltables_versions.md)
+ [Bonnes pratiques relatives aux tables globales](globaltables-bestpractices.md)

# Concepts fondamentaux des tables globales
<a name="globaltables-CoreConcepts"></a>

Les sections suivantes décrivent les concepts et les comportements des tables globales dans Amazon DynamoDB

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

*Les tables globales* sont une fonctionnalité de DynamoDB qui réplique les données des tables entre les régions. AWS 

Une *table de réplica* (ou réplica) est une table DynamoDB unique qui fonctionne comme une partie d’une table globale. Une table globale se compose d'au moins deux répliques de tables réparties dans différentes AWS régions. Une table globale donnée ne peut avoir qu’une seule table de réplica par région AWS . Toutes les répliques d’une table globale partagent le même nom de table, le même schéma de clé primaire et les mêmes données d’élément.

Quand une application écrit des données dans une réplique d’une région, DynamoDB réplique automatiquement l’écriture aux autres réplicas dans la table globale. Pour plus d'informations sur la façon de démarrer avec les tables globales, consultez [Tutoriels : Création de tables globales](V2globaltables.tutorial.md) ou[Tutoriels : Création de tables globales multi-comptes](V2globaltables_MA.tutorial.md).

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

Deux versions des tables globales DynamoDB sont disponibles : [Tables globales version 2019.11.21 (actuelle)](GlobalTables.md) et [Tables globales de la version 2017.11.29 (héritée)](globaltables.V1.md). Vous devez utiliser la version 2019.11.21 (Current) de Global Tables dans la mesure du possible. Les informations contenues dans cette section de documentation concernent la version 2019.11.21 (actuelle). Pour plus d'informations, consultez la section Détermination de la version d'une table globale[Détermination de la version d’une table globale](V2globaltables_versions.md#globaltables.DetermineVersion).

## Disponibilité
<a name="globaltables-CoreConcepts.availability"></a>

Les tables globales contribuent à améliorer la continuité de votre activité en facilitant la mise en œuvre d’une architecture de haute disponibilité multirégionale. Si la charge de travail d'une seule AWS région est altérée, vous pouvez déplacer le trafic de l'application vers une autre région et effectuer des lectures et des écritures dans une autre table de réplication de la même table globale.

Chaque table de réplica d’une table globale offre la même durabilité et la même disponibilité qu’une table DynamoDB à région unique. Les tables globales offrent un [contrat de niveau de service (SLA)](https://aws.amazon.com//dynamodb/sla/) avec une disponibilité de 99,999 %, contre 99,99 % pour les tables à région unique.

## Test d’injection de pannes
<a name="fault-injection-testing"></a>

Les tables globales MREC et MRSC s'intègrent au [AWS Fault Injection Service](https://docs.aws.amazon.com/resilience-hub/latest/userguide/testing.html) (AWS FIS), un service entièrement géré permettant d'exécuter des expériences d'injection de défauts contrôlées afin d'améliorer la résilience d'une application. À l'aide du AWS FIS, vous pouvez :
+ Créez des modèles d'expérimentation qui définissent des scénarios de défaillance spécifiques.
+ Injectez les échecs pour valider la résilience des applications en simulant l'isolation des régions (c'est-à-dire en interrompant la réplication vers et depuis une réplique sélectionnée) afin de tester la gestion des erreurs, les mécanismes de restauration et le comportement de transfert du trafic multirégional lorsqu'une AWS région est perturbée.

Par exemple, dans un tableau global contenant des répliques dans l'est des États-Unis (Virginie du Nord), dans l'est des États-Unis (Ohio) et dans l'ouest des États-Unis (Oregon), vous pouvez effectuer une expérience dans l'est des États-Unis (Ohio) pour tester l'isolement de la région dans cette région tandis que l'est des États-Unis (Virginie du Nord) et l'ouest des États-Unis (Oregon) poursuivent leurs activités normales. Ces tests contrôlés vous aident à identifier et à résoudre les problèmes potentiels avant qu’ils n’affectent les charges de travail de production. 

Consultez les [cibles d'action](https://docs.aws.amazon.com/fis/latest/userguide/action-sequence.html#action-targets) dans le *guide de l'utilisateur du AWS FIS* pour obtenir la liste complète des actions prises en charge par le AWS FIS et la [section Connectivité entre régions](https://docs.aws.amazon.com/fis/latest/userguide/cross-region-scenario.html) pour suspendre la réplication DynamoDB entre les régions.

*Pour plus d'informations sur les actions de table globales Amazon DynamoDB disponibles AWS dans FIS, [consultez la référence des actions de tables globales DynamoDB dans le guide de l'utilisateur du FIS](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#dynamodb-actions-reference).AWS *

Pour commencer à exécuter des expériences d'injection de défauts, consultez [la section Planification de vos expériences AWS FIS](https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html) dans le guide de l'utilisateur du AWS FIS.

**Note**  
Au cours AWS FIS des expériences menées dans le MRSC, des lectures cohérentes sont finalement autorisées, mais les mises à jour des paramètres des tables, telles que le changement du mode de facturation ou la configuration du débit des tables, ne sont pas autorisées, comme dans le cas du MREC. Veuillez consulter la CloudWatch métrique [`FaultInjectionServiceInducedErrors`](metrics-dimensions.md#FaultInjectionServiceInducedErrors)pour plus de détails concernant le code d'erreur.

## Durée de vie (TTL)
<a name="global-tables-ttl"></a>

Les tables globales configurées pour le MREC prennent en charge la configuration de la suppression [Time To Live](TTL.md) (TTL). Les paramètres TTL sont automatiquement synchronisés pour tous les réplicas d’une table globale. Lorsque la TTL supprime un élément d’un réplica dans une région, la suppression est répliquée sur tous les autres réplicas de la table globale. La TTL n’utilise pas de capacité d’écriture. La suppression TTL ne vous est donc pas facturée dans la région où la suppression a eu lieu. Toutefois, vous êtes facturé pour la suppression répliquée dans chaque autre région avec un réplica dans la table globale.

La réplication de suppression TTL utilise de la capacité d’écriture sur les réplicas dans lesquels la suppression est répliquée. Les réplicas configurés pour la capacité allouée peuvent limiter les demandes si la combinaison du débit d’écriture et du débit de suppression TTL est supérieure à la capacité d’écriture allouée.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne prennent pas en charge la configuration de la suppression Time To Live (TTL).

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

Les tables globales configurées pour une cohérence à terme entre plusieurs régions (MREC) répliquent les modifications en lisant ces modifications à partir de [flux DynamoDB](Streams.md) sur une table de réplica et en appliquant cette modification à toutes les autres tables de réplica. Les flux sont donc activés par défaut sur tous les réplicas d’une table globale MREC et ne peuvent pas être désactivé sur ces réplicas. Le processus de réplication MREC peut combiner plusieurs modifications sur une courte période en une seule écriture répliquée, ce qui fait que le flux de chaque réplica contient des enregistrements légèrement différents. Les enregistrements Streams sur les répliques MREC maintiennent l'ordre pour toutes les modifications apportées au même article, mais l'ordre relatif des modifications apportées aux différents articles peut varier d'une réplique à l'autre.

Si vous souhaitez écrire une application qui traite les enregistrements de flux pour les modifications survenues dans une région particulière mais pas dans d’autres régions d’une table globale, vous pouvez ajouter un attribut à chaque élément qui définit dans quelle région le changement pour cet élément s’est produit. Vous pouvez utiliser cet attribut pour filtrer les enregistrements de flux en fonction des modifications survenues dans d’autres régions, notamment en utilisant des filtres d’événements Lambda pour n’appeler les fonctions Lambda que pour les modifications dans une région spécifique.

Les tables globales configurées pour une forte cohérence multirégionale (tables MRSC) n’utilisent pas les flux DynamoDB pour la réplication. Cette fonctionnalité n’est donc pas activée par défaut sur les réplicas MRSC. Vous pouvez activer les flux sur un réplica MRSC. Les enregistrements de flux sur les répliques MRSC sont identiques pour chaque réplica, y compris l’ordre des enregistrements de flux.

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

Sur une table globale configurée pour MREC, les opérations de transaction DynamoDB ( [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) et [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)) ne sont atomiques que dans la région où l’opération a été invoquée. Les écritures transactionnelles ne sont pas répliquées en tant qu’unité entre les régions, ce qui signifie que seules certaines des écritures d’une transaction peuvent être renvoyées par des opérations de lecture dans d’autres réplicas à un instant dans le passé donné.

Par exemple, si vous avez une table globale avec des réplicas dans les régions USA Est (Ohio) et USA Ouest (Oregon), et que vous réalisez une opération `TransactWriteItems` dans la région USA Est (Ohio), vous remarquerez peut-être des transactions partiellement incomplètes dans la région USA Ouest (Oregon) lorsque les changements sont répliqués. Les changements seront uniquement répliqués aux autres régions une fois validés dans la région source.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne prennent pas en charge les opérations de transaction et renvoient une erreur si ces opérations sont invoquées sur une réplique MRSC.

## Débit de lecture et d’écriture
<a name="globaltables-CoreConcepts.Throughput"></a>

### Mode alloué
<a name="gt_throughput.provisioned"></a>

La réplication consomme de la capacité d’écriture. Les répliques configurées pour la capacité allouée peuvent limiter les demandes si la combinaison du débit d'écriture de l'application et du débit d'écriture de réplication dépasse la capacité d'écriture allouée. Pour les tables globales utilisant le mode provisionné, les paramètres de dimensionnement automatique pour les capacités de lecture et d'écriture sont synchronisés entre les répliques.

Vous pouvez configurer indépendamment les paramètres de capacité de lecture pour chaque réplique dans une table globale en utilisant le [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html)paramètre au niveau de la réplique. Par défaut, les modifications apportées à la capacité de lecture allouée sont appliquées à toutes les répliques de la table globale. Lors de l'ajout d'une nouvelle réplique à une table globale, la capacité de lecture de la table source ou de la réplique est utilisée comme valeur initiale, sauf si une dérogation au niveau de la réplique est explicitement spécifiée.

### Mode de capacité à la demande
<a name="gt_throughput.on-demand"></a>

Pour les tables globales configurées en mode à la demande, la capacité d'écriture est automatiquement synchronisée entre toutes les répliques. DynamoDB ajuste automatiquement la capacité en fonction du trafic, et il n'existe aucun paramètre de capacité de lecture ou d'écriture spécifique à la réplique à gérer.

## Surveillance des tables globales
<a name="monitoring-global-tables"></a>

Les tables globales configurées pour la cohérence finale multirégionale (MREC) publient la [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency)métrique dans. CloudWatch Cette métrique suit le temps écoulé entre le moment où un élément est écrit dans une table de réplicas et celui où il apparaît dans un autre réplica dans la table globale. `ReplicationLatency` est exprimé en millisecondes et est émis pour chaque paire région source/région de destination dans une table globale. 

Les `ReplicationLatency` valeurs typiques dépendent de la distance entre les AWS régions que vous avez choisies, ainsi que d'autres variables telles que le type de charge de travail et le débit. Par exemple, un réplica source située dans la région USA Ouest (Californie du Nord) (us-west-1) a une `ReplicationLatency` inférieure dans la région USA Ouest (Oregon) (us-west-2) par rapport à la région Afrique (Le Cap) (af-south-1).

Une valeur croissante pour `ReplicationLatency` peut indiquer que les mises à jour d’un réplica ne sont pas propagées vers d’autres tables de réplica dans un délai raisonnable. Dans ce cas, vous pouvez rediriger temporairement les activités de lecture et d'écriture de votre application vers une autre AWS région.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne publient aucune métrique `ReplicationLatency`.

## Considérations relatives à la gestion des tables globales
<a name="management-considerations"></a>

Vous ne pouvez pas supprimer une table utilisée pour ajouter un nouveau réplica de table globale avant que 24 heures ne se soient écoulées depuis la création du nouveau réplica.

Si vous désactivez une AWS région contenant des répliques de tables globales, ces répliques sont définitivement converties en tables à région unique 20 heures après la désactivation de la région.

# Table globale DynamoDB pour le même compte
<a name="globaltables-SameAccount"></a>

Les tables globales de même compte répliquent automatiquement les données de vos tables DynamoDB entre les régions au sein d'un même compte. AWS AWS Les tables globales de même compte constituent le modèle le plus simple pour exécuter des applications multirégionales, car toutes les répliques partagent les mêmes limites de compte, de propriété et le même modèle d'autorisations. Lorsque vous choisissez les AWS régions pour vos tables de réplication, les tables globales gèrent automatiquement toutes les réplications. Les tables globales sont disponibles dans toutes les régions où DynamoDB est disponible.

Les tables globales pour le même compte offrent les avantages suivants :
+ Répliquez automatiquement les données des tables DynamoDB dans les régions de votre choix pour localiser les données au plus près AWS de vos utilisateurs
+ Améliorez la disponibilité des applications en cas d’isolation ou de dégradation au niveau régional
+ Utilisez la résolution de conflits intégrée pour vous concentrer sur la logique métier de votre application
+ Lorsque vous créez une table globale pour un même compte, vous pouvez choisir soit [Cohérence à terme multirégionale (MREC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrec) [Forte cohérence multirégionale (MRSC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrsc)

**Topics**
+ [Fonctionnement des tables globales DynamoDB](V2globaltables_HowItWorks.md)
+ [Tutoriels : Création de tables globales](V2globaltables.tutorial.md)
+ [Sécurité des tables globales DynamoDB](globaltables-security.md)

# Fonctionnement des tables globales DynamoDB
<a name="V2globaltables_HowItWorks"></a>

Les sections suivantes décrivent les concepts et les comportements des tables globales dans Amazon DynamoDB.

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

*Les tables globales* sont une fonctionnalité de DynamoDB qui réplique les données des tables entre les régions. AWS 

Une *table de réplica* (ou réplica) est une table DynamoDB unique qui fonctionne comme une partie d’une table globale. Une table globale se compose d'au moins deux répliques de tables réparties dans différentes AWS régions. Une table globale donnée ne peut avoir qu’une seule table de réplica par région AWS . Toutes les répliques d’une table globale partagent le même nom de table, le même schéma de clé primaire et les mêmes données d’élément.

Quand une application écrit des données dans une réplique d’une région, DynamoDB réplique automatiquement l’écriture aux autres réplicas dans la table globale. Pour en savoir plus sur la mise en route avec des tables globales, consultez [Tutoriels : Création de tables globales](V2globaltables.tutorial.md).

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

Deux versions des tables globales DynamoDB sont disponibles : la version 2019.11.21 (actuelle) et la [version 2017.11.29 (héritée)](globaltables.V1.md). Vous devez utiliser la version 2019.11.21 (actuelle) dans la mesure du possible. Les informations contenues dans cette section de documentation concernent la version 2019.11.21 (actuelle). Pour de plus amples informations, veuillez consulter [Détermination de la version d’une table globale](V2globaltables_versions.md#globaltables.DetermineVersion).

## Disponibilité
<a name="V2globaltables_HowItWorks.availability"></a>

Les tables globales contribuent à améliorer la continuité de votre activité en facilitant la mise en œuvre d’une architecture de haute disponibilité multirégionale. Si la charge de travail d'une seule AWS région est altérée, vous pouvez déplacer le trafic de l'application vers une autre région et effectuer des lectures et des écritures dans une autre table de réplication de la même table globale.

Chaque table de réplica d’une table globale offre la même durabilité et la même disponibilité qu’une table DynamoDB à région unique. Les tables globales offrent un [contrat de niveau de service (SLA)](https://aws.amazon.com//dynamodb/sla/) avec une disponibilité de 99,999 %, contre 99,99 % pour les tables à région unique.

## Modes de cohérence
<a name="V2globaltables_HowItWorks.consistency-modes"></a>

Lorsque vous créez une table globale, vous pouvez configurer son mode de cohérence. Les tables globales prennent en charge deux modes de cohérence : la cohérence à terme multirégionale (MREC) et la forte cohérence multirégionale (MRSC).

Si vous ne spécifiez pas de mode de cohérence lors de la création d’une table globale, la table globale est définie par défaut sur la cohérence à terme multirégionale (MREC). Une table globale ne peut pas contenir de réplicas configurés avec différents modes de cohérence. Vous ne pouvez pas modifier le mode de cohérence d’une table globale après sa création.

### Cohérence à terme multirégionale (MREC)
<a name="V2globaltables_HowItWorks.consistency-modes.mrec"></a>

La cohérence à terme multirégionale (MREC) est le mode de cohérence par défaut pour les tables globales. Les modifications d’éléments dans une réplique de table globale MREC sont répliquées de manière asynchrone sur toutes les autres répliques, généralement en une seconde ou moins. Dans le cas peu probable où une réplique d’une table globale MREC serait isolée ou altérée, toutes les données non encore répliquées dans d’autres régions seront répliquées lorsque la réplique sera saine.

Si le même élément est modifié simultanément dans plusieurs régions, DynamoDB résoudra le conflit en utilisant la modification avec le dernier horodatage interne sur une base par élément, ce que l’on appelle la méthode de résolution des conflits « victoire du dernier auteur ». Un élément finira par converger dans toutes les répliques vers la version créée lors de la dernière écriture.

Les [opérations de lecture fortement cohérentes](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html#DDB-GetItem-request-ConsistentRead) renvoient la dernière version d’un élément si cet élément a été mis à jour pour la dernière fois dans la région où la lecture a eu lieu, mais peuvent renvoyer des données périmées si l’article a été mis à jour pour la dernière fois dans une autre région. Les écritures conditionnelles évaluent l’expression de condition par rapport à la version de l’élément dans la région.

Vous créez une table globale MREC en ajoutant une réplique à une table DynamoDB existante. L’ajout d’un réplica n’a aucun impact sur les performances des tables DynamoDB à région unique ou des réplicas de tables globales existantes. Vous pouvez ajouter des réplicas à une table globale MREC pour augmenter le nombre de régions dans lesquelles les données sont répliquées, ou supprimer des réplicas d’une table globale MREC si elles ne sont plus nécessaires. Une table globale MREC peut comporter un réplica dans n’importe quelle région dans laquelle DynamoDB est disponible, et elle peut comporter autant de réplicas que de régions dans la [partition AWS](https://docs.aws.amazon.com/whitepapers/latest/aws-fault-isolation-boundaries/partitions.html).

### Forte cohérence multirégionale (MRSC)
<a name="V2globaltables_HowItWorks.consistency-modes.mrsc"></a>

Vous pouvez configurer le mode MRSC (forte cohérence multirégionale) lorsque vous créez une table globale. Les modifications d’éléments dans un réplica de table globale MRSC sont répliquées de manière synchrone dans au moins une autre région avant que l’opération d’écriture ne renvoie une réponse réussie. Les opérations de lecture fortement cohérente sur tout réplica MRSC renvoient toujours la dernière version d’un élément. Les écritures conditionnelles évaluent toujours l’expression de condition par rapport à la dernière version d’un élément.

Une table globale MRSC doit être déployée dans exactement trois régions. Vous pouvez configurer une table globale MRSC avec trois réplicas, ou avec deux réplicas et un témoin. Un témoin est un composant d'une table globale MRSC qui contient des données écrites dans des répliques de tables globales et fournit une alternative facultative à une réplique complète tout en prenant en charge l'architecture de disponibilité du MRSC. Vous ne pouvez pas effectuer d’opérations de lecture ou d’écriture sur un témoin. Un témoin se trouve dans une région différente de celle des deux réplicas. Lorsque vous créez une table globale MRSC, vous choisissez les régions pour vos répliques et pour le déploiement témoin au moment de la création de la table MRSC. Vous pouvez déterminer si et dans quelle région une table globale MRSC comporte un témoin configuré à partir de la sortie de l’API [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html). Le témoin est détenu et géré par DynamoDB, et il n'apparaîtra pas dans AWS votre compte dans la région où il est configuré.

Les tables mondiales du MRSC sont disponibles dans les ensembles de régions suivants : ensemble de régions des États-Unis (Virginie du Nord des États-Unis, États-Unis de l'Ohio, États-Unis de l'ouest de l'Oregon), ensemble de régions de l'UE (Europe Irlande, Europe Londres, Europe Paris, Europe de Francfort) et ensemble de régions AP (Asie-Pacifique Tokyo, Asie-Pacifique Séoul et Asie-Pacifique Osaka). Les tables globales MRSC ne peuvent pas couvrir des ensembles régionaux (par exemple, une table globale MRSC ne peut pas contenir de réplicas d’ensembles régionaux des États-Unis et de l’UE).

Vous créez une table globale MRSC en ajoutant un réplica et un témoin, ou deux réplicas à une table DynamoDB existante qui ne contient aucune donnée. Lorsque vous convertissez une table mono-région existante en table globale MRSC, vous devez vous assurer que la table est vide. La conversion d’une table à région unique en une table globale MRSC contenant des éléments existants n’est pas prise en charge. Assurez-vous qu’aucune donnée n’est écrite dans la table pendant le processus de conversion. Vous ne pouvez pas ajouter de réplicas supplémentaires à une table globale MRSC existante. Vous ne pouvez pas supprimer un seul réplica ou un seul témoin d’une table globale MRSC. Vous pouvez supprimer deux réplicas ou supprimer un réplica et un témoin d’une table globale MRSC, en convertissant le réplica restant en une table DynamoDB à région unique.

Une opération d’écriture échoue avec une `ReplicatedWriteConflictException` lorsqu’elle tente de modifier un élément déjà en cours de modification dans une autre région. Les écritures qui échouent `ReplicatedWriteConflictException` peuvent être réessayées et seront couronnées de succès si l'élément n'est plus modifié dans une autre région.

Les considérations suivantes s’appliquent aux tables globales MRSC :
+ La durée de vie (TTL) n’est pas prise en charge pour les tables globales MRSC.
+ Les index secondaires locaux (LSIs) ne sont pas pris en charge pour les tables globales MRSC.
+ CloudWatch Les informations de Contributor Insights ne sont communiquées que pour la région dans laquelle une opération a eu lieu.

## Choix d’un mode de cohérence
<a name="V2globaltables_HowItWorks.choosing-consistency-mode"></a>

Le critère clé pour choisir un mode de cohérence multirégional est de savoir si votre application privilégie les écritures à faible latence et les lectures fortement cohérentes, ou privilégie la cohérence globale.

Les tables globales MREC auront des temps d’écriture plus faibles et des latences de lecture fortement cohérentes par rapport aux tables globales MRSC. Les tables globales MREC ont un objectif de point de restauration (RPO) égal au délai de réplication entre les répliques, généralement de quelques secondes selon les régions de réplication.

Vous devez utiliser le mode MREC lorsque :
+ Votre application peut tolérer des données obsolètes renvoyées par des opérations de lecture fortement cohérentes si ces données ont été mises à jour dans une autre région.
+ Vous privilégiez une écriture plus faible et des latences de lecture fortement cohérentes par rapport à la cohérence de lecture multirégionale.
+ Votre stratégie de haute disponibilité multirégionale peut tolérer un RPO supérieur à zéro.

Les tables globales MRSC auront des temps d’écriture plus élevés et des latences de lecture fortement cohérentes par rapport aux tables globales MREC. Les tables MRSC prennent en charge un objectif de point de reprise (RPO) de zéro.

Vous devez utiliser le mode MREC lorsque :
+ Vous avez besoin de lectures fortement cohérentes dans plusieurs régions.
+ Vous privilégiez la cohérence globale de la lecture plutôt que la réduction de la latence d’écriture.
+ Votre stratégie de haute disponibilité multirégionale nécessite un RPO de zéro.

## Surveillance des tables globales
<a name="monitoring-global-tables"></a>

Les tables globales configurées pour la cohérence finale multirégionale (MREC) publient la [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency)métrique dans. CloudWatch Cette métrique suit le temps écoulé entre le moment où un élément est écrit dans une table de réplicas et celui où il apparaît dans un autre réplica dans la table globale. `ReplicationLatency` est exprimé en millisecondes et est émis pour chaque paire région source/région de destination dans une table globale. 

Les `ReplicationLatency` valeurs typiques dépendent de la distance entre les AWS régions que vous avez choisies, ainsi que d'autres variables telles que le type de charge de travail et le débit. Par exemple, un réplica source située dans la région USA Ouest (Californie du Nord) (us-west-1) a une `ReplicationLatency` inférieure dans la région USA Ouest (Oregon) (us-west-2) par rapport à la région Afrique (Le Cap) (af-south-1).

Une valeur croissante pour `ReplicationLatency` peut indiquer que les mises à jour d’un réplica ne sont pas propagées vers d’autres tables de réplica dans un délai raisonnable. Dans ce cas, vous pouvez rediriger temporairement les activités de lecture et d'écriture de votre application vers une autre AWS région.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne publient aucune métrique `ReplicationLatency`.

## Test d’injection de pannes
<a name="fault-injection-testing"></a>

Les tables globales MREC et MRSC s'intègrent au [AWS Fault Injection Service](https://docs.aws.amazon.com/resilience-hub/latest/userguide/testing.html) (AWS FIS), un service entièrement géré permettant d'exécuter des expériences d'injection de défauts contrôlées afin d'améliorer la résilience d'une application. À l'aide du AWS FIS, vous pouvez :
+ Créez des modèles d'expérimentation qui définissent des scénarios de défaillance spécifiques.
+ Injectez les échecs pour valider la résilience des applications en simulant l'isolation des régions (c'est-à-dire en interrompant la réplication vers et depuis une réplique sélectionnée) afin de tester la gestion des erreurs, les mécanismes de restauration et le comportement de transfert du trafic multirégional lorsqu'une AWS région est perturbée.

Par exemple, dans un tableau global contenant des répliques dans l'est des États-Unis (Virginie du Nord), dans l'est des États-Unis (Ohio) et dans l'ouest des États-Unis (Oregon), vous pouvez exécuter une expérience dans l'est des États-Unis (Ohio) pour tester l'isolement de la région dans cette région tandis que l'est des États-Unis (Virginie du Nord) et l'ouest des États-Unis (Oregon) poursuivent leurs activités normales. Ces tests contrôlés vous aident à identifier et à résoudre les problèmes potentiels avant qu’ils n’affectent les charges de travail de production. 

Consultez les [cibles d'action](https://docs.aws.amazon.com/fis/latest/userguide/action-sequence.html#action-targets) dans le *guide de l'utilisateur du AWS FIS* pour obtenir la liste complète des actions prises en charge par le AWS FIS et la [section Connectivité entre régions](https://docs.aws.amazon.com/fis/latest/userguide/cross-region-scenario.html) pour suspendre la réplication DynamoDB entre les régions.

*Pour plus d'informations sur les actions de table globales Amazon DynamoDB disponibles AWS dans FIS, [consultez la référence des actions de tables globales DynamoDB dans le guide de l'utilisateur du FIS](https://docs.aws.amazon.com/fis/latest/userguide/fis-actions-reference.html#dynamodb-actions-reference).AWS *

Pour commencer à exécuter des expériences d'injection de défauts, consultez [la section Planification de vos expériences AWS FIS](https://docs.aws.amazon.com/fis/latest/userguide/getting-started-planning.html) dans le guide de l'utilisateur du AWS FIS.

**Note**  
Au cours AWS FIS des expériences menées dans le MRSC, des lectures cohérentes sont finalement autorisées, mais les mises à jour des paramètres des tables, telles que le changement du mode de facturation ou la configuration du débit des tables, ne sont pas autorisées, comme dans le cas du MREC. Veuillez consulter la CloudWatch métrique [`FaultInjectionServiceInducedErrors`](metrics-dimensions.md#FaultInjectionServiceInducedErrors)pour plus de détails concernant le code d'erreur.

## Durée de vie (TTL)
<a name="global-tables-ttl"></a>

Les tables globales configurées pour le MREC prennent en charge la configuration de la suppression [Time To Live](TTL.md) (TTL). Les paramètres TTL sont automatiquement synchronisés pour tous les réplicas d’une table globale. Lorsque la TTL supprime un élément d’un réplica dans une région, la suppression est répliquée sur tous les autres réplicas de la table globale. La TTL n’utilise pas de capacité d’écriture. La suppression TTL ne vous est donc pas facturée dans la région où la suppression a eu lieu. Toutefois, vous êtes facturé pour la suppression répliquée dans chaque autre région avec un réplica dans la table globale.

La réplication de suppression TTL utilise de la capacité d’écriture sur les réplicas dans lesquels la suppression est répliquée. Les réplicas configurés pour la capacité allouée peuvent limiter les demandes si la combinaison du débit d’écriture et du débit de suppression TTL est supérieure à la capacité d’écriture allouée.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne prennent pas en charge la configuration de la suppression Time To Live (TTL).

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

Les tables globales configurées pour une cohérence à terme entre plusieurs régions (MREC) répliquent les modifications en lisant ces modifications à partir de [flux DynamoDB](Streams.md) sur une table de réplica et en appliquant cette modification à toutes les autres tables de réplica. Les flux sont donc activés par défaut sur tous les réplicas d’une table globale MREC et ne peuvent pas être désactivé sur ces réplicas. Le processus de réplication MREC peut combiner plusieurs modifications sur une courte période en une seule écriture répliquée, ce qui fait que le flux de chaque réplica contient des enregistrements légèrement différents. Les enregistrements de flux sur les réplicas MREC sont toujours classés par article, mais l’ordre entre les éléments peut différer selon les réplicas.

Les tables globales configurées pour une forte cohérence multirégionale (tables MRSC) n’utilisent pas les flux DynamoDB pour la réplication. Cette fonctionnalité n’est donc pas activée par défaut sur les réplicas MRSC. Vous pouvez activer les flux sur un réplica MRSC. Les enregistrements de flux sur les répliques MRSC sont identiques pour chaque réplica, y compris l’ordre des enregistrements de flux.

Si vous souhaitez écrire une application qui traite les enregistrements de flux pour les modifications survenues dans une région particulière mais pas dans d’autres régions d’une table globale, vous pouvez ajouter un attribut à chaque élément qui définit dans quelle région le changement pour cet élément s’est produit. Vous pouvez utiliser cet attribut pour filtrer les enregistrements de flux en fonction des modifications survenues dans d’autres régions, notamment en utilisant des filtres d’événements Lambda pour n’appeler les fonctions Lambda que pour les modifications dans une région spécifique.

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

Sur une table globale configurée pour MREC, les opérations de transaction DynamoDB ( [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactWriteItems.html) et [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TransactGetItems.html)) ne sont atomiques que dans la région où l’opération a été invoquée. Les écritures transactionnelles ne sont pas répliquées en tant qu’unité entre les régions, ce qui signifie que seules certaines des écritures d’une transaction peuvent être renvoyées par des opérations de lecture dans d’autres réplicas à un instant dans le passé donné.

Par exemple, si vous avez une table globale avec des réplicas dans les régions USA Est (Ohio) et USA Ouest (Oregon), et que vous réalisez une opération `TransactWriteItems` dans la région USA Est (Ohio), vous remarquerez peut-être des transactions partiellement incomplètes dans la région USA Ouest (Oregon) lorsque les changements sont répliqués. Les changements seront uniquement répliqués aux autres régions une fois validés dans la région source.

Les tables globales configurées pour une forte cohérence multirégionale (MRSC) ne prennent pas en charge les opérations de transaction et renvoient une erreur si ces opérations sont invoquées sur une réplique MRSC.

## Débit de lecture et d’écriture
<a name="V2globaltables_HowItWorks.Throughput"></a>

### Mode alloué
<a name="gt_throughput.provisioned"></a>

La réplication consomme de la capacité d’écriture. Les répliques configurées pour la capacité allouée peuvent limiter les demandes si la combinaison du débit d'écriture de l'application et du débit d'écriture de réplication dépasse la capacité d'écriture allouée. Pour les tables globales utilisant le mode provisionné, les paramètres de dimensionnement automatique pour les capacités de lecture et d'écriture sont synchronisés entre les répliques.

Vous pouvez configurer indépendamment les paramètres de capacité de lecture pour chaque réplique dans une table globale en utilisant le [https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ProvisionedThroughputOverride.html)paramètre au niveau de la réplique. Par défaut, les modifications apportées à la capacité de lecture allouée sont appliquées à toutes les répliques de la table globale. Lors de l'ajout d'une nouvelle réplique à une table globale, la capacité de lecture de la table source ou de la réplique est utilisée comme valeur initiale, sauf si une dérogation au niveau de la réplique est explicitement spécifiée.

### Mode de capacité à la demande
<a name="gt_throughput.on-demand"></a>

Pour les tables globales configurées en mode à la demande, la capacité d'écriture est automatiquement synchronisée entre toutes les répliques. DynamoDB ajuste automatiquement la capacité en fonction du trafic, et il n'existe aucun paramètre de capacité de lecture ou d'écriture spécifique à la réplique à gérer.

## Synchronisation des paramètres
<a name="V2globaltables_HowItWorks.setting-synchronization"></a>

Les paramètres des tables globales DynamoDB sont des paramètres de configuration qui contrôlent divers aspects du comportement des tables et de la réplication. Ces paramètres sont gérés via le APIs plan de contrôle DynamoDB et peuvent être configurés lors de la création ou de la modification de tables globales. Les tables globales synchronisent automatiquement certains paramètres entre tous les réplicas afin de maintenir la cohérence, tout en offrant une certaine flexibilité pour les optimisations spécifiques aux régions. Comprendre quels paramètres sont synchronisés et comment ils se comportent vous permet de configurer efficacement votre table globale. Les paramètres se répartissent en trois catégories principales en fonction de la façon dont ils sont synchronisés entre les réplicas.

Les paramètres suivants sont toujours synchronisés entre les réplicas d’une table globale :
+ Mode capacité (capacité provisionnée ou à la demande)
+ Capacité d’écriture provisionnée dans la table
+ Autoscaling de l’écriture dans une table
+ Définition de l'attribut du schéma clé
+ Définition de l’index secondaire global (GSI)
+ Capacité d’écriture provisionnée dans GSI
+ Autoscaling de l’écriture dans GSI
+ Type de chiffrement côté serveur (SSE)
+ Définition des flux en mode MREC
+ Durée de vie (TTL)
+ Débit chaud
+ Débit d’écriture maximal à la demande

Les paramètres suivants sont synchronisés entre les réplicas, mais peuvent être remplacés au cas par cas :
+ Capacité de lecture provisionnée pour une table
+ Autoscaling de la lecture dans une table
+ Capacité de lecture provisionnée dans GSI
+ Autoscaling de la lecture dans GSI
+ Classe de table
+ Débit de lecture maximum à la demande

**Note**  
Les valeurs de paramètre remplaçables sont modifiées si le paramètre est modifié sur un autre réplica. Par exemple, vous avez une table globale MREC avec des réplicas dans les régions USA Est (Virginie du Nord) et USA Ouest (Oregon). La réplique de l'est des États-Unis (Virginie du Nord) a prévu un débit de lecture fixé à 200. RCUs La réplique située dans l'ouest des États-Unis (Oregon) dispose d'une dérogation au débit de lecture provisionnée fixée à 100. RCUs Si vous mettez à jour le paramètre de débit de lecture provisionné sur la réplique de l'est des États-Unis (Virginie du Nord) de 200 RCUs à 300 RCUs, la nouvelle valeur du débit de lecture provisionné sera également appliquée à la réplique de l'ouest des États-Unis (Oregon). Cela fait passer le paramètre de débit de lecture provisionné pour la réplique de l'ouest des États-Unis (Oregon) de la valeur remplacée de 100 RCUs à la nouvelle valeur de 300. RCUs

Les paramètres suivants ne sont jamais synchronisés entre les réplicas :
+ Protection contre la suppression
+ Point-in-time Récupération
+ Étiquettes
+ Activation de Tableau CloudWatch Contributor Insights
+ Activation de GSI CloudWatch Contributor Insights
+ Définition de flux de données Kinesis
+ Stratégies basées sur une ressource
+ Définition des flux en mode MRSC

Tous les autres paramètres ne sont pas synchronisés entre les réplicas.

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

Les écritures dans des réplicas de tables globales contournent DynamoDB Accelerator (DAX) et mettent directement DynamoDB à jour. Par conséquent, les caches DAX peuvent devenir obsolètes, car les écritures ne mettent pas à jour le cache DAX. Les caches DAX configurés pour les réplicas de tables globales ne seront actualisés que lorsque la TTL du cache expirera.

## Considérations relatives à la gestion des tables globales
<a name="management-considerations"></a>

Vous ne pouvez pas supprimer une table utilisée pour ajouter un nouveau réplica de table globale avant que 24 heures ne se soient écoulées depuis la création du nouveau réplica.

Si vous désactivez une AWS région contenant des répliques de tables globales, ces répliques sont définitivement converties en tables à région unique 20 heures après la désactivation de la région.

# Tutoriels : Création de tables globales
<a name="V2globaltables.tutorial"></a>

Cette section fournit des step-by-step instructions pour créer des tables globales DynamoDB configurées pour votre mode de cohérence préféré. Choisissez le mode MREC ou le mode MRSC en fonction des exigences de votre application.

Les tables globales MREC offrent une latence d’écriture plus faible avec une cohérence à terme entre les Régions AWS. Les tables globales MRSC permettent des lectures fortement cohérentes dans toutes les régions avec des latences d’écriture légèrement supérieures à celles des tables MREC. Choisissez le mode de cohérence qui répond le mieux aux besoins de cohérence, de latence et de disponibilité des données de votre application.

**Topics**
+ [Création d’une table globale configurée pour MREC](#V2creategt_mrec)
+ [Création d’une table globale configurée pour MRSC](#create-gt-mrsc)

## Création d’une table globale configurée pour MREC
<a name="V2creategt_mrec"></a>

Cette section explique comment créer une table globale avec le mode MREC. MREC est le mode de cohérence par défaut pour les tables globales et il permet des écritures à faible latence avec une réplication asynchrone entre les Régions AWS. Les modifications apportées à un élément dans une région sont généralement répliquées dans toutes les autres régions en une seconde. Le mode MREC est donc idéal pour les applications qui privilégient une faible latence d’écriture et peuvent tolérer de brèves périodes pendant lesquelles différentes régions peuvent renvoyer des versions de données légèrement différentes.

Vous pouvez créer des tables globales MREC avec des répliques dans toutes les AWS régions où DynamoDB est disponible et ajouter ou supprimer des répliques à tout moment. Les exemples suivants montrent comment créer une table globale MREC avec des réplicas dans plusieurs régions.

### Création d’une table globale MREC à l’aide de la console DynamoDB
<a name="mrec-console"></a>

Suivez ces étapes pour créer une table globale avec AWS Management Console. L’exemple suivant crée une table globale avec des tables de réplica aux États-Unis et en Europe.

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Pour cet exemple, choisissez **USA Est (Ohio)** dans le sélecteur de région dans la barre de navigation.

1. Dans le volet de navigation sur le côté gauche de la console, choisissez **Tables**.

1. Choisissez **Créer une table**.

1. Sur la page **Créer un tableau** :

   1. Sous **Nom du tableau**, saisissez **Music**.

   1. Pour **Clé de partition**, saisissez **Artist**.

   1. Pour **Clé de tri**, entrez **SongTitle**.

   1. Conservez les autres paramètres par défaut et choisissez **Créer une table**.

      La nouvelle table sert de première table de réplica dans une nouvelle table globale. Il s’agit du prototype pour d’autres tables de réplica que vous ajouterez ultérieurement.

1. Une fois que la table est active :

   1. Choisissez la table **Musique** dans la liste de tables.

   1. Choisissez l’onglet **Tables globales**.

   1. Choisissez **Créer un réplica**.

1. Dans la liste déroulante **Régions de réplication disponibles**, choisissez **USA Ouest (Oregon) us-west-2**.

   La console vérifie qu’il n’existe pas de table du même nom dans la région sélectionnée. (Si une table du même nom existe, vous devez la supprimer avant de pouvoir créer une nouvelle table de réplicas dans cette région.)

1. Choisissez **Créer un réplica**. Cela a pour effet de démarrer le processus de création de table dans la région USA Ouest (Oregon) us-west-2 Region.

   L’onglet **Tables globales** pour la table **Musique** (et pour toutes les autres tables de réplica) indique que la table a été répliquée dans plusieurs régions.

1. Ajoutez une autre région en répétant les étapes précédentes, mais choisissez **Europe (Francfort) eu-central-1** comme région.

1. Pour tester la réplication :

   1. Assurez-vous d'utiliser le AWS Management Console dans la région de l'est des États-Unis (Ohio).

   1. Choisissez **Explorer les éléments de la table**.

   1. Choisissez **Créer un élément**.

   1. Entrez **item\$11** pour **Artiste** et **Song Value 1** pour **SongTitle**.

   1. Choisissez **Créer un élément**.

1. Vérifiez la réplication en passant aux autres régions :

   1. Dans le sélecteur de région situé en haut à droite, choisissez **Europe (**Francfort).

   1. Vérifiez que le tableau **Musique** contient l’élément que vous avez créé.

   1. Répétez la vérification pour la région **USA Ouest (Oregon)**.

### Création d'une table globale MREC à l'aide de AWS CLI ou Java
<a name="mrec-cli-java"></a>

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

L’exemple de code suivant montre comment gérer les tables globales DynamoDB avec la cohérence à terme de la réplication multirégionale (MREC).
+ Créez une table avec la réplication multirégionale (MREC).
+ Placez et récupérez des objets de tables de réplica.
+ Supprimez les répliques one-by-one.
+ Nettoyez en supprimant la table.

**AWS CLI avec le script Bash**  
Créez une table avec la réplication multirégionale.  

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

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

# Step 3: Create a table in Europe (Ireland)
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Create": {
        "RegionName": "eu-west-1"
      }
    }
  ]
}' \
--region us-east-2
```
Décrivez la table multirégionale.  

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

```
# Step 5: To verify that replication is working, add a new item to the Music table in US East (Ohio)
aws dynamodb put-item \
    --table-name MusicTable \
    --item '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region us-east-2
```
Récupérez des objets de tables de réplica.  

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

aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"item_1"},"SongTitle": {"S":"Song Value 1"}}' \
    --region eu-west-1
```
Supprimez les réplicas.  

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

# Delete the replica table in US East (N. Virginia) Region
aws dynamodb update-table --table-name MusicTable --cli-input-json \
'{
  "ReplicaUpdates":
  [
    {
      "Delete": {
        "RegionName": "us-east-1"
      }
    }
  ]
}' \
--region us-east-2
```
Nettoyez en supprimant la table.  

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

echo "Global table demonstration complete."
```
+ Pour plus de détails sur l’API, consultez les rubriques suivantes dans la *Référence des commandes de l’AWS CLI *.
  + [CreateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/PutItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateTable)

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

L’exemple de code suivant montre comment créer et gérer des tables globales DynamoDB avec des réplicas entre plusieurs régions.
+ Création d’une table avec un index secondaire global et DynamoDB Streams.
+ Ajout de réplicas dans différentes régions pour créer une table globale.
+ Suppression de réplicas d’une table globale.
+ Ajout d’éléments de test pour vérifier la réplication entre plusieurs régions.
+ Description de la configuration globale de la table et de l’état du réplica.

**SDK pour Java 2.x**  
Créez une table avec l'index secondaire global et les flux DynamoDB à l'aide de. AWS SDK for Java 2.x  

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to create table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Attendez qu'une table soit active en utilisant AWS SDK for Java 2.x.  

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

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

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

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

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

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to wait for table to become active: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Ajoutez une réplique pour créer ou étendre une table globale à l'aide de AWS SDK for Java 2.x.  

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

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add replica in region: " + replicaRegion.id() + " - " + e.getMessage());
            throw e;
        }
    }
```
Supprimez une réplique d'une table globale à l'aide de AWS SDK for Java 2.x.  

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

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to remove replica in region: " + replicaRegion.id() + " - " + e.getMessage());
            throw e;
        }
    }
```
Ajoutez des éléments de test pour vérifier la réplication à l'aide de AWS SDK for Java 2.x.  

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

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add test item to table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Décrivez la configuration globale des tables et les répliques à l'aide AWS SDK for Java 2.x de.  

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

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

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

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

            DescribeTableResponse response = dynamoDbClient.describeTable(request);

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

            return response;

        } catch (ResourceNotFoundException e) {
            LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage());
            throw e;
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Exemple complet d'opérations de table globales utilisant AWS SDK for Java 2.x.  

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

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

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

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

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

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

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

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

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

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

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

            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("Thread was interrupted", e);
            } catch (DynamoDbException e) {
                LOGGER.severe("DynamoDB operation failed: " + e.getMessage());
                throw e;
            }
        }
    }
```
+ Pour plus de détails sur l’API, consultez les rubriques suivantes dans la *Référence des API du kit AWS SDK for Java 2.x *.
  + [CreateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/CreateTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DescribeTable)
  + [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateTable)

------

## Création d’une table globale configurée pour MRSC
<a name="create-gt-mrsc"></a>

Cette section explique comment créer une table globale à forte cohérence multirégionale (MRSC). Les tables globales MRSC reproduisent de manière synchrone les modifications apportées aux éléments d’une région à l’autre, ce qui garantit que les opérations de lecture fortement cohérentes sur tout réplica renvoient toujours la dernière version d’un élément. Lorsque vous convertissez une table à région unique en table globale MRSC, vous devez vous assurer que la table est vide. La conversion d’une table à région unique en une table globale MRSC contenant des éléments existants n’est pas prise en charge. Assurez-vous qu’aucune donnée n’est écrite dans la table pendant le processus de conversion.

Vous pouvez configurer une table globale MRSC avec trois réplicas, ou deux réplicas et un témoin. Lorsque vous créez une table globale MRSC, vous choisissez les régions dans lesquelles les réplicas et un témoin facultatif sont déployés. L’exemple suivant crée une table globale MRSC avec des réplicas dans les régions USA Est (Virginie du Nord) et USA Est (Ohio) et USA Est (Ohio) et un témoin dans la région USA Ouest (Oregon).

**Note**  
Avant de créer une table globale, vérifiez que les limites de débit des quotas de service sont cohérentes dans toutes les régions cibles, car cela est nécessaire pour créer une table globale. Pour plus d’informations sur les limites de débit globales des tables, consultez [Global tables quotas](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ServiceQuotas.html#gt-limits-throughput).

### Création d’une table globale MRSC à l’aide de la console DynamoDB
<a name="mrsc_console"></a>

Suivez ces étapes pour créer une table globale MRSC avec l’ AWS Management Console.

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le sélecteur de région dans la barre de navigation, choisissez une région où les tables globales avec MRSC sont [prises en charge](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes), par exemple **us-east-2**.

1. Dans le volet de navigation, choisissez **Tables**.

1. Choisissez **Créer un tableau**.

1. Sur la page **Créer un tableau** :

   1. Sous **Nom du tableau**, saisissez **Music**.

   1. Pour **Clé de partition**, saisissez **Artist**, et conservez le type de **Chaîne** par défaut.

   1. Pour **Clé de tri**, saisissez **SongTitle**, et conservez le type de **Chaîne** par défaut.

   1. Conservez les autres paramètres par défaut et choisissez **Créer une table**

      La nouvelle table sert de première table de réplica dans une nouvelle table globale. Il s’agit du prototype pour d’autres tables de réplica que vous ajouterez ultérieurement.

1. Attendez que la table soit active, puis sélectionnez-la dans la liste des tables.

1. Choisissez l’onglet **Tables globales**, puis choisissez **Créer un réplica**.

1. Sur la page **Créer un réplica** :

   1. Sous **Cohérence multirégionale**, sélectionnez **Forte cohérence**.

   1. Pour **Région de réplication 1**, choisissez **US East (N. Virginia) us-east-1**.

   1. Pour **Région de réplication 2**, choisissez **US West (Oregon) us-west-2**.

   1. Cochez la case **Configurer en tant que témoin** pour la région USA Ouest (Oregon).

   1. Choisissez **Créer des réplicas**.

1. Attendez que le processus de création du réplica et du témoin soit terminé. L’état du réplica affiché est **Actif** lorsque la table est prête pour utilisation.

### Création d'une table globale MRSC à l'aide de AWS CLI ou Java
<a name="mrsc-cli-java"></a>

Avant de commencer, assurez-vous que votre principal IAM dispose des autorisations requises pour créer une table globale MRSC avec une région témoin.

L’exemple de politique IAM suivant vous permet de créer une table DynamoDB (`MusicTable`) dans la région USA Est (Ohio) avec un réplica dans la région USA Est (Virginie du Nord) et une région témoin dans la région USA Ouest (Oregon) :

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

****  

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

------

Les exemples de code suivants montrent comment créer et gérer des tables globales DynamoDB avec MRSC (forte cohérence multirégionale).
+ Création d’une table avec une forte cohérence multirégionale.
+ Vérifiez la configuration MRSC et le statut du réplica.
+ Testez une forte cohérence entre les régions grâce à des lectures immédiates.
+ Effectuez des écritures conditionnelles avec les garanties MRSC.
+ Nettoyez les ressources des tables globales MRSC.

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

**AWS CLI avec le script Bash**  
Créez une table avec une forte cohérence multirégionale.  

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

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

# Step 2: Add replica and witness with Multi-Region Strong Consistency
# MRSC requires exactly three replicas in supported regions
aws dynamodb update-table \
    --table-name MusicTable \
    --replica-updates '[{"Create": {"RegionName": "us-east-1"}}]' \
    --global-table-witness-updates '[{"Create": {"RegionName": "us-west-2"}}]' \
    --multi-region-consistency STRONG \
    --region us-east-2
```
Vérifiez la configuration MRSC et le statut du réplica.  

```
# Verify the global table configuration and MRSC setting
aws dynamodb describe-table \
    --table-name MusicTable \
    --region us-east-2 \
    --query 'Table.{TableName:TableName,TableStatus:TableStatus,MultiRegionConsistency:MultiRegionConsistency,Replicas:Replicas[*],GlobalTableWitnesses:GlobalTableWitnesses[*].{Region:RegionName,Status:ReplicaStatus}}'
```
Testez une forte cohérence avec des lectures immédiates dans les régions.  

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

# Read the item from replica region to verify strong consistency (cannot read or write to witness)
# No wait time needed - MRSC provides immediate consistency
echo "Reading from us-east-1 (immediate consistency):"
aws dynamodb get-item \
    --table-name MusicTable \
    --key '{"Artist": {"S":"The Beatles"},"SongTitle": {"S":"Hey Jude"}}' \
    --consistent-read \
    --region us-east-1
```
Effectuez des écritures conditionnelles avec les garanties MRSC.  

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

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

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

# Delete the primary table
aws dynamodb delete-table \
    --table-name MusicTable \
    --region us-east-2
```
+ Pour plus de détails sur l’API, consultez les rubriques suivantes dans la *Référence des commandes de l’AWS CLI *.
  + [CreateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/PutItem)
  + [UpdateItem](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/aws-cli/dynamodb-2012-08-10/UpdateTable)

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

**SDK pour Java 2.x**  
Créez un tableau régional prêt pour la conversion MRSC à l'aide AWS SDK for Java 2.x de.  

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to create regional table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to create regional table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Convertissez une table régionale en MRSC à l'aide de répliques et de témoins à l'aide de témoins. AWS SDK for Java 2.x  

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

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

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

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

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

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

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

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to convert table to MRSC: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to convert table to MRSC: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Décrivez une configuration de table globale MRSC à l'aide AWS SDK for Java 2.x de.  

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

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

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

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

            DescribeTableResponse response = dynamoDbClient.describeTable(request);

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

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

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

            return response;

        } catch (ResourceNotFoundException e) {
            LOGGER.severe("Table not found: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Table not found: " + tableName)
                .cause(e)
                .build();
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to describe table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to describe table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Ajout d’éléments de test pour vérifier la forte cohérence du MRSC à l’aide du kit AWS SDK for Java 2.x.  

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

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

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to add test item to table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to add test item to table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Lisez des éléments avec des lectures cohérentes à partir de répliques MRSC à l'aide de. AWS SDK for Java 2.x  

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

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

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

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

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

            GetItemResponse response = dynamoDbClient.getItem(getItemRequest);

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to read item from table: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to read item from table: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Effectuez des mises à jour conditionnelles avec les garanties MRSC en utilisant AWS SDK for Java 2.x.  

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

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

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

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

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

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

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

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

            return response;

        } catch (ConditionalCheckFailedException e) {
            LOGGER.warning("Conditional check failed: " + e.getMessage());
            throw e;
        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to perform conditional update: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to perform conditional update: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Attendez que les répliques du MRSC et que les témoins deviennent actifs en utilisant. AWS SDK for Java 2.x  

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

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

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

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

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

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

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

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

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

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

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

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

                tempWait(backoffSeconds);

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

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

        } catch (DynamoDbException | InterruptedException e) {
            LOGGER.severe("Failed to wait for MRSC replicas to become active: " + tableName + " - " + e.getMessage());
            throw e;
        }
    }
```
Nettoyez les répliques du MRSC et les témoins à l'aide de. AWS SDK for Java 2.x  

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

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

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

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

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

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

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

            return response;

        } catch (DynamoDbException e) {
            LOGGER.severe("Failed to cleanup MRSC replicas: " + tableName + " - " + e.getMessage());
            throw DynamoDbException.builder()
                .message("Failed to cleanup MRSC replicas: " + tableName)
                .cause(e)
                .build();
        }
    }
```
Démonstration complète du flux de travail MRSC à l'aide de AWS SDK for Java 2.x.  

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        } catch (DynamoDbException | InterruptedException e) {
            LOGGER.severe("MRSC workflow failed: " + e.getMessage());
            throw e;
        }
    }
```
+ Pour plus de détails sur l’API, consultez les rubriques suivantes dans la *Référence des API du kit AWS SDK for Java 2.x *.
  + [CreateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/CreateTable)
  + [DeleteTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DeleteTable)
  + [DescribeTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/DescribeTable)
  + [GetItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/GetItem)
  + [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)
  + [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)
  + [UpdateTable](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateTable)

------

# Sécurité des tables globales DynamoDB
<a name="globaltables-security"></a>

Les répliques de tables globales étant des tables DynamoDB, vous utilisez les mêmes méthodes pour contrôler l'accès aux répliques que pour les tables à région unique, Gestion des identités et des accès AWS y compris les politiques d'identité (IAM) et les politiques basées sur les ressources.

Cette rubrique explique comment sécuriser les tables globales DynamoDB à l'aide des autorisations AWS Key Management Service IAM et du chiffrement ().AWS KMS Vous découvrirez les rôles liés aux services (SLR) qui permettent la réplication entre régions et l'auto-scaling, les autorisations IAM nécessaires pour créer, mettre à jour et supprimer des tables globales, ainsi que les différences entre les tables de cohérence finale multirégionale (MREC) et les tables de cohérence forte multirégions (MRSC). Vous découvrirez également les clés de AWS KMS chiffrement permettant de gérer la réplication entre régions en toute sécurité.

## Rôles liés à un service pour les tables globales
<a name="globaltables-slr"></a>

Les tables globales DynamoDB s'appuient sur des rôles liés à un service SLRs () pour gérer les fonctionnalités de réplication entre régions et d'auto-scaling.

Vous ne devez configurer ces rôles qu'une seule fois par AWS compte. Une fois créés, les mêmes rôles sont utilisés pour toutes les tables globales de votre compte. Pour en savoir plus sur l’utilisation des rôles liés à un service, consultez [Utilisation des rôles liés à un service](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) dans le *Guide de l’utilisateur IAM*.

### Rôle lié à un service pour la réplication
<a name="globaltables-replication-slr"></a>

Amazon DynamoDB crée automatiquement `AWSServiceRoleForDynamoDBReplication` le rôle lié à un service (SLR) lorsque vous créez votre première table globale. Ce rôle gère la réplication entre régions pour vous.

Lorsque vous appliquez des politiques basées sur les ressources à des répliques, assurez-vous de ne refuser aucune des autorisations définies dans le `AWSServiceRoleForDynamoDBReplicationPolicy` SLR principal, car cela interrompra la réplication. Si vous refusez les autorisations SLR requises, la réplication vers et depuis les réplicas concernés s’arrêtera et le statut de la table de réplicas passera à `REPLICATION_NOT_AUTHORIZED`.
+ Pour les tables globales MREC (Multi-region Evental Cohérence), si une réplique reste dans l'`REPLICATION_NOT_AUTHORIZED`état pendant plus de 20 heures, elle est convertie de manière irréversible en table DynamoDB à région unique.
+ Pour les tables globales à forte cohérence multirégionale (MRSC), le refus des autorisations requises entraîne des opérations `AccessDeniedException` d'écriture et de lecture très cohérentes. Si une réplique reste dans `REPLICATION_NOT_AUTHORIZED` cet état pendant plus de sept jours, elle devient définitivement inaccessible, et les opérations d'écriture et de lecture très cohérentes continueront d'échouer avec une erreur. Certaines opérations de gestion, telles que la suppression des réplicas, seront couronnées de succès.

### Rôle lié à un service pour l’autoscaling
<a name="globaltables-autoscaling-slr"></a>

Lors de la configuration d'une table globale pour le mode capacité allouée, le dimensionnement automatique doit être configuré pour la table globale. DynamoDB Auto Scaling AWS utilise le service Application Auto Scaling pour ajuster dynamiquement la capacité de débit allouée sur vos répliques de tables globales. Le service Application Auto Scaling crée un rôle lié au service (SLR) nommé. [https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html](https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html) Ce rôle lié à un service est automatiquement créé dans votre AWS compte lorsque vous configurez pour la première fois le dimensionnement automatique pour une table DynamoDB. Il permet à Application Auto Scaling de gérer la capacité des tables provisionnées et de créer des CloudWatch alarmes. 

 Lorsque vous appliquez des politiques basées sur les ressources à des répliques, assurez-vous de ne pas refuser les autorisations définies dans le [https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html)principal Application Auto Scaling SLR, car cela interromprait la fonctionnalité de dimensionnement automatique.

### Exemples de politiques IAM pour les rôles liés à un service
<a name="globaltables-example-slr"></a>

Une politique IAM présentant la condition suivante n'a aucune incidence sur les autorisations requises pour le SLR de réplication DynamoDB et AWS le SLR Auto Scaling. Cette condition peut être ajoutée à des politiques par ailleurs largement restrictives afin d'éviter d'interrompre involontairement la réplication ou le dimensionnement automatique.

#### Exclusion des autorisations SLR requises des politiques de refus
<a name="example-exclude-slr-policy"></a>

L'exemple suivant montre comment exclure les principaux de rôles liés à un service des déclarations de refus :

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

## Comment les tables globales utilisent AWS IAM
<a name="globaltables-iam"></a>

Les sections suivantes décrivent les autorisations requises pour les différentes opérations sur les tables globales et fournissent des exemples de politiques pour vous aider à configurer l'accès approprié pour vos utilisateurs et applications.

**Note**  
Toutes les autorisations décrites doivent être appliquées à l'ARN de la ressource de table spécifique dans la ou les régions concernées. L'ARN de la ressource de table suit le format `arn:aws:dynamodb:region:account-id:table/table-name` dans lequel vous devez spécifier les valeurs réelles de votre région, de votre identifiant de compte et du nom de la table.

**Topics**
+ [Création de tables globales et ajout de répliques](#globaltables-creation-iam)
+ [Mise à jour de tables globales](#globaltables-update-iam)
+ [Suppression de tables globales et suppression de répliques](#globaltables-delete-iam)

### Création de tables globales et ajout de répliques
<a name="globaltables-creation-iam"></a>

Les tables globales DynamoDB prennent en charge deux modes de cohérence : cohérence finale multirégionale (MREC) et cohérence forte multirégionale (MRSC). Les tables globales MREC peuvent avoir plusieurs répliques dans un certain nombre de régions et garantir une cohérence finale. Les tables mondiales MRSC nécessitent exactement trois régions (trois répliques ou deux répliques et un témoin) et garantissent une forte cohérence avec un objectif de point de reprise zéro (RPO).

Les autorisations requises pour créer des tables globales varient selon que vous créez une table globale avec ou sans témoin.

#### Autorisations pour créer des tables globales
<a name="globaltables-creation-iam-all-types"></a>

Les autorisations suivantes sont requises à la fois pour la création initiale de la table globale et pour l'ajout de répliques ultérieurement. Ces autorisations s'appliquent à la fois aux tables globales de cohérence éventuelle multirégionale (MREC) et de cohérence forte entre régions (MRSC).
+ Les tables globales nécessitent une réplication entre régions, que DynamoDB gère via le rôle lié à un service ([`AWSServiceRoleForDynamoDBReplication`](#globaltables-replication-slr)SLR). L'autorisation suivante permet à DynamoDB de créer ce rôle automatiquement lorsque vous créez une table globale pour la première fois :
  + `iam:CreateServiceLinkedRole`
+ Pour créer une table globale ou ajouter une réplique à l'aide de l'[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API, vous devez disposer des autorisations suivantes sur la ressource de la table source :
  + `dynamodb:UpdateTable`
+ Vous devez disposer des autorisations suivantes sur la ressource de table dans les régions pour que les répliques soient ajoutées :
  + `dynamodb:CreateTable`
  + `dynamodb:CreateTableReplica`
  + `dynamodb:Query`
  + `dynamodb:Scan`
  + `dynamodb:UpdateItem`
  + `dynamodb:PutItem`
  + `dynamodb:GetItem`
  + `dynamodb:DeleteItem`
  + `dynamodb:BatchWriteItem`

#### Autorisations supplémentaires pour les tables globales MRSC utilisant un témoin
<a name="globaltables-creation-iam-witness"></a>

Lorsque vous créez une table globale multirégionale à forte cohérence (MRSC) avec une région témoin, vous devez disposer des autorisations suivantes sur la ressource de la table dans toutes les régions participantes (y compris les régions répliques et la région témoin) :
+ `dynamodb:CreateGlobalTableWitness`

#### Exemples de politiques IAM pour créer des tables globales
<a name="globaltables-creation-iam-example"></a>

##### Création d'une table mondiale MREC ou MRSC dans trois régions
<a name="globaltables-creation-iam-example-three-regions"></a>

La politique basée sur l'identité suivante vous permet de créer une table globale MREC ou MRSC nommée « utilisateurs » dans trois régions, notamment en créant le rôle lié au service de réplication DynamoDB requis.

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

****  

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

------

##### Restreindre la création de tables globales MREC ou MRSC à des régions spécifiques
<a name="globaltables-creation-iam-example-restrict-regions"></a>

La politique basée sur l'identité suivante vous permet de créer des répliques de tables globales DynamoDB dans des régions spécifiques à l'aide de la clé de RequestedRegion condition [aws :](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requestedregion), notamment en créant le rôle lié au service de réplication DynamoDB requis.

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

****  

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

------

##### Création d'une table mondiale du MRSC avec témoins
<a name="globaltables-creation-iam-example-witness"></a>

La politique basée sur l'identité suivante vous permet de créer une table globale DynamoDB MRSC nommée « users » avec des répliques dans us-east-1 et us-east-2 et un témoin dans us-west-2, notamment en créant le rôle lié au service de réplication DynamoDB requis.

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

****  

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

------

##### Restreindre la création de témoins MRSC à des régions spécifiques
<a name="globaltables-creation-iam-example-restrict-witness-regions"></a>

Cette politique basée sur l'identité vous permet de créer une table globale MRSC avec des répliques limitées à des régions spécifiques à l'aide de la clé de RequestedRegion condition [aws :](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-requestedregion) et de la création illimitée de témoins dans toutes les régions, y compris la création du rôle lié au service de réplication DynamoDB requis.

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

****  

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

------

### Mise à jour de tables globales
<a name="globaltables-update-iam"></a>

Pour modifier les paramètres de réplication d'une table globale existante à l'aide de l'[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API, vous devez disposer de l'autorisation suivante sur la ressource de table dans la région dans laquelle vous effectuez l'appel d'API :
+ `dynamodb:UpdateTable`

Vous pouvez également mettre à jour d'autres configurations de table globales, telles que les politiques de dimensionnement automatique et les paramètres Time to Live. Les autorisations suivantes sont requises pour ces opérations de mise à jour supplémentaires :
+ Pour mettre à jour une politique de dimensionnement automatique des répliques avec l'[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTableReplicaAutoScaling.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTableReplicaAutoScaling.html)API, vous devez disposer des autorisations suivantes sur la ressource de table dans toutes les régions contenant des répliques :
  + `application-autoscaling:DeleteScalingPolicy`
  + `application-autoscaling:DeleteScheduledAction`
  + `application-autoscaling:DeregisterScalableTarget`
  + `application-autoscaling:DescribeScalableTargets`
  + `application-autoscaling:DescribeScalingActivities`
  + `application-autoscaling:DescribeScalingPolicies`
  + `application-autoscaling:DescribeScheduledActions`
  + `application-autoscaling:PutScalingPolicy`
  + `application-autoscaling:PutScheduledAction`
  + `application-autoscaling:RegisterScalableTarget`
+ Pour mettre à jour les paramètres Time to Live avec l'[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTimeToLive.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTimeToLive.html)API, vous devez disposer de l'autorisation suivante sur la ressource de table dans toutes les régions contenant des répliques :
  + `dynamodb:UpdateTimeToLive`

  Notez que le Time to Live (TTL) n'est pris en charge que pour les tables globales configurées avec MREC (Multi-Region Evental Consistency). Pour plus d'informations sur le fonctionnement des tables globales avec TTL, voir [Fonctionnement des tables globales DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/V2globaltables_HowItWorks.html).

### Suppression de tables globales et suppression de répliques
<a name="globaltables-delete-iam"></a>

Pour supprimer une table globale, vous devez supprimer toutes les répliques. Les autorisations requises pour cette opération varient selon que vous supprimez une table globale avec ou sans région témoin.

#### Autorisations pour supprimer des tables globales et supprimer des répliques
<a name="globaltables-delete-iam-all-types"></a>

Les autorisations suivantes sont requises à la fois pour supprimer des répliques individuelles et pour supprimer complètement des tables globales. La suppression d'une configuration de table globale supprime uniquement la relation de réplication entre les tables de différentes régions. Cela ne supprime pas la table DynamoDB sous-jacente dans la dernière région restante. La table de la dernière région continue d'exister en tant que table DynamoDB standard avec les mêmes données et paramètres. Ces autorisations s'appliquent à la fois aux tables globales de cohérence éventuelle multirégionale (MREC) et de cohérence forte entre régions (MRSC). 
+ Pour supprimer des répliques d'une table globale à l'aide de l'[https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API, vous devez disposer de l'autorisation suivante sur la ressource de table de la région à partir de laquelle vous effectuez l'appel d'API :
  + `dynamodb:UpdateTable`
+ Vous devez disposer des autorisations suivantes sur la ressource de table dans chaque région dans laquelle vous supprimez une réplique :
  + `dynamodb:DeleteTable`
  + `dynamodb:DeleteTableReplica`

#### Autorisations supplémentaires pour les tables globales MRSC utilisant un témoin
<a name="globaltables-delete-iam-witness"></a>

Pour supprimer une table globale multirégionale à forte cohérence (MRSC) avec un témoin, vous devez disposer de l'autorisation suivante sur la ressource de table dans toutes les régions participantes (y compris les régions répliques et la région témoin) :
+ `dynamodb:DeleteGlobalTableWitness`

#### Exemples de politiques IAM pour supprimer les répliques d'une table globale
<a name="globaltables-delete-iam-example"></a>

##### Suppression de répliques de tables globales
<a name="globaltables-delete-replicas-iam-example"></a>

Cette politique basée sur l'identité vous permet de supprimer une table globale DynamoDB nommée « utilisateurs » et ses répliques dans trois régions :

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

****  

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

------

##### Supprimer une table globale MRSC avec un témoin
<a name="globaltables-delete-witness-iam-example"></a>

Cette politique basée sur l'identité vous permet de supprimer la réplique et le témoin d'une table globale MRSC nommée « users » :

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

****  

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

------

## Utilisation des tables globales AWS KMS
<a name="globaltables-kms"></a>

Comme toutes les tables DynamoDB, les répliques de tables globales chiffrent toujours les données au repos à l'aide de clés de chiffrement stockées AWS dans Key Management Service ().AWS KMS

Tous les réplicas d’une table globale doivent être configurés avec le même type de clé KMS (clé détenue par AWS , clé gérée par AWS ou clé gérée par le client).

**Important**  
DynamoDB a besoin d’accéder à la clé de chiffrement du réplica pour supprimer un réplica. Si vous souhaitez désactiver ou supprimer une clé gérée par le client utilisée pour chiffrer un réplica parce que vous supprimez ce réplica, vous devez d’abord supprimer le réplica, attendre que le statut de la table de l’une des répliques restantes soit changé en `ACTIVE`, puis désactiver ou supprimer la clé.

Dans le cas d’une table globale configurée pour une cohérence finale multirégionale (MREC), si vous désactivez ou révoquez l’accès de DynamoDB à une clé gérée par le client utilisée pour chiffrer un réplica, la réplication vers et depuis le réplica s’arrêtera et le statut du réplica passera à `INACCESSIBLE_ENCRYPTION_CREDENTIALS`. Si un réplica d’une table globale MREC reste dans l’état `INACCESSIBLE_ENCRYPTION_CREDENTIALS` pendant plus de 20 heures, le réplica est converti de manière irréversible en une table DynamoDB à région unique.

Dans le cas d’une table globale configurée pour une forte cohérence multirégionale (MREC), si vous désactivez ou révoquez l’accès de DynamoDB à une clé gérée par le client utilisée pour chiffrer un réplica, la réplication vers et depuis le réplica s’arrêtera, les tentatives d’exécution d’écriture ou de lectures fortement cohérentes renverront une erreur, et l’état du réplica passera à `INACCESSIBLE_ENCRYPTION_CREDENTIALS`. Si un réplica d’une table globale MRSC reste dans l’état `INACCESSIBLE_ENCRYPTION_CREDENTIALS` pendant plus de sept jours, en fonction des autorisations spécifiques révoquées, le réplica sera archivé ou deviendra définitivement inaccessible.

# Tableaux globaux multicomptes DynamoDB
<a name="globaltables-MultiAccount"></a>

Les tables globales multicomptes répliquent automatiquement les données de vos tables DynamoDB sur plusieurs AWS régions et plusieurs AWS comptes afin d'améliorer la résilience, d'isoler les charges de travail au niveau du compte et d'appliquer des contrôles de sécurité et de gouvernance distincts. Chaque table de réplication réside dans un AWS compte distinct, ce qui permet d'isoler les défaillances au niveau de la région et du compte. Vous pouvez également aligner les répliques sur votre structure AWS organisationnelle. Les tables globales multi-comptes offrent des avantages supplémentaires en termes d'isolation, de gouvernance et de sécurité par rapport aux tables globales pour comptes identiques.

Les tables globales multi-comptes offrent les avantages suivants :
+ Répliquez automatiquement les données des tables DynamoDB sur les comptes et les régions de votre choix AWS 
+ Améliorez la sécurité et la gouvernance en répliquant les données entre les comptes avec des politiques, des garde-fous et des limites de conformité distincts
+ Améliorez la résilience opérationnelle et l'isolation des défaillances au niveau des comptes en plaçant les répliques dans des comptes distincts AWS 
+ Alignez les charges de travail par unité commerciale ou par propriétaire lors de l'utilisation d'une stratégie multi-comptes
+ Simplifiez l'attribution des coûts en facturant chaque réplique à son AWS compte respectif

Pour plus d'informations, consultez la section [Avantages liés à l'utilisation de plusieurs AWS comptes](https://docs.aws.amazon.com/whitepapers/latest/organizing-your-aws-environment/benefits-of-using-multiple-aws-accounts.html). Si vos charges de travail ne nécessitent pas de réplication multicompte ou si vous souhaitez simplifier la gestion des répliques avec des remplacements locaux, vous pouvez continuer à utiliser des tables globales pour les mêmes comptes.

Vous pouvez configurer des tables globales multi-comptes avec[Cohérence à terme multirégionale (MREC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrec). Les tables globales configurées pour [Forte cohérence multirégionale (MRSC)](V2globaltables_HowItWorks.md#V2globaltables_HowItWorks.consistency-modes.mrsc) ne prennent pas en charge le modèle multi-comptes.

**Topics**
+ [Fonctionnement des tables globales DynamoDB](V2globaltables_MA_HowItWorks.md)
+ [Tutoriels : Création de tables globales multi-comptes](V2globaltables_MA.tutorial.md)
+ [Sécurité des tables globales DynamoDB](globaltables_MA_security.md)

# Fonctionnement des tables globales DynamoDB
<a name="V2globaltables_MA_HowItWorks"></a>

Les tables globales multicomptes étendent les fonctionnalités multirégionales et multiactives des tables globales DynamoDB entièrement gérées, sans serveur, à plusieurs régions et à plusieurs comptes. AWS Les tables globales multi-comptes répliquent les données entre AWS les régions et les comptes, fournissant les mêmes fonctionnalités active-active que les tables globales pour les mêmes comptes. Lorsque vous écrivez sur une réplique, DynamoDB réplique les données sur toutes les autres répliques.

Les principales différences par rapport aux tables globales pour comptes identiques sont les suivantes :
+ La réplication multicompte est prise en charge pour les tables globales de cohérence éventuelle multirégionale (MREC).
+ Vous ne pouvez ajouter des répliques qu'en commençant par une table à région unique. La conversion d'une table globale existante pour un même compte en une configuration multi-comptes n'est pas prise en charge. Pour effectuer la migration, vous devez supprimer les répliques existantes pour revenir à une table à région unique avant de créer une nouvelle table globale multi-comptes.
+ Chaque réplique doit résider dans un AWS compte distinct. Pour une table globale multi-comptes comportant *N* répliques, vous devez disposer de *N* comptes.
+ Les tables globales multicomptes utilisent par défaut des paramètres de table unifiés pour toutes les répliques. Toutes les répliques partagent automatiquement la même configuration (comme le mode débit et le TTL) et, contrairement aux tables globales de même compte, ces paramètres ne peuvent pas être remplacés par réplique.
+ Les clients doivent fournir des autorisations de réplication au principal du service de tables globales DynamoDB dans leurs politiques de ressources.

Les tables globales à comptes multiples utilisent la même technologie de réplication sous-jacente que les tables globales à compte identique. Les paramètres de table sont répliqués automatiquement sur toutes les répliques régionales, et les clients ne peuvent pas modifier ou personnaliser les paramètres par réplique. Cela garantit une configuration cohérente et un comportement prévisible sur plusieurs AWS comptes participant à la même table globale.

Les paramètres des tables globales DynamoDB définissent le comportement d'une table et la manière dont les données sont répliquées entre les régions. Ces paramètres sont configurés via le APIs plan de contrôle DynamoDB lors de la création de la table ou lors de l'ajout d'une nouvelle réplique régionale.

Lors de la création d'un tableau global multi-comptes, les clients doivent le définir `GlobalTableSettingsReplicationMode = ENABLED` pour chaque réplique régionale. Cela garantit que les modifications de configuration apportées dans une région se propagent automatiquement à toutes les autres régions qui participent au tableau global.

Vous pouvez activer la réplication des paramètres après la création de la table. Cela prend en charge le scénario dans lequel une table est initialement créée en tant que table régionale puis mise à niveau vers une table globale multi-comptes.

**Réglages synchronisés**

Les paramètres de table suivants sont toujours synchronisés entre toutes les répliques d'une table globale multi-comptes :

**Note**  
Contrairement aux tables globales à comptes identiques, les tables globales à comptes multiples n'autorisent pas le remplacement de ces paramètres par région. La seule exception est que les remplacements pour les politiques d'auto-scaling en lecture (tables GSIs et) sont autorisés car il s'agit de ressources externes distinctes.
+ Mode capacité (capacité provisionnée ou à la demande)
+ Capacité de lecture et d'écriture allouée aux tables
+ Mise à l'échelle automatique en lecture et en écriture de tableaux
+ Définition de l'index secondaire local (LSI)
+ Définition de l’index secondaire global (GSI)
+ Capacité de lecture et d'écriture allouée par GSI
+ Mise à l'échelle automatique de lecture et d'écriture GSI
+ Définition des flux en mode MREC
+ Durée de vie (TTL)
+ Débit chaud
+ Débit de lecture et d'écriture maximal à la demande

**Réglages non synchronisés**

Les paramètres suivants ne sont pas synchronisés entre les répliques et doivent être configurés indépendamment pour chaque table de répliques dans chaque région.
+ Classe de table
+ Type de chiffrement côté serveur (SSE)
+ Point-in-time Récupération
+ ID de clé KMS de chiffrement côté serveur (SSE)
+ Protection contre la suppression
+ Kinesis Data Streams (KDSD)
+ Étiquettes
+ Stratégie de ressources
+ Tableau Cloudwatch-Contributor Insights (CCI)
+ Informations sur les contributeurs de GSI Cloudwatch (CCI)

## Contrôle
<a name="V2globaltables_MA_HowItWorks.monitoring"></a>

Les tables globales configurées pour la cohérence finale multirégionale (MREC) publient la [`ReplicationLatency`](metrics-dimensions.md#ReplicationLatency)métrique dans. CloudWatch Cette métrique suit le temps écoulé entre le moment où un élément est écrit dans une table de réplicas et celui où il apparaît dans un autre réplica dans la table globale. `ReplicationLatency` est exprimé en millisecondes et est émis pour chaque paire région source/région de destination dans une table globale.

Les `ReplicationLatency` valeurs typiques dépendent de la distance entre les AWS régions que vous avez choisies, ainsi que d'autres variables telles que le type de charge de travail et le débit. Par exemple, un réplica source située dans la région USA Ouest (Californie du Nord) (us-west-1) a une `ReplicationLatency` inférieure dans la région USA Ouest (Oregon) (us-west-2) par rapport à la région Afrique (Le Cap) (af-south-1).

Une valeur croissante pour `ReplicationLatency` peut indiquer que les mises à jour d’un réplica ne sont pas propagées vers d’autres tables de réplica dans un délai raisonnable. Dans ce cas, vous pouvez rediriger temporairement les activités de lecture et d'écriture de votre application vers une autre AWS région.

**Gestion des problèmes de latence de réplication dans les tables globales multi-comptes**

Si `ReplicationLatency` le délai dépasse 3 heures en raison de problèmes provoqués par le client sur une table de réplication, DynamoDB envoie une notification demandant au client de résoudre le problème sous-jacent. Les problèmes courants provoqués par le client susceptibles d'empêcher la réplication sont notamment les suivants :
+ Suppression des autorisations requises de la politique de ressources de la table de réplication
+ Se désinscrire d'une AWS région hébergeant une réplique de la table globale multi-comptes
+ Refuser les autorisations relatives AWS à la clé KMS de la table requises pour déchiffrer les données

DynamoDB envoie une notification initiale dans les 3 heures suivant une latence de réplication élevée, suivie d'une seconde notification après 20 heures si le problème n'est toujours pas résolu. Si le problème n'est pas résolu dans le délai imparti, DynamoDB dissociera automatiquement le réplica de la table globale. La réplique affectée sera ensuite convertie en table régionale.

# Tutoriels : Création de tables globales multi-comptes
<a name="V2globaltables_MA.tutorial"></a>

Cette section fournit des step-by-step instructions pour créer des tables globales DynamoDB qui s'étendent sur plusieurs comptes. AWS 

## Création d'une table globale multi-comptes à l'aide de la console DynamoDB
<a name="create-ma-gt-console"></a>

Procédez comme suit pour créer une table globale multi-comptes à l'aide du AWS Management Console. L'exemple suivant crée une table globale avec des répliques de tables aux États-Unis d'Amérique.

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse correspondant [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)au premier compte (par exemple). *111122223333*

1. Pour cet exemple, choisissez **USA Est (Ohio)** dans le sélecteur de région dans la barre de navigation.

1. Dans le volet de navigation sur le côté gauche de la console, choisissez **Tables**.

1. Choisissez **Créer une table**.

1. Sur la page **Créer un tableau** :

   1. Sous **Nom du tableau**, saisissez **MusicTable**.

   1. Pour **Clé de partition**, saisissez **Artist**.

   1. Pour **Clé de tri**, entrez **SongTitle**.

   1. Conservez les autres paramètres par défaut et choisissez **Créer une table**.

1. Ajoutez la politique de ressources suivante au tableau

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

****  

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

------

1. La nouvelle table sert de première table de réplica dans une nouvelle table globale. Il s’agit du prototype pour d’autres tables de réplica que vous ajouterez ultérieurement.

1. Attendez que la table soit **active**. Pour la table nouvellement créée, dans l'onglet **Tableaux globaux**, accédez à **Réglages > Réplication**, puis cliquez sur **Activer**.

1. Déconnectez-vous de ce compte (*111122223333*ici).

1. Connectez-vous au AWS Management Console et ouvrez-le sur la console [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)DynamoDB pour le deuxième compte (par exemple). *444455556666*

1. Pour cet exemple, choisissez **USA East (Virginie du Nord)** dans le sélecteur de région de la barre de navigation.

1. La console vérifie qu’il n’existe pas de table du même nom dans la région sélectionnée. (Si une table du même nom existe, vous devez la supprimer avant de pouvoir créer une nouvelle table de réplicas dans cette région.)

1. Dans le menu déroulant situé près de **Créer une table**, choisissez **Créer depuis un autre compte**

1. Dans le **tableau Créer depuis un autre compte** :

   1. Ajoutez **arn:aws:dynamodb:us-east-2:*111122223333*:table/MusicTable** en tant qu'arn de table pour la table source.

   1. Dans la **table de réplication ARNs**, ajoutez à nouveau l'ARN de la table source**arn:aws:dynamodb:us-east-2:*111122223333*:table/MusicTable**. Si plusieurs répliques existent déjà dans le cadre d'une table globale multi-comptes, vous devez ajouter chaque réplique existante à l' ReplicaTableARN.

   1. Conservez les autres paramètres par défaut et choisissez **Soumettre**.

1. L'onglet **Tables globales** de la table Music (et de toute autre table répliquée) indique que la table a été répliquée dans plusieurs régions.

1. Pour tester la réplication :

   1. Vous pouvez utiliser n'importe quelle région dans laquelle une réplique existe pour cette table

   1. Choisissez **Explorer les éléments de la table**.

   1. Choisissez **Créer un élément**.

   1. Entrez **item\$11** pour **Artiste** et **Song Value 1** pour **SongTitle**.

   1. Choisissez **Créer un élément**.

   1. Vérifiez la réplication en passant aux autres régions :

   1. Vérifiez que le tableau Musique contient l’élément que vous avez créé.

## Créez un tableau global multi-comptes à l'aide du AWS CLI
<a name="ma-gt-cli"></a>

Les exemples suivants montrent comment créer une table globale multi-comptes à l'aide du AWS CLI. Ces exemples illustrent le flux de travail complet pour configurer la réplication entre comptes.

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

Utilisez les AWS CLI commandes suivantes pour créer une table globale multi-comptes avec réplication entre comptes.

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

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

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

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


# Step 3: Creating replica table in account 444455556666

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

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

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

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

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

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

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

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

------

# Sécurité des tables globales DynamoDB
<a name="globaltables_MA_security"></a>

Les répliques de tables globales étant des tables DynamoDB, vous utilisez les mêmes méthodes pour contrôler l'accès aux répliques que pour les tables à région unique, Gestion des identités et des accès AWS y compris les politiques d'identité (IAM) et les politiques basées sur les ressources. Cette rubrique explique comment sécuriser les tables globales multicomptes DynamoDB à l'aide des autorisations IAM et du chiffrement (). AWS Key Management Service AWS KMS Vous découvrirez les politiques basées sur les ressources et les rôles liés aux services (SLR) qui permettent la réplication entre comptes entre régions et l'auto-scaling, ainsi que les autorisations IAM nécessaires pour créer, mettre à jour et supprimer des tables globales, pour des tables de cohérence finale multirégionales (MREC). Vous découvrirez également les clés de AWS KMS chiffrement permettant de gérer la réplication entre régions en toute sécurité.

Il fournit des informations détaillées sur les politiques basées sur les ressources et les autorisations requises pour établir une réplication de tables entre comptes et entre régions. La compréhension de ce modèle de sécurité est essentielle pour les clients qui ont besoin de mettre en œuvre des solutions sécurisées de réplication de données entre comptes.

## Autorisation principale du service pour la réplication
<a name="globaltables_MA_service_principal"></a>

Les tables globales multicomptes de DynamoDB utilisent une approche d'autorisation distincte, car la réplication s'effectue au-delà des limites des comptes. Cela se fait à l'aide du principal du service de réplication de DynamoDB :. `replication.dynamodb.amazonaws.com` Chaque compte participant doit explicitement autoriser ce principal dans la politique de ressources de la table de répliques, en lui accordant des autorisations qui peuvent être limitées à des répliques spécifiques en fonction des conditions du contexte source sur des clés telles que `aws:SourceAccount``aws:SourceArn`, etc. — voir les [clés de condition AWS globales](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html) pour plus de détails. Les autorisations sont bidirectionnelles, ce qui signifie que toutes les répliques doivent s'accorder explicitement des autorisations les unes aux autres avant que la réplication puisse être établie sur une paire de répliques en particulier.

Les autorisations principales de service suivantes sont essentielles pour la réplication entre comptes :
+ `dynamodb:ReadDataForReplication`permet de lire des données à des fins de réplication. Cette autorisation permet de lire les modifications apportées à une réplique et de les propager à d'autres répliques.
+ `dynamodb:WriteDataForReplication`permet d'écrire des données répliquées dans les tables de destination. Cette autorisation permet de synchroniser les modifications entre toutes les répliques de la table globale.
+ `dynamodb:ReplicateSettings`permet de synchroniser les paramètres des tables entre les répliques, fournissant ainsi une configuration cohérente entre toutes les tables participantes.

Chaque réplique doit accorder les autorisations ci-dessus à toutes les autres répliques et à elle-même, c'est-à-dire que les conditions du contexte source doivent inclure l'ensemble complet des répliques composant la table globale. Ces autorisations sont vérifiées pour chaque nouvelle réplique lorsqu'elle est ajoutée à une table globale multi-comptes. Cela permet de vérifier que les opérations de réplication sont effectuées uniquement par le service DynamoDB autorisé et uniquement entre les tables prévues.

## Rôles liés à un service pour les tables globales multi-comptes
<a name="globaltables_MA_service_linked_roles"></a>

Les tables globales multicomptes DynamoDB répliquent les paramètres de toutes les répliques afin que chaque réplique soit configurée de manière identique avec un débit constant et offre une expérience de basculement fluide. La réplication des paramètres est contrôlée par l'`ReplicateSettings`autorisation accordée au principal du service, mais nous nous appuyons également sur les rôles liés au service (SLRs) pour gérer certaines fonctionnalités de réplication entre comptes et entre régions et d'auto-scaling. Ces rôles ne sont définis qu'une seule fois par AWS compte. Une fois créés, les mêmes rôles sont utilisés pour toutes les tables globales de votre compte. Pour plus d'informations sur les rôles liés à un service, consultez la section [Utilisation des rôles liés à un service dans le guide de l'utilisateur](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create-service-linked-role.html) IAM.

### Rôle lié au service de gestion des paramètres
<a name="globaltables_MA_settings_management_slr"></a>

Amazon DynamoDB crée automatiquement le rôle lié AWSService RoleForDynamo DBGlobal TableSettingsManagement au service (SLR) lorsque vous créez votre première réplique de table globale multi-comptes dans le compte. Ce rôle gère pour vous la réplication des paramètres entre comptes et entre régions.

Lorsque vous appliquez des politiques basées sur les ressources aux répliques, assurez-vous de ne refuser aucune des autorisations définies dans le `AWSServiceRoleForDynamoDBGlobalTableSettingsManagement` SLR principal, car cela pourrait interférer avec la gestion des paramètres et entraver la réplication si le débit ne correspond pas entre les répliques ou. GSIs Si vous refusez les autorisations SLR requises, la réplication vers et depuis les répliques concernées peut s'arrêter et le statut de la table de répliques passera à. `REPLICATION_NOT_AUTHORIZED` Pour les tables globales multicomptes, si une réplique reste dans l'`REPLICATION_NOT_AUTHORIZED`état pendant plus de 20 heures, elle est convertie de manière irréversible en table DynamoDB à région unique. Le SLR dispose des autorisations suivantes :
+ `application-autoscaling:DeleteScalingPolicy`
+ `application-autoscaling:DescribeScalableTargets`
+ `application-autoscaling:DescribeScalingPolicies`
+ `application-autoscaling:DeregisterScalableTarget`
+ `application-autoscaling:PutScalingPolicy`
+ `application-autoscaling:RegisterScalableTarget`

### Rôle lié à un service pour l’autoscaling
<a name="globaltables_MA_autoscaling_slr"></a>

Lors de la configuration d'une table globale pour le mode capacité allouée, le dimensionnement automatique doit être configuré pour la table globale. DynamoDB Auto Scaling AWS utilise le service Application Auto Scaling pour ajuster dynamiquement la capacité de débit allouée sur vos répliques de tables globales. Le service Application Auto Scaling crée un rôle lié au service (SLR) nommé. [AWSServiceRoleForApplicationAutoScaling\$1DynamoDBTable](https://docs.aws.amazon.com/autoscaling/application/userguide/application-auto-scaling-service-linked-roles.html) Ce rôle lié à un service est automatiquement créé dans votre AWS compte lorsque vous configurez pour la première fois le dimensionnement automatique pour une table DynamoDB. Il permet à Application Auto Scaling de gérer la capacité des tables provisionnées et de créer des CloudWatch alarmes.

Lorsque vous appliquez des politiques basées sur les ressources à des répliques, vérifiez que vous ne refusez aucune autorisation définie dans la [AWSApplicationAutoscalingDynamoDBTablepolitique](https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSApplicationAutoscalingDynamoDBTablePolicy.html) au principal Application Auto Scaling SLR, car cela interromprait la fonctionnalité d'auto-scaling.

## Comment les tables globales utilisent AWS IAM
<a name="globaltables_MA_iam"></a>

Les sections suivantes décrivent les autorisations requises pour les différentes opérations sur les tables globales et fournissent des exemples de politiques pour vous aider à configurer l'accès approprié pour vos utilisateurs et applications.

**Note**  
Toutes les autorisations décrites doivent être appliquées à l'ARN de la ressource de table spécifique dans la ou les régions concernées. L'ARN de la ressource de table suit le format `arn:aws:dynamodb:region:account-id:table/table-name` dans lequel vous devez spécifier les valeurs réelles de votre région, de votre identifiant de compte et du nom de la table.

Les step-by-step sujets que nous abordons dans les sections ci-dessous sont les suivants :
+ Création de tables globales multi-comptes et ajout de répliques
+ Mettre à jour un tableau global multi-comptes
+ Supprimer des tables globales et supprimer des répliques

### Création de tables globales et ajout de répliques
<a name="globaltables_MA_creating"></a>

#### Autorisations pour créer des tables globales
<a name="globaltables_MA_creating_permissions"></a>

Lorsqu'une nouvelle réplique est ajoutée à une table régionale pour former une table globale multi-comptes ou à une table globale multi-comptes existante, le principal IAM qui exécute l'action doit être autorisé par tous les membres existants. Tous les membres existants doivent donner l'autorisation suivante dans leur politique de table pour que l'ajout de répliques réussisse :
+ `dynamodb:AssociateTableReplica`- Cette autorisation permet de joindre des tables dans une configuration de table globale. Il s'agit de l'autorisation fondamentale qui permet l'établissement initial de la relation de réplication.

Ce contrôle précis permet uniquement aux comptes autorisés de participer à la configuration globale du tableau.

#### Exemples de politiques IAM pour créer des tables globales
<a name="globaltables_MA_creating_examples"></a>

##### Exemples de politiques IAM pour une configuration à 2 répliques
<a name="globaltables_MA_2replica_example"></a>

La configuration des tables globales multi-comptes suit un flux d'autorisation spécifique qui assure une réplication sécurisée. Voyons comment cela fonctionne dans la pratique en passant en revue un scénario pratique dans lequel un client souhaite établir une table globale avec deux répliques. La première réplique (réplicAA) se trouve dans le compte A dans la région ap-east-1, tandis que la seconde réplique (réplicAB) se trouve dans le compte B dans la région eu-south-1.
+ Dans le compte source (compte A), le processus commence par la création de la table de réplication principale. L'administrateur du compte doit associer à ce tableau une politique basée sur les ressources qui accorde explicitement les autorisations nécessaires au compte de destination (compte B) pour effectuer l'association. Cette politique autorise également le service de réplication DynamoDB à effectuer des actions de réplication essentielles.
+ Le compte de destination (compte B) suit un processus similaire en joignant une politique basée sur les ressources correspondante lors de la création de la réplique et en référençant l'ARN de la table source à utiliser pour créer la réplique. Cette politique reflète les autorisations accordées par le compte A, créant ainsi une relation bidirectionnelle de confiance. Avant d'établir la réplication, DynamoDB valide ces autorisations entre comptes afin de vérifier que les autorisations appropriées sont en place.

Pour établir cette configuration, procédez comme suit :
+ L'administrateur du compte A doit d'abord associer la politique basée sur les ressources à ReplicAA. Cette politique accorde explicitement les autorisations nécessaires au compte B et au service de réplication DynamoDB.
+ De même, l'administrateur du compte B doit associer une politique correspondante à Replicab, avec des références de compte inversées pour accorder les autorisations correspondantes au compte A, lors de l'appel de création de table pour créer une réplique B référençant la réplique A comme table source.

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

****  

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

------

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

****  

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

------

##### Exemple de politiques IAM pour une configuration à 3 répliques
<a name="globaltables_MA_3replica_example"></a>

Dans cette configuration, nous avons 3 répliques Replica A, Replicab et ReplicAC dans le compte A, le compte B et le compte C, respectivement. La réplique A est la première réplique, qui commence sous la forme d'une table régionale, puis ReplicAB et ReplicAC y sont ajoutés.
+ L'administrateur du compte A doit d'abord associer la politique basée sur les ressources à ReplicAA pour permettre la réplication avec tous les membres et autoriser les principaux IAM du compte B et du compte C à ajouter des répliques.

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

****  

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

------
+ L'administrateur du compte B doit ajouter une réplique (réplique B) pointant vers la réplique A comme source. La réplique B applique la politique suivante autorisant la réplication entre tous les membres et autorisant le compte C à ajouter une réplique :

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

****  

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

------
+ Enfin, l'administrateur du compte C crée une réplique avec la politique suivante autorisant les autorisations de réplication entre tous les membres. La politique n'autorise pas l'ajout de répliques supplémentaires.

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

****  

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

------

### Mettre à jour un tableau global multi-comptes
<a name="globaltables_MA_updating"></a>

Pour modifier les paramètres de réplication d'une table globale existante à l'aide de l' UpdateTable API, vous devez disposer de l'autorisation suivante sur la ressource de table dans la région dans laquelle vous effectuez l'appel d'API : `dynamodb:UpdateTable`

Vous pouvez également mettre à jour d'autres configurations de table globales, telles que les politiques de dimensionnement automatique et les paramètres Time to Live. Les autorisations suivantes sont requises pour ces opérations de mise à jour supplémentaires :

Pour mettre à jour les paramètres Time to Live avec l'`UpdateTimeToLive`API, vous devez disposer de l'autorisation suivante sur la ressource de table dans toutes les régions contenant des répliques : `dynamodb:UpdateTimeToLive`

Pour mettre à jour une politique de dimensionnement automatique des répliques avec l'`UpdateTableReplicaAutoScaling`API, vous devez disposer des autorisations suivantes sur la ressource de table dans toutes les régions contenant des répliques :
+ `application-autoscaling:DeleteScalingPolicy`
+ `application-autoscaling:DeleteScheduledAction`
+ `application-autoscaling:DeregisterScalableTarget`
+ `application-autoscaling:DescribeScalableTargets`
+ `application-autoscaling:DescribeScalingActivities`
+ `application-autoscaling:DescribeScalingPolicies`
+ `application-autoscaling:DescribeScheduledActions`
+ `application-autoscaling:PutScalingPolicy`
+ `application-autoscaling:PutScheduledAction`
+ `application-autoscaling:RegisterScalableTarget`

**Note**  
Vous devez fournir des `dynamodb:ReplicateSettings` autorisations pour toutes les régions et tous les comptes de réplication pour que la table de mise à jour réussisse. Si aucune réplique ne fournit l'autorisation de répliquer les paramètres vers une réplique de la table globale multicompte, toutes les opérations de mise à jour sur toutes les répliques échoueront `AccessDeniedException` jusqu'à ce que les autorisations soient corrigées.

### Supprimer des tables globales et supprimer des répliques
<a name="globaltables_MA_deleting"></a>

Pour supprimer une table globale, vous devez supprimer toutes les répliques. Contrairement à la table globale de même compte, vous ne pouvez pas l'utiliser `UpdateTable` pour supprimer une réplique de table dans une région distante et chaque réplique doit être supprimée via l'`DeleteTable`API depuis le compte qui la contrôle.

#### Autorisations pour supprimer des tables globales et supprimer des répliques
<a name="globaltables_MA_deleting_permissions"></a>

Les autorisations suivantes sont requises à la fois pour supprimer des répliques individuelles et pour supprimer complètement des tables globales. La suppression d'une configuration de table globale supprime uniquement la relation de réplication entre les tables de différentes régions. Cela ne supprime pas la table DynamoDB sous-jacente dans la dernière région restante. La table de la dernière région continue d'exister en tant que table DynamoDB standard avec les mêmes données et paramètres.

Vous devez disposer des autorisations suivantes sur la ressource de table dans chaque région dans laquelle vous supprimez une réplique :
+ `dynamodb:DeleteTable`
+ `dynamodb:DeleteTableReplica`

## Utilisation des tables globales AWS KMS
<a name="globaltables_MA_kms"></a>

Comme toutes les tables DynamoDB, les répliques de tables globales chiffrent toujours les données au repos à l'aide de clés de chiffrement stockées AWS dans Key Management Service ().AWS KMS

**Note**  
Contrairement à une table globale à comptes identiques, les différentes répliques d'une table globale à comptes multiples peuvent être configurées avec un type de AWS KMS clé différent (cléAWS détenue ou clé gérée par le client). Les tables globales multicomptes ne prennent pas en charge les clés AWS gérées.

Les tables globales multicomptes utilisées CMKs nécessitent que la politique des clés de chaque réplique donne au principal du service de réplication DynamoDB `replication.dynamodb.amazonaws.com` () l'autorisation d'accéder à la clé pour la réplication et la gestion des paramètres. Les autorisations suivantes sont requises :
+ `kms:Decrypt`
+ `kms:ReEncrypt*`
+ `kms:GenerateDataKey*`
+ `kms:DescribeKey`

**Important **

DynamoDB a besoin d’accéder à la clé de chiffrement du réplica pour supprimer un réplica. Si vous souhaitez désactiver ou supprimer une clé gérée par le client utilisée pour chiffrer une réplique parce que vous supprimez la réplique, vous devez d'abord supprimer la réplique, attendre que la table soit supprimée du groupe de réplication en appelant describe dans l'une des autres répliques, puis désactiver ou supprimer la clé.

Si vous désactivez ou révoquez l'accès de DynamoDB à une clé gérée par le client utilisée pour chiffrer une réplique, la réplication vers et depuis la réplique s'arrête et le statut de la réplique passe à. `INACCESSIBLE_ENCRYPTION_CREDENTIALS` Si un réplica reste dans `INACCESSIBLE_ENCRYPTION_CREDENTIALS` cet état pendant plus de 20 heures, il est converti de manière irréversible en une table DynamoDB à région unique.

### Exemple AWS KMS de politique
<a name="globaltables_MA_kms_example"></a>

La AWS KMS politique permet à DynamoDB d'accéder aux AWS KMS deux clés pour la réplication entre les répliques A et B. Les clés associées à AWS KMS la réplique DynamoDB dans chaque compte doivent être mises à jour conformément à la politique suivante :

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

****  

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

------

# Présentation de la facturation Amazon DynamoDB pour les tables globales
<a name="global-tables-billing"></a>

Ce guide décrit le fonctionnement de la facturation DynamoDB pour les tables globales, en identifiant les composants qui contribuent au coût des tables globales, y compris un exemple pratique. 

Les [tables globales Amazon DynamoDB](GlobalTables.md) sont une base de données entièrement gérée, sans serveur, multirégionale et multiactive. Les tables globales sont conçues pour une [disponibilité de 99,999 %](https://aws.amazon.com/dynamodb/sla/), offrant ainsi une résilience accrue des applications et une meilleure continuité des activités. Les tables globales répliquent automatiquement vos tables DynamoDB dans les régions de votre choix afin que vous puissiez obtenir AWS des performances de lecture et d'écriture rapides et locales. 

## Comment ça marche
<a name="global-tables-billing-how-it-works"></a>

Le modèle de facturation des tables globales est différent de celui des tables DynamoDB à région unique. Les opérations d’écriture pour les tables DynamoDB à région unique sont facturées selon les unités suivantes :
+ Unités de demande d'écriture (WRUs) pour le mode capacité à la demande, où une WRU est facturée pour chaque écriture jusqu'à 1 Ko
+ Unités de capacité d'écriture (WCUs) pour le mode de capacité provisionnée, où une WCU fournit une écriture par seconde pour un maximum de 1 Ko

Lorsque vous créez une table globale en ajoutant une table de réplicas à une table à région unique existante, cette table à région unique devient une table de réplicas, ce qui signifie que les unités utilisées pour facturer les écritures dans la table changent également. Les opérations d’écriture pour les tables de réplicas sont facturées selon les unités suivantes : 
+ Unités de demande d'écriture répliquées (rWRUs) pour le mode capacité à la demande, où une RWru par table de réplication est facturée pour chaque écriture jusqu'à 1 Ko
+ Unités de capacité d'écriture répliquées (rWCUs) pour le mode de capacité provisionnée, où une WCU par table de réplication fournit une écriture par seconde pour un maximum de 1 Ko

Les mises à jour des index secondaires globaux (GSIs) sont facturées en utilisant les mêmes unités que les tables DynamoDB à région unique, même si la table de base du GSI est une table de réplique. Les opérations de mise à jour pour GSIs sont facturées selon les unités suivantes :
+ Unités de demande d'écriture (WRUs) pour le mode capacité à la demande, où une WRU est facturée pour chaque écriture jusqu'à 1 Ko
+ Unités de capacité d'écriture (WCUs) pour le mode de capacité provisionnée, où une WCU fournit une écriture par seconde pour un maximum de 1 Ko

Le prix des unités d'écriture répliquées (r WCUs et rWRUs) est le même que celui des unités d'écriture à région unique (WCUs et WRUs). Des frais de transfert de données entre régions s’appliquent aux tables globales, car les données sont répliquées dans toutes les régions. Des frais d’écriture répliquée (rWCU ou rWRU) sont facturés dans chaque région contenant une table de réplicas pour la table globale.

Les opérations de lecture à partir de tables à région unique et de tables de réplicas utilisent les unités suivantes :
+ Unités de demande de lecture (RRUs) pour le mode de capacité à la demande, où une RRU est facturée pour chaque lecture hautement cohérente jusqu'à 4 Ko
+ Unités de capacité de lecture (RCUs) pour les tables provisionnées, où une RCU fournit une lecture très cohérente par seconde jusqu'à 4 Ko

## Modes de cohérence et facturation
<a name="global-tables-billing-consistency-modes"></a>

Les unités d'écriture répliquées (r WCUs et rWRUs) utilisées pour facturer les opérations d'écriture sont identiques pour les modes de cohérence forte multirégion (MRSC) et de cohérence finale multirégionale (MREC). Les tables globales utilisant le mode MRSC (Multi-region Strong Cohérence) configuré avec un témoin n'entraînent pas de coûts unitaires d'écriture répliqués (r WCUs et rWRUs), de coûts de stockage ou de transfert de données pour la réplication vers le témoin.

## Exemple de facturation des tables globales DynamoDB
<a name="global-tables-billing-example"></a>

Passons en revue un exemple de scénario de plusieurs jours pour voir comment fonctionne la facturation globale des demandes d’écriture de table dans la pratique (notez que cet exemple ne prend en compte que les demandes d’écriture et n’inclut pas les frais de restauration de tables et de transfert de données entre régions qui seraient encourus dans cet exemple) :

**Jour 1 - Table à région unique : vous disposez d’une table** DynamoDB à la demande à région unique nommée Table\$1A dans la région us-west-2. Vous écrivez 100 éléments de 1 Ko dans Table\$1A. Pour ces opérations d’écriture dans une seule région, 1 unité de demande d’écriture (WRU) vous est facturée par 1 Ko écrit. Vos frais pour le premier jour sont les suivants :
+ 100 WRUs dans la région us-west-2 pour les écritures à région unique

Nombre total d'unités demandées facturées le jour 1 : **100 WRUs**.

**Jour 2 - Création d’une table globale :** vous créez une table globale en ajoutant une réplica à Table\$1A dans la région us-east-2. Table\$1A est désormais une table globale avec deux tables de réplicas : un dans la région us-west-2 et l’autre dans la région us-east-2. Vous écrivez 150 éléments de 1 Ko dans la table de réplicas de la région us-west-2. Vos frais pour le deuxième jour sont les suivants :
+ 150 r WRUs dans la région us-west-2 pour les écritures répliquées
+ 150 r WRUs dans la région us-east-2 pour les écritures répliquées

Nombre total d'unités demandées facturées le jour 2 : **300 WRUs r.**

**Jour 3 - Ajout d’un index secondaire global : **Vous ajoutez un index secondaire global (GSI) à la table de réplicas de la région us-east-2 qui projette tous les attributs de la table de base (réplica). La table globale crée automatiquement pour vous le GSI sur la table de réplicas de la région us-west-2. Vous écrivez 200 nouveaux enregistrements de 1 Ko dans la table de réplicas de la région us-west-2. Vos frais pour le troisième jour sont les suivants :
+ • 200 r WRUs dans la région us-west-2 pour les écritures répliquées
+ • 200 WRUs dans la région us-west-2 pour les mises à jour du GSI
+ • 200 r WRUs dans la région us-east-2 pour les écritures répliquées
+ • 200 WRUs dans la région us-east-2 pour les mises à jour du GSI

Nombre total d'unités de demande d'écriture facturées le jour 3 : **400 WRUs et 400 WRUs r.**

Les frais unitaires d'écriture totaux pour les trois jours sont de 500 WRUs (100 WRU le jour 1 \$1 400 WRUs le jour 3) et de 700 r WRUs (300 r WRUs le jour 2 \$1 400 r WRUs le jour 3).

En résumé, les opérations d’écriture de tables de réplicas sont facturées en unités d’écriture répliquées dans toutes les régions qui contiennent une table de réplicas. Si vous avez des index secondaires globaux, des unités d'écriture vous sont facturées pour les mises à jour GSIs dans toutes les régions contenant un GSI (dans une table globale, il s'agit de toutes les régions contenant une table répliquée). 

# Versions des tables globales DynamoDB
<a name="V2globaltables_versions"></a>

Deux versions des tables globales DynamoDB sont disponibles : la version 2019.11.21 (actuelle) et la version 2017.11.29 (héritée). Nous recommandons d’utiliser la version 2019.11.21 (actuelle) des tables globales, car elle est plus facile à utiliser, est prise en charge dans un plus grand nombre de régions et coûte moins cher pour la plupart des charges de travail que la version 2017.11.29 (héritée).

## Détermination de la version d’une table globale
<a name="globaltables.DetermineVersion"></a>

### Déterminer la version à l'aide du AWS CLI
<a name="globaltables.CLI"></a>

#### Identification d’une réplica de table globale de la version 2019.11.21 (actuelle)
<a name="globaltables.CLI.current"></a>

Pour déterminer si une table est une réplica de table globale 2019.11.21 (actuelle), appelez la commande `describe-table` de la table. Si la sortie contient l’attribut `GlobalTableVersion` dont la valeur est « 2019.11.21 », la table est un réplica de table globale de la version 2019.11.21 (actuelle).

Exemple de commande CLI pour `describe-table` :

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

La sortie (abrégée) contient l’attribut `GlobalTableVersion` dont la valeur est « 2019.11.21 ». La table est donc un réplica de table globale de la version 2019.11.21 (actuelle).

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

#### Identification d’un réplica de table version 2017.11.29 (héritée)
<a name="globaltables.CLI.legacy"></a>

La version 2017.11.29 (héritée) des tables globales utilise un ensemble de commandes dédié pour la gestion globale des tables. Pour déterminer si une table est un réplica de tables globales version 2017.11.29 (actuelle), invoquez la commande `describe-global-table` pour la table. Si vous recevez une réponse positive, la table est un réplica de table globale de la version 2017.11.29 (héritée). Si la commande `describe-global-table` renvoie une erreur `GlobalTableNotFoundException`, la table n’est pas un réplica de la version 2017.11.29 (héritée).

Exemple de commande CLI pour `describe-global-table` :

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

La commande renvoie une réponse positive, de sorte que la table est un réplica de table globale de la version 2017.11.29 (héritée).

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

### Détermination de la version à l’aide de la console DynamoDB
<a name="globaltables.console"></a>

Pour identifier la version d’un réplica de table globale, effectuez les opérations suivantes :

1. [Ouvrez la console DynamoDB à la maison. https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/home)

1. Dans le volet de navigation sur le côté gauche de la console, choisissez **Tables**.

1. Choisissez la table dont vous souhaitez identifier la version des tables globales.

1. Choisissez l’onglet **Tables globales**.

   La section *Récapitulatif* affiche la version des tables globales utilisée.

## Différences de comportement entre les versions héritées et les versions actuelles
<a name="DiffLegacyVsCurrent"></a>

La liste suivante décrit les différences de comportement entre les versions héritées et actuelles des tables globales.
+ La version 2019.11.21 (actuelle) utilise moins de capacité d’écriture pour plusieurs opérations DynamoDB que la version 2017.11.29 (héritée), et est donc plus rentable pour la plupart des clients. Les différences de ces opérations DynamoDB sont les suivantes :
  + L'appel [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html)d'un élément de 1 Ko dans une région et sa réplication vers d'autres régions nécessitent 2 r WRUs par région pour le 29 novembre 2017 (ancien), mais seulement 1 RWru pour le 21 novembre 2019 (actuel).
  + L'invocation [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)d'un élément de 1 Ko nécessite 2 r WRUs dans la région source et 1 RWru par région de destination pour le 29 novembre 2017 (ancienne), mais un seul RWru pour les régions source et de destination pour le 21 novembre 2019 (actuel).
  + L'appel [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html)d'un élément de 1 Ko nécessite 1 RWru dans la région source et 2 r WRUs par région de destination pour le 29 novembre 2017 (ancien), mais un seul RWru pour la région source ou de destination pour le 21 novembre 2019 (actuel).

  Le tableau suivant montre la consommation rWRU des tables 2017.11.29 (ancienne) et 2019.11.21 (actuelle) pour un élément de 1 Ko dans deux régions.    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/V2globaltables_versions.html)
+ la version 2017.11.29 (Legacy) n'est disponible que dans la version 11. Régions AWS Cependant, la version 2019.11.21 (actuelle) est disponible dans toutes les Régions AWS.
+ Vous créez les tables globales de la version 2017.11.29 (Legacy) en créant d'abord un ensemble de tables régionales vides, puis en invoquant l'[CreateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateGlobalTable.html)API pour former la table globale. Vous créez des tables globales de la version 2019.11.21 (Current) en appelant l'[UpdateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html)API pour ajouter une réplique à une table régionale existante.
+ La version 2017.11.29 (héritée) vous oblige à vider tous les réplicas de la table avant d’ajouter un réplica dans une nouvelle région (y compris lors de la création). La version 2019.11.21 (actuelle) vous permet d’ajouter et de supprimer des réplicas dans les régions d’une table contenant déjà des données.
+ la version 2017.11.29 (Legacy) utilise l'ensemble de plans de contrôle dédié suivant APIs pour gérer les répliques :
  + [CreateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CreateGlobalTable.html)
  + [DescribeGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeGlobalTable.html)
  + [DescribeGlobalTableSettings](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeGlobalTableSettings.html)
  + [ListGlobalTables](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ListGlobalTables.html)
  + [UpdateGlobalTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateGlobalTable.html)
  + [UpdateGlobalTableSettings](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateGlobalTableSettings.html)

  la version 2019.11.21 (Current) utilise le [DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)et [UpdateTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateTable.html) APIs pour gérer les répliques.
+ la version 2017.11.29 (héritée) publie deux enregistrements DynamoDB Streams pour chaque écriture. La version 2019.11.21 (actuelle) ne publie qu’un seul enregistrement DynamoDB Streams pour chaque écriture.
+ La version 2017.11.29 (héritée) renseigne et met à jour les attributs `aws:rep:deleting`, `aws:rep:updateregion` et `aws:rep:updatetime`. La version 2019.11.21 (actuelle) ne renseigne ni ne met à jour ces attributs.
+ La version 2017.11.29 (héritée) ne synchronise pas les paramètres [Utilisation de la durée de vie (TTL) dans DynamoDB](TTL.md) entre les réplicas. La version 2019.11.21 (actuelle) synchronise les paramètres TTL entre les réplicas.
+ la version 2017.11.29 (héritée) ne réplique pas les suppressions TTL vers d’autres réplicas. La version 2019.11.21 (actuelle) réplique les suppressions TTL dans tous les réplicas.
+ La version 2017.11.29 (héritée) ne synchronise pas les paramètres d’[autoscaling](AutoScaling.md) entre les réplicas. La version 2019.11.21 (actuelle) synchronise les paramètres d’autoscaling entre les réplicas.
+ La version 2017.11.29 (héritée) ne synchronise pas les paramètres d’[index secondaires globaux (GSI)](GSI.md) entre les réplicas. La version 2019.11.21 (actuelle) synchronise les paramètres GSI entre les réplicas.
+ La version 2017.11.29 (héritée) ne synchronise pas les paramètres de [chiffrement au repos](encryption.usagenotes.md) entre les réplicas. La version 2019.11.21 (actuelle) synchronise les paramètres de chiffrement au repos entre les réplicas.
+ La version 2017.11.29 (héritée) publie la métrique `PendingReplicationCount`. La version 2019.11.21 (actuelle) ne publie pas cette métrique.

## Mise à niveau vers la version actuelle
<a name="upgrading-to-current-version"></a>

### Autorisations requises pour la mise à niveau des tables globales
<a name="V2globaltables_versions.Notes-permissions"></a>

Pour effectuer une mise à niveau vers la version 2019.11.21 (actuelle), vous devez disposer d’autorisations `dynamodb:UpdateGlobalTableversion` dans toutes les régions avec des réplicas. Ces autorisations s’ajoutent aux autorisations nécessaires pour accéder à la console DynamoDB et afficher les tables.

La politique IAM suivante accorde des autorisations pour mettre à niveau n’importe quelle table globale vers la version 2019.11.21 (actuelle).

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

La politique IAM suivante accorde des autorisations pour mettre à niveau uniquement la table globale `Music`, avec des réplicas dans deux régions, vers la version 2019.11.21 (actuelle).

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

### À quoi s’attendre lors de la mise à niveau
<a name="V2GlobalTablesUpgradeExpectations"></a>
+ Tous les réplicas de tables globales continueront à traiter le trafic de lecture et d’écriture pendant la mise à niveau.
+ Le processus de mise à niveau prend entre quelques minutes et plusieurs heures selon la taille de la table et le nombre de réplicas.
+ Au cours du processus de mise à niveau, la valeur de [TableStatus](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_TableDescription.html#DDB-Type-TableDescription-TableStatus)passera de `ACTIVE` à`UPDATING`. Vous pouvez consulter l'état de la table en appelant l'[DescribeTable](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DescribeTable.html)API ou en utilisant la vue **Tables** de la console DynamoDB.
+ L’autoscaling n’ajustera pas les paramètres de capacité provisionnée pour une table globale pendant la mise à niveau de la table. Nous vous recommandons vivement de configurer la table en mode capacité [à la demande](capacity-mode.md#capacity-mode-on-demand) lors de la mise à niveau.
+ Si vous choisissez d’utiliser la capacité [provisionné](provisioned-capacity-mode.md) avec autoscaling pendant la mise à niveau, vous devez augmenter le débit minimum de lecture et d’écriture de vos politiques pour tenir compte des augmentations attendues du trafic et éviter toute limitation pendant la mise à niveau.
+ La métrique `ReplicationLatency` peut signaler temporairement les pics de latence ou arrêter de signaler les données métriques pendant le processus de mise à niveau. Pour plus d’informations, consultez [ReplicationLatency](metrics-dimensions.md#ReplicationLatency). 
+ Lorsque le processus de mise à niveau est terminé, l’état de votre table revient à `ACTIVE`.

### Comportement de DynamoDB Streams avant, pendant et après la mise à niveau
<a name="V2GlobalTablesUpgradeDDBStreamsBehavior"></a>

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

### Mise à jour vers la version 2019.11.21 (actuelle)
<a name="V2globaltables_versions.upgrade"></a>

Procédez comme suit pour mettre à jour la version des tables globales DynamoDB à l’aide de la AWS Management Console.

**Pour mettre à niveau des tables globales vers la version 2019.11.21 (actuelle)**

1. [Ouvrez la console DynamoDB à la maison. https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/home) 

1. Dans le volet de navigation situé sur le côté gauche de la console, choisissez **Tables**, puis sélectionnez la table globale à mettre à niveau vers la version 2019.11.21 (actuelle). 

1. Choisissez l’onglet **Tables globales**.

1. Choisissez **Update version (Mettre à jour la version)**.  
![\[Capture d’écran de la console illustrant le bouton Update version (Mettre à jour la version).\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GlobalTables-upgrade.png)

1. Lisez et acceptez les nouvelles exigences, puis choisissez **Mettre à jour la version**.

1. Une fois le processus de mise à niveau terminé, la version des tables globales qui apparaît sur la console est la version **2019.11.21**.

# Bonnes pratiques relatives aux tables globales
<a name="globaltables-bestpractices"></a>

Les sections suivantes décrivent les bonnes pratiques en matière de déploiement et d’utilisation de tables globales.

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

Deux versions des tables globales DynamoDB sont disponibles : la version 2019.11.21 (actuelle) et la [version 2017.11.29 (héritée)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/globaltables.V1.html). Vous devez utiliser la version 2019.11.21 (actuelle) dans la mesure du possible. 

## Protection contre la suppression
<a name="globaltables-bestpractices-deletionprotection"></a>

Vous devez activer la protection contre la suppression sur les réplicas de tables globales que vous souhaitez protéger contre toute suppression accidentelle. Vous devez activer la protection contre la suppression sur chaque réplica.

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

CloudFormation ne prend actuellement pas en charge la coordination des ressources multirégionales telles que les tables mondiales entre les piles. Si vous définissez chaque réplica d’une table globale dans une pile régionale distincte, vous rencontrerez des erreurs dues à la détection d’une dérive entre les piles lors de la mise à jour des réplicas. Pour éviter ce problème, vous devez choisir une région comme région de référence pour déployer vos tables globales et définir tous les réplicas de vos tables globales dans la pile de cette région.

**Important**  
Vous ne pouvez pas convertir une ressource de type `AWS::DynamoDB::Table` en une ressource de type `AWS::DynamoDB::GlobalTable` en modifiant son type dans votre modèle. Toute tentative de conversion d'une table à région unique en table globale en modifiant son type de CloudFormation ressource peut entraîner la suppression de votre table DynamoDB.

Vous pouvez utiliser la ressource `AWS::DynamoDB::GlobalTable` pour créer une table dans une seule région. Cette table sera déployée comme toute autre table à région unique. Si vous mettez ultérieurement à jour la pile pour ajouter d’autres régions à une ressource, des réplicas seront ajoutés à la table et celle-ci sera convertie en toute sécurité en table globale.

Si vous souhaitez convertir une ressource `AWS::DynamoDB::Table` existante en ressource `AWS::DynamoDB::GlobalTable`, les étapes recommandées pour convertir le type de ressource sont les suivantes :

1. Définir la politique de suppression `AWS::DynamoDB::Table` à conserver.

1. Retirer la table de la définition de pile.

1. Ajoutez des répliques à la table à région unique de la AWS console, en la convertissant en table globale.

1. Importer la table globale en tant que nouvelle ressource `AWS::DynamoDB::GlobalTable` dans la pile.

## Sauvegardes et Point-in-Time restauration
<a name="globaltables-bestpractices-backups"></a>

L'activation des sauvegardes et Point-in-Time restaurations automatisées (PITR) pour une réplique dans une table globale peut être suffisante pour atteindre vos objectifs de reprise après sinistre. Les répliques de sauvegarde créées avec AWS-Backup peuvent être automatiquement répliquées entre les régions pour une meilleure résilience. Tenez compte des objectifs de votre plan de reprise après sinistre dans le contexte de la haute disponibilité multirégionale lorsque vous choisissez votre stratégie de sauvegarde et d’activation du PITR.

## Conception pour une haute disponibilité multirégionale
<a name="globaltables-bestpractices-multiregion"></a>

Pour obtenir des conseils prescriptifs sur le déploiement de tables globales, consultez les [Bonnes pratiques relatives à la conception d’une table globale DynamoDB](bp-global-table-design.md).

# Utilisation d’éléments et d’attributs dans DynamoDB
<a name="WorkingWithItems"></a>

Dans Amazon DynamoDB, un *élément* est une collection d’attributs. Chaque attribut a un nom et une valeur. Une valeur d’attribut peut être de type scalaire, d’ensemble ou de document. Pour de plus amples informations, veuillez consulter [Fonctionnement d’Amazon DynamoDB](HowItWorks.md).

DynamoDB fournit quatre opérations correspondant aux fonctionnalités de base de création, lecture, mise à jour et suppression (CRUD). Toutes ces opérations sont atomiques.
+ `PutItem` – Création d’un élément
+ `GetItem` – Lecture d’un élément
+ `UpdateItem` – Mise à jour d’un élément
+ `DeleteItem` – Suppression d’un élément

Pour chacune de ces opérations, vous devez indiquer la clé primaire de l’élément que vous souhaitez utiliser. Par exemple, pour lire un élément avec `GetItem`, vous devez spécifier la clé de partition et la clé de tri (le cas échéant) de cet élément.

Outre les quatre opérations CRUD de base, DynamoDB offre les fonctionnalités suivantes :
+ `BatchGetItem` – Lecture de 100 éléments au plus à partir d’une ou de plusieurs tables
+ `BatchWriteItem` – Création ou suppression de 25 éléments au plus dans une ou plusieurs tables

Ces opérations par lots peuvent associer plusieurs opérations CRUD dans une même demande. En outre, les opérations par lots lisent et écrivent des éléments en parallèle afin de réduire les latences de réponse.

Cette section explique comment utiliser ces opérations. Elle comprend des rubriques connexes telles que les mises à jour conditionnelles et les compteurs atomiques. Cette section inclut également un exemple de code utilisant le AWS SDKs. 

**Topics**
+ [Tailles et formats d’élément DynamoDB](CapacityUnitCalculations.md)
+ [Lecture d’un élément](#WorkingWithItems.ReadingData)
+ [Écriture d’un élément](#WorkingWithItems.WritingData)
+ [Valeurs renvoyées](#WorkingWithItems.ReturnValues)
+ [Opérations par lots](#WorkingWithItems.BatchOperations)
+ [Compteurs atomiques](#WorkingWithItems.AtomicCounters)
+ [Écritures conditionnelles](#WorkingWithItems.ConditionalUpdate)
+ [Utilisation d’expressions dans DynamoDB](Expressions.md)
+ [Utilisation de la durée de vie (TTL) dans DynamoDB](TTL.md)
+ [Interrogation de tables dans DynamoDB](Query.md)
+ [Analyse de tables dans DynamoDB](Scan.md)
+ [PartiQL – Langage de requête compatible SQL pour Amazon DynamoDB](ql-reference.md)
+ [Utilisation des éléments : Java](JavaDocumentAPIItemCRUD.md)
+ [Utilisation des élements : .NET](LowLevelDotNetItemCRUD.md)

# Tailles et formats d’élément DynamoDB
<a name="CapacityUnitCalculations"></a>

Les tables DynamoDB étant sans schéma, sauf pour la clé primaire, les éléments d’une table peuvent avoir des attributs, tailles et types de données différents.

La taille totale d’un élément est la somme des longueurs de ses noms et valeurs d’attribut, plus toute surcharge applicable telle que décrite ci-dessous. Vous pouvez évaluer la taille des attributs à l’aide des consignes suivantes :
+ Les chaînes sont Unicode avec codage binaire UTF-8. La taille d’une chaîne est *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 (nombre d’octets codés en UTF-8)*.
+ Les nombres sont de longueur variable, avec 38 chiffres significatifs au plus. Les zéros de début et de fin sont tronqués. La taille d’un nombre est approximativement *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 (1 octet pour 2 chiffres significatifs) \$1 (1 octet)*.
+ Une valeur binaire doit être codée en base 64 avant d’être envoyée à DynamoDB, mais la longueur en octets bruts de la valeur est utilisée pour le calcul de la taille. La taille d’un binary attribute est *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 (nombre d’octets bruts).*
+ La taille d’un attribut nul ou booléen est *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 (1 octet)*.
+ Un attribut de type `List` ou `Map` a besoin de 3 octets de surcharge, quel que soit son contenu. La taille d’un attribut `List` ou `Map` est *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 somme de (taille des éléments imbriqués) \$1 (3 octets)*. La taille d’un attribut `List` ou `Map` vide est *(nombre d’octets codés en UTF-8 du nom d’attribut) \$1 (3 octets)*.
+ Chaque élément `List` ou `Map` nécessite également 1 octet de surcharge.

**Note**  
Nous vous recommandons de choisir des noms d’attribut courts. Cela vous permet de réduire la quantité de stockage requise, mais peut également réduire la quantité RCU/WCUs que vous utilisez.

À des fins de facturation du stockage, chaque élément inclut une surcharge de stockage par élément qui dépend des fonctionnalités que vous avez activées.
+ Tous les éléments de DynamoDB nécessitent une surcharge de stockage de 100 octets pour l’indexation.
+ Certaines fonctionnalités DynamoDB (tables globales, transactions, récupération de données de modification pour Kinesis Data Streams avec DynamoDB) nécessitent une surcharge de stockage supplémentaire pour tenir compte des attributs créés par le système résultant de l’activation de ces fonctions. Par exemple, les tables globales nécessitent une surcharge de stockage de 48 octets supplémentaires.

## Lecture d’un élément
<a name="WorkingWithItems.ReadingData"></a>

L’opération `GetItem` vous permet de lire un élément à partir d’une table DynamoDB. Vous devez fournir le nom de la table, ainsi que la clé primaire de l’élément souhaité.

**Example**  
L' AWS CLI exemple suivant montre comment lire un élément du `ProductCatalog` tableau.  

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}'
```

**Note**  
Avec `GetItem`, vous devez spécifier la *totalité* de la clé primaire, et non uniquement une partie. Par exemple, si une table possède une clé primaire composite (clé de partition et clé de tri), vous devez fournir une valeur pour la clé de partition et une valeur pour la clé de tri.

Une demande `GetItem` effectue une lecture cohérente à terme par défaut. Le paramètre `ConsistentRead` vous permet de demander une lecture fortement cohérente à la place. (Cela consomme des unités de capacité de lecture supplémentaires, mais renvoie la up-to-date version la plus complète de l'article.)

`GetItem` renvoie tous les attributs de l’élément. Vous pouvez renvoyer uniquement certains des attributs à l’aide d’une *expression de projection*. Pour de plus amples informations, veuillez consulter [Utilisation d’expressions de projection dans DynamoDB](Expressions.ProjectionExpressions.md).

Pour renvoyer le nombre d’unités de capacité de lecture consommées par l’opération `GetItem`, définissez le paramètre `ReturnConsumedCapacity` sur la valeur `TOTAL`.

**Example**  
L'exemple suivant AWS Command Line Interface (AWS CLI) montre certains des `GetItem` paramètres facultatifs.  

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --consistent-read \
    --projection-expression "Description, Price, RelatedItems" \
    --return-consumed-capacity TOTAL
```

## Écriture d’un élément
<a name="WorkingWithItems.WritingData"></a>

Créez, mettez à jour ou supprimez un élément dans une table DynamoDB à l’aide de l’une des opérations suivantes :
+ `PutItem`
+ `UpdateItem`
+ `DeleteItem`

Pour chacune de ces opérations, vous devez spécifier la totalité de la clé primaire, et non uniquement une partie. Par exemple, si une table possède une clé primaire composite (clé de partition et clé de tri), vous devez fournir une valeur pour la clé de partition et une valeur pour la clé de tri.

Pour renvoyer le nombre d’unités de capacité d’écriture consommées par l’une de ces opérations, définissez le paramètre `ReturnConsumedCapacity` sur l’une des valeurs suivantes : 
+ `TOTAL` – Renvoie le nombre total d’unités de capacité d’écriture consommées.
+ `INDEXES` – Renvoie le nombre total d’unités de capacité de lecture consommées, avec les sous-totaux correspondant à la table et aux index secondaires concernés par l’opération.
+ `NONE` – Aucun détail concernant la capacité d’écriture n’est renvoyé. (Il s’agit de l’option par défaut.)

### PutItem
<a name="WorkingWithItems.WritingData.PutItem"></a>

`PutItem` crée un élément. Si un élément avec la même clé existe déjà dans la table, il est remplacé par le nouvel élément.

**Example**  
Écrivez un nouvel élément dans la table `Thread`. La clé primaire de la table `Thread` est composée de `ForumName` (clé de partition) et `Subject` (clé de tri).  

```
aws dynamodb put-item \
    --table-name Thread \
    --item file://item.json
```
Les arguments de la fonction `--item` sont stockés dans le fichier `item.json`.  

```
{
    "ForumName": {"S": "Amazon DynamoDB"},
    "Subject": {"S": "New discussion thread"},
    "Message": {"S": "First post in this thread"},
    "LastPostedBy": {"S": "fred@example.com"},
    "LastPostDateTime": {"S": "201603190422"}
}
```

### UpdateItem
<a name="WorkingWithItems.WritingData.UpdateItem"></a>

S’il n’existe aucun élément associé à la clé spécifiée, `UpdateItem` en crée un. Dans le cas contraire, l’opération modifie les attributs d’un élément existant.

Vous préciser les attributs à modifier, ainsi que leurs nouvelles valeurs, à l’aide d’une *expression de mise à jour*. Pour de plus amples informations, veuillez consulter [Utilisation d’expressions de mise à jour dans DynamoDB](Expressions.UpdateExpressions.md). 

Au sein de l’expression de mise à jour, vous utilisez des valeurs d’attributs d’expression comme espaces réservés pour les valeurs réelles. Pour de plus amples informations, veuillez consulter [Utilisation de valeurs d’attributs d’expression dans DynamoDB](Expressions.ExpressionAttributeValues.md).

**Example**  
Modifiez plusieurs attributs dans l’élément `Thread`. Le paramètre `ReturnValues` facultatif présente l’élément tel qu’il s’affiche après la mise à jour. Pour de plus amples informations, veuillez consulter [Valeurs renvoyées](#WorkingWithItems.ReturnValues).  

```
aws dynamodb update-item \
    --table-name Thread \
    --key file://key.json \
    --update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy = :lastpostedby" \
    --expression-attribute-values file://expression-attribute-values.json \
    --return-values ALL_NEW
```

Les arguments de la fonction `--key` sont stockés dans le fichier `key.json`.

```
{
    "ForumName": {"S": "Amazon DynamoDB"},
    "Subject": {"S": "New discussion thread"}
}
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `expression-attribute-values.json`.

```
{
    ":zero": {"N":"0"},
    ":lastpostedby": {"S":"barney@example.com"}
}
```

### DeleteItem
<a name="WorkingWithItems.WritingData.DeleteItem"></a>

`DeleteItem` supprime l’élément avec la clé spécifiée.

**Example**  
L' AWS CLI exemple suivant montre comment supprimer l'`Thread`élément.  

```
aws dynamodb delete-item \
    --table-name Thread \
    --key file://key.json
```

## Valeurs renvoyées
<a name="WorkingWithItems.ReturnValues"></a>

Dans certains cas, vous souhaitez que DynamoDB renvoie certaines valeurs d’attribut telles qu’elles s’affichent avant ou après leur modification. Les opérations `PutItem`, `UpdateItem` et `DeleteItem` ont un paramètre `ReturnValues` vous permettant de renvoyer les valeurs d’attribut avant ou après leur modification.

La valeur par défaut de `ReturnValues` est `NONE`. Autrement dit, DynamoDB ne renvoie aucune information concernant les attributs modifiés. 

Les autres paramètres valides pour `ReturnValues` sont les suivants, classés par opération d'API DynamoDB.

### PutItem
<a name="WorkingWithItems.ReturnValues.PutItem"></a>
+ `ReturnValues`: `ALL_OLD`
  + Si vous remplacez un élément existant, `ALL_OLD` renvoie l’élément entier tel qu’il s’affichait avant son remplacement.
  + Si vous écrivez un élément qui n’existe pas, `ALL_OLD` n’a aucun effet.

### UpdateItem
<a name="WorkingWithItems.ReturnValues.UpdateItem"></a>

L’utilisation la plus courante d’`UpdateItem` est la mise à jour d’un élément existant. Cependant, `UpdateItem` effectue une opération de *mise à jour/insertion*. Autrement dit, il crée automatiquement l’élément si celui-ci n’existe pas.
+ `ReturnValues`: `ALL_OLD`
  + Si vous mettez à jour un élément existant, `ALL_OLD` renvoie l’élément entier tel qu’il s’affichait avant sa mise à jour.
  + Si vous mettez à jour un élément qui n’existe pas (upsert), `ALL_OLD` n’a aucun effet.
+ `ReturnValues`: `ALL_NEW`
  + Si vous mettez à jour un élément existant, `ALL_NEW` renvoie l’élément entier tel qu’il s’affiche après sa mise à jour.
  + Si vous mettez à jour un élément qui n’existe pas (upsert), `ALL_NEW` renvoie l’élément entier.
+ `ReturnValues`: `UPDATED_OLD`
  + Si vous mettez à jour un élément existant, `UPDATED_OLD` renvoie uniquement les attributs mis à jour tels qu’ils s’affichaient avant leur mise à jour.
  + Si vous mettez à jour un élément qui n’existe pas (upsert), `UPDATED_OLD` n’a aucun effet.
+ `ReturnValues`: `UPDATED_NEW`
  + Si vous mettez à jour un élément existant, `UPDATED_NEW` renvoie uniquement les attributs affectés tels qu’ils s’affichaient après leur mise à jour.
  + Si vous mettez à jour (upsert) un élément qui n’existe pas, `UPDATED_NEW` renvoie uniquement les attributs mis à jour tels qu’ils s’affichent après la mise à jour.

### DeleteItem
<a name="WorkingWithItems.ReturnValues.DeleteItem"></a>
+ `ReturnValues`: `ALL_OLD`
  + Si vous supprimez un élément existant, `ALL_OLD` renvoie l’élément entier tel qu’il s’affichait avant sa suppression.
  + Si vous supprimez un élément qui n’existe pas, `ALL_OLD` ne renvoie pas de données.

## Opérations par lots
<a name="WorkingWithItems.BatchOperations"></a>

Pour les applications ayant besoin de lire ou d’écrire plusieurs éléments, DynamoDB fournit les opérations `BatchGetItem` et `BatchWriteItem`. L’utilisation de ces opérations peut réduire le nombre d’allers et retours réseau entre votre application et DynamoDB. En outre, DynamoDB effectue les opérations de lecture ou d’écriture individuelles en parallèle. Vos applications bénéficient de ce parallélisme sans devoir gérer la simultanéité ou les threads.

Les opérations par lots sont essentiellement des wrappers autour de plusieurs demandes de lecture ou d’écriture. Par exemple, si une demande `BatchGetItem` comporte cinq éléments, DynamoDB exécute cinq opérations `GetItem` pour vous. De même, si une demande `BatchWriteItem` comporte deux demandes d’insertion et quatre demandes de suppression, DynamoDB exécute deux demandes `PutItem` et quatre demandes `DeleteItem`.

En général, une opération par lots n’échoue pas, sauf si *toutes* les demandes du lot échouent. Supposons, par exemple, que vous effectuiez une opération `BatchGetItem`, mais que l’une des demandes `GetItem` du lot échoue. Dans ce cas, `BatchGetItem` renvoie les clés et les données provenant de la demande `GetItem` qui a échoué. Les autres demandes `GetItem` du lot ne sont pas affectées.

### BatchGetItem
<a name="WorkingWithItems.BatchOperations.BatchGetItem"></a>

Une seule opération `BatchGetItem` peut contenir jusqu'à 100 demandes `GetItem` individuelles, et peuvent extraire jusqu'à 16 Mo de données. En outre, une opération `BatchGetItem` peut extraire des éléments de plusieurs tables.

**Example**  
Extrayez deux éléments de la table `Thread` en renvoyant uniquement certains des attributs à l’aide d’une expression de projection.  

```
aws dynamodb batch-get-item \
    --request-items file://request-items.json
```
Les arguments de la fonction `--request-items` sont stockés dans le fichier `request-items.json`.  

```
{
    "Thread": {
        "Keys": [
            {
                "ForumName":{"S": "Amazon DynamoDB"},
                "Subject":{"S": "DynamoDB Thread 1"}
            },
            {
                "ForumName":{"S": "Amazon S3"},
                "Subject":{"S": "S3 Thread 1"}
            }
        ],
        "ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies"
    }
}
```

### BatchWriteItem
<a name="WorkingWithItems.BatchOperations.BatchWriteItem"></a>

L'opération `BatchWriteItem` peut contenir jusqu'à 25 demandes `PutItem` et `DeleteItem` individuelles, et peut écrire jusqu'à 16 Mo de données (La taille maximale d’un élément est de 400 Ko.) En outre, une même opération `BatchWriteItem` peut insérer ou supprimer des éléments de plusieurs tables. 

**Note**  
`BatchWriteItem` ne prend pas en charge les demandes `UpdateItem`.

**Example**  
Ajoutez deux éléments à la table `ProductCatalog`.  

```
aws dynamodb batch-write-item \
    --request-items file://request-items.json
```
Les arguments de la fonction `--request-items` sont stockés dans le fichier `request-items.json`.  

```
{
    "ProductCatalog": [
        {
            "PutRequest": {
                "Item": {
                    "Id": { "N": "601" },
                    "Description": { "S": "Snowboard" },
                    "QuantityOnHand": { "N": "5" },
                    "Price": { "N": "100" }
                }
            }
        },
        {
            "PutRequest": {
                "Item": {
                    "Id": { "N": "602" },
                    "Description": { "S": "Snow shovel" }
                }
            }
        }
    ]
}
```

## Compteurs atomiques
<a name="WorkingWithItems.AtomicCounters"></a>

L’opération `UpdateItem` vous permet d’implémenter un *compteur atomique*, c’est-à-dire un attribut numérique incrémenté sans condition, sans interférer avec d’autres demandes d’écriture. (Toutes les demandes d’écriture sont appliquées dans l’ordre dans lequel elles ont été reçues.) Avec un compteur atomique, les mises à jour ne sont pas idempotentes. Autrement dit, la valeur numérique augmente ou diminue chaque fois que vous appelez `UpdateItem`. Si la valeur d’incrément permettant de mettre à jour le compteur atomique est positive, cela peut provoquer un surcomptage. Si la valeur d’incrément est négative, cela peut entraîner une sous-estimation.

Un compteur atomique vous permet de suivre le nombre de visiteurs d’un site web. Dans ce cas, l’application doit incrémenter une valeur numérique, quelle que soit sa valeur actuelle. En cas d’échec d’une opération `UpdateItem`, l’application peut simplement retenter l’opération. Cela risquerait de mettre à jour le compteur deux fois, mais vous pourriez probablement tolérer de sur-comptabiliser ou sous-comptabiliser légèrement les visiteurs.

Dans le cas contraire, l’utilisation d’un compteur automatique n’est pas adaptée (par exemple dans une application bancaire). Il est alors plus sûr d’utiliser une mise à jour conditionnelle plutôt qu’un compteur atomique.

Pour de plus amples informations, veuillez consulter [Incrémentation et décrémentation d’attributs numériques](Expressions.UpdateExpressions.md#Expressions.UpdateExpressions.SET.IncrementAndDecrement).

**Example**  
L' AWS CLI exemple suivant augmente la valeur `Price` d'un produit de 5. Dans cet exemple, l’existence de l’élément était connue avant la mise à jour du compteur. Puisque l’opération `UpdateItem` n’est pas idempotente, le `Price` augmente à chaque exécution de ce code.   

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id": { "N": "601" }}' \
    --update-expression "SET Price = Price + :incr" \
    --expression-attribute-values '{":incr":{"N":"5"}}' \
    --return-values UPDATED_NEW
```

## Écritures conditionnelles
<a name="WorkingWithItems.ConditionalUpdate"></a>

Par défaut, les opérations d'écriture DynamoDB `PutItem` (`DeleteItem`,) *sont* inconditionnelles : chaque opération remplace un élément existant qui possède la clé primaire spécifiée.

DynamoDB prend en charge, en option, les écritures conditionnelles pour ces opérations. Une écriture conditionnelle réussit seulement si les attributs de l’élément remplissent une ou plusieurs conditions prévues. Dans le cas contraire, elle renvoie une erreur.

Les écritures conditionnelles vérifient leurs conditions par rapport à la dernière version mise à jour de l’élément. Notez que si l’élément n’existait pas auparavant ou si la dernière opération réussie sur cet élément était une suppression, l’écriture conditionnelle ne trouvera aucun élément précédent.

 Les écritures conditionnelles sont utiles dans de nombreux cas. Par exemple, vous pouvez décider qu’une opération `PutItem` réussit seulement si aucun élément avec la même clé primaire n’existe déjà. Vous pouvez également empêcher une opération `UpdateItem` de modifier un élément si l’un de ses attributs possède une valeur donnée.

Les écritures conditionnelles sont utiles dans les cas où plusieurs utilisateurs tentent de modifier le même élément. Examinez le diagramme suivant, dans lequel deux utilisateurs (Alice et Bob) utilisent le même élément provenant d’une table DynamoDB.

![\[Les utilisateurs Alice et Bob tentent de modifier un élément ayant l’ID 1, démontrant ainsi la nécessité d’écritures conditionnelles.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/update-no-condition.png)


Supposons qu'Alice utilise le AWS CLI pour mettre à jour l'`Price`attribut à 8.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --update-expression "SET Price = :newval" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `expression-attribute-values.json` :

```
{
    ":newval":{"N":"8"}
}
```

Supposons maintenant que Bob émette une demande `UpdateItem` similaire ultérieurement, mais qu’il redéfinisse l’attribut `Price` sur la valeur 12. Pour Bob, le paramètre `--expression-attribute-values` prend la forme suivante.

```
{
    ":newval":{"N":"12"}
}
```

La demande de Bob aboutit, mais la mise à jour précédente d’Alice est perdue.

Pour demander une opération `PutItem`, `DeleteItem` ou `UpdateItem` conditionnelle, vous spécifiez une expression de condition. Une *expression de condition* est une chaîne comportant des noms d’attributs, des opérateurs conditionnels et des fonctions intégrées. L’expression entière doit avoir la valeur true. Sinon, l’opération échoue.

Examinez maintenant le diagramme suivant, qui présente les écritures conditionnelles qui empêcheraient le remplacement de la mise à jour d’Alice.

![\[Écriture conditionnelle empêchant la mise à jour de l’utilisateur Bob de remplacer la modification apportée par l’utilisatrice Alice au même élément.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/update-yes-condition.png)


Alice tente dans un premier temps de redéfinir l’attribut `Price` sur la valeur 8, mais seulement si la valeur actuelle de l’attribut `Price` est 10.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"1"}}' \
    --update-expression "SET Price = :newval" \
    --condition-expression "Price = :currval" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `expression-attribute-values.json`.

```
{
    ":newval":{"N":"8"},
    ":currval":{"N":"10"}
}
```

La mise à jour d’Alice aboutit, car la condition a la valeur true.

Ensuite, Bob tente de redéfinir l’attribut `Price` sur la valeur 12, mais seulement si la valeur actuelle de l’attribut `Price` est 10. Pour Bob, le paramètre `--expression-attribute-values` prend la forme suivante.

```
{
    ":newval":{"N":"12"},
    ":currval":{"N":"10"}
}
```

Comme Alice a précédemment redéfinit l’attribut `Price` sur la valeur 8, l’expression de condition a la valeur false et la mise à jour de Bob échoue.

Pour de plus amples informations, veuillez consulter [Exemple de commande CLI d’expression de condition DynamoDB](Expressions.ConditionExpressions.md).

### Idempotence d’écriture conditionnelle
<a name="WorkingWithItems.ConditionalWrites.Idempotence"></a>

Les écritures conditionnelles peuvent être *idempotentes* si la vérification conditionnelle porte sur le même attribut que celui mis à jour. Autrement dit, DynamoDB effectue une demande d’écriture donnée seulement si certaines valeurs d’attribut dans l’élément correspondent à ce que vous attendez lors de la demande. 

Par exemple, supposons que vous émettiez une demande `UpdateItem` pour augmenter l’attribut `Price` d’un élément de 3, mais seulement si la valeur actuelle de l’attribut `Price` est 20. Après l’envoi de la demande, mais avant que vous n’obteniez les résultats, une erreur réseau se produit et vous ne savez pas si votre demande a abouti ou non. Cette écriture conditionnelle étant idempotente, vous pouvez retenter la même demande `UpdateItem`, puis DynamoDB met à jour l’élément seulement si l’attribut `Price` est actuellement défini sur la valeur 20.

### Unités de capacité consommées par les écritures conditionnelles
<a name="WorkingWithItems.ConditionalWrites.ReturnConsumedCapacity"></a>

Si une `ConditionExpression` prend la valeur false pendant une écriture conditionnelle, DynamoDB continue à consommer la capacité d’écriture de la table. La quantité consommée dépend de la taille de l’élément existant (ou valeur minimale de 1). Par exemple, si un élément existant fait 300 Ko et que l’élément que vous essayez de créer ou mettre à jour fait 310 Ko, les unités de capacité d’écriture consommées seront de 300 Ko si la condition n’est pas remplie et de 310 si elle est remplie. S’il s’agit d’un nouvel élément (élément non existant), les unités de capacité d’écriture consommées seront de 1 si la condition n’est pas remplie et de 310 si elle est remplie.

**Note**  
Les opérations d’écriture consomment uniquement des unités de capacité d’*écriture*. Elles n’utilisent jamais d’unités de capacité de *lecture*.

Une écriture conditionnelle ayant échoué renvoie un `ConditionalCheckFailedException`. Lorsque cela se produit, vous ne recevez aucune information dans la réponse concernant la capacité d’écriture consommée.

Renvoyez le nombre d’unités de capacité d’écriture consommées au cours d’une écriture conditionnelle à l’aide du paramètre `ReturnConsumedCapacity` :
+ `TOTAL` – Renvoie le nombre total d’unités de capacité d’écriture consommées.
+ `INDEXES` – Renvoie le nombre total d’unités de capacité de lecture consommées, avec les sous-totaux correspondant à la table et aux index secondaires concernés par l’opération.
+ `NONE` – Aucun détail concernant la capacité d’écriture n’est renvoyé. (Il s’agit de l’option par défaut.)

  

**Note**  
Contrairement à un index secondaire global, un index secondaire local partage sa capacité de débit alloué avec sa table. L’activité de lecture et d’écriture sur un index secondaire local consomme la capacité de débit alloué de la table.

# Utilisation d’expressions dans DynamoDB
<a name="Expressions"></a>

Dans Amazon DynamoDB, les *expressions* vous permettent de spécifier les attributs à lire dans un élément, d’écrire des données lorsqu’une condition est remplie, d’indiquer comment mettre à jour un élément, de définir des requêtes et de filtrer les résultats d’une requête.

Ce tableau décrit la grammaire d’expression basique et les types d’expressions disponibles.


| Type d’expression | Description | 
| --- | --- | 
| Expression de projection | Une expression de projection identifie les attributs que vous souhaitez récupérer d'un élément lorsque vous utilisez des opérations telles que GetItem Query ou Scan. | 
| Expression de condition | Une expression de condition détermine quels éléments doivent être modifiés lorsque vous utilisez les DeleteItem opérations PutItem UpdateItem, et. | 
| Expression de mise à jour | Une expression de mise à jour indique comment UpdateItem modifier les attributs d'un élément, par exemple en définissant une valeur scalaire ou en supprimant des éléments d'une liste ou d'une carte. | 
| Expression de condition clé | Une expression de condition clé détermine les éléments qu’une requête doit lire dans une table ou un index. | 
| Expression de filtre | Une expression de filtre détermine les éléments dans les résultats de la requête à vous renvoyer. Tous les autres résultats sont ignorés. | 

Pour en savoir plus sur la syntaxe d’expression et chaque type d’expression, consultez les sections suivantes.

**Topics**
+ [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](Expressions.Attributes.md)
+ [Noms d’attributs d’expression (alias) dans DynamoDB](Expressions.ExpressionAttributeNames.md)
+ [Utilisation de valeurs d’attributs d’expression dans DynamoDB](Expressions.ExpressionAttributeValues.md)
+ [Utilisation d’expressions de projection dans DynamoDB](Expressions.ProjectionExpressions.md)
+ [Utilisation d’expressions de mise à jour dans DynamoDB](Expressions.UpdateExpressions.md)
+ [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md)
+ [Exemple de commande CLI d’expression de condition DynamoDB](Expressions.ConditionExpressions.md)

**Note**  
Pour la compatibilité descendante, DynamoDB prend également en charge des paramètres conditionnels qui n’utilisent pas d’expressions. Pour de plus amples informations, veuillez consulter [Paramètres conditionnels hérités de DynamoDB](LegacyConditionalParameters.md).  
Les nouvelles applications doivent utiliser des expressions plutôt que des paramètres hérités.

# Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB
<a name="Expressions.Attributes"></a>

Cette section décrit comment référencer des attributs d’élément dans une expression dans Amazon DynamoDB. Vous pouvez utiliser tout attribut, même s’il est profondément imbriqué dans plusieurs listes et mappages.

**Topics**
+ [Attributs de niveau supérieur](#Expressions.Attributes.TopLevelAttributes)
+ [Attributs imbriqués](#Expressions.Attributes.NestedAttributes)
+ [Chemins d’accès à des documents](#Expressions.Attributes.NestedElements.DocumentPathExamples)

**Un exemple d'article : ProductCatalog**  
Les exemples sur cette page utilisent l’exemple d’élément suivant dans la table `ProductCatalog`. (Cette table est décrite dans [Exemples de tables et de données à utiliser dans DynamoDB](AppendixSampleTables.md).)

```
{
    "Id": 123,
    "Title": "Bicycle 123",
    "Description": "123 description",
    "BicycleType": "Hybrid",
    "Brand": "Brand-Company C",
    "Price": 500,
    "Color": ["Red", "Black"],
    "ProductCategory": "Bicycle",
    "InStock": true,
    "QuantityOnHand": null,
    "RelatedItems": [
        341,
        472,
        649
    ],
    "Pictures": {
        "FrontView": "http://example.com/products/123_front.jpg",
        "RearView": "http://example.com/products/123_rear.jpg",
        "SideView": "http://example.com/products/123_left_side.jpg"
    },
    "ProductReviews": {
	    "FiveStar": [
	    		"Excellent! Can't recommend it highly enough! Buy it!",
	    		"Do yourself a favor and buy this."
	    ],
	    "OneStar": [
	    		"Terrible product! Do not buy this."
	    ]
    },
    "Comment": "This product sells out quickly during the summer",
    "Safety.Warning": "Always wear a helmet"
 }
```

Notez ce qui suit :
+ La valeur de la clé de partition (`Id`) est `123`. Il n’y a aucune clé de tri.
+ La plupart des attributs ont des types de données scalaires, comme `String`, `Number`, `Boolean` et `Null`.
+ Un attribut (`Color`) est un `String Set`.
+ Les attributs suivants sont des types de données de documents :
  + Une liste de `RelatedItems`. Chaque élément est un `Id` pour un produit concerné.
  + Une carte de `Pictures`. Chaque élément est une brève description d’une image, accompagnée d’une URL pour le fichier image correspondant.
  + Une carte de `ProductReviews`. Chaque élément représente une évaluation et une liste de commentaires correspondant à cette évaluation. À l’origine, ce mappage est renseigné avec des commentaires cinq étoiles et une étoile.

## Attributs de niveau supérieur
<a name="Expressions.Attributes.TopLevelAttributes"></a>

Un attribut est dit *de niveau supérieur* lorsqu’il n’est pas imbriqué dans un autre. Dans le cas de l’élément `ProductCatalog`, voici les attributs de niveau supérieur :
+ `Id`
+ `Title`
+ `Description`
+ `BicycleType`
+ `Brand`
+ `Price`
+ `Color`
+ `ProductCategory`
+ `InStock`
+ `QuantityOnHand`
+ `RelatedItems`
+ `Pictures`
+ `ProductReviews`
+ `Comment`
+ `Safety.Warning`

Tous ces attributs de niveau supérieur sont scalaires, à l’exception de `Color` (liste), `RelatedItems` (liste), `Pictures` (mappage) et `ProductReviews` (mappage).

## Attributs imbriqués
<a name="Expressions.Attributes.NestedAttributes"></a>

Un attribut est dit *imbriqué* lorsqu’il est incorporé dans un autre. Accédez à un attribut imbriqué à l’aide d’*opérateurs de déréférençage* :
+ `[n]` – Pour des éléments de liste
+ `.` (point) – Pour des éléments de mappage

### Accès à des éléments de liste
<a name="Expressions.Attributes.NestedElements.AccessingListElements"></a>

L’opérateur de déréférençage pour un élément de liste est **[*n*]**, où *n* est le numéro d’élément. Des éléments de liste sont de base zéro, donc [0] représente le premier élément dans la liste, [1] représente le deuxième et ainsi de suite. Voici quelques exemples :
+ `MyList[0]`
+ `AnotherList[12]`
+ `ThisList[5][11]`

L’élément `ThisList[5]` est lui-même une liste imbriquée. Par conséquent, `ThisList[5][11]` fait référence au douzième élément dans cette liste.

Le nombre entre crochets doit être un nombre entier non négatif. Par conséquent, les expressions suivantes ne sont pas valides :
+ `MyList[-1]`
+ `MyList[0.4]`

### Accès à des éléments de mappage
<a name="Expressions.Attributes.NestedElements.AccessingMapElements"></a>

L’opérateur de déréférençage pour un élément de mappage est **.** (un point). Utilisez un point comme séparateur entre des éléments d’un mappage :
+ `MyMap.nestedField`
+ `MyMap.nestedField.deeplyNestedField`

## Chemins d’accès à des documents
<a name="Expressions.Attributes.NestedElements.DocumentPathExamples"></a>

Dans une expression, vous indiquez à DynamoDB où trouver un attribut à l’aide d’un *chemin d’accès à un document*. Pour un attribut de niveau supérieur, le chemin d’accès au document est simplement le nom d’attribut. Pour un attribut imbriqué, vous construisez le chemin d’accès au document à l’aide d’opérateurs de déréférençage.

Voici quelques exemples d’expressions de chemins d’accès à des documents. (Consultez l’élément présenté dans [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](#Expressions.Attributes).)
+ Attribut scalaire de niveau supérieur.

   `Description`
+ Attribut de liste de niveau supérieur. (Renvoie la liste entière, et non uniquement certains éléments.)

  `RelatedItems`
+ Le troisième élément de la liste `RelatedItems`. (N’oubliez pas que les éléments de liste sont de base zéro.)

  `RelatedItems[2]`
+ Photo de face du produit.

  `Pictures.FrontView`
+ Tous les commentaires cinq étoiles.

  `ProductReviews.FiveStar`
+ Le premier des commentaires cinq étoiles.

  `ProductReviews.FiveStar[0]`

**Note**  
La profondeur maximale pour un chemin d’accès à un document est de 32. Par conséquent, le nombre d’opérateurs de déréférençage dans un chemin d’accès ne peut pas dépasser cette limite.

Vous pouvez utiliser tout nom d’attribut dans le chemin d’accès à un document, à condition qu’il réponde aux exigences suivantes :
+ Le premier caractère est `a-z` ou `A-Z` et/ou `0-9`.
+ Le second caractère (le cas échéant) est `a-z`, `A-Z`.

**Note**  
Si un nom d’attribut ne répond pas à cette exigence, vous devez définir un nom d’attribut d’expression comme espace réservé.

Pour de plus amples informations, veuillez consulter [Noms d’attributs d’expression (alias) dans DynamoDB](Expressions.ExpressionAttributeNames.md).

# Noms d’attributs d’expression (alias) dans DynamoDB
<a name="Expressions.ExpressionAttributeNames"></a>

Un *nom d’attribut d’expression* est un alias (ou espace réservé) utilisé dans une expression Amazon DynamoDB à la place d’un nom d’attribut réel. Un nom d’attribut d’expression doit commencer par un signe dièse (`#`) et être suivi d’un ou de plusieurs caractères alphanumériques. Le trait de soulignement (`_`) est également autorisé.

Cette section présente plusieurs cas dans lesquels vous devez utiliser des noms d’attributs d’expression.

**Note**  
Les exemples de cette section utilisent le AWS Command Line Interface (AWS CLI). 

**Topics**
+ [Mots réservés](#Expressions.ExpressionAttributeNames.ReservedWords)
+ [Noms d’attributs comportant des caractères spéciaux](#Expressions.ExpressionAttributeNames.AttributeNamesContainingSpecialCharacters)
+ [Attributs imbriqués](#Expressions.ExpressionAttributeNames.NestedAttributes)
+ [Référencement répété de noms d’attributs](#Expressions.ExpressionAttributeNames.RepeatingAttributeNames)

## Mots réservés
<a name="Expressions.ExpressionAttributeNames.ReservedWords"></a>

Dans certains cas, vous pouvez avoir besoin d’écrire une expression comportant un nom d’attribut qui entre en conflit avec un mot réservé DynamoDB. (Pour obtenir la liste complète des mots réservés, consultez [Mots réservés dans DynamoDB](ReservedWords.md).)

Par exemple, l' AWS CLI exemple suivant échouerait car il `COMMENT` s'agit d'un mot réservé.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "Comment"
```

Pour contourner cela, vous pouvez remplacer `Comment` par un nom d’attribut d’expression tel que `#c`. Le `#` (signe dièse) est obligatoire et indique qu’il s’agit d’un espace réservé pour un nom d’attribut. L' AWS CLI exemple devrait maintenant ressembler à ce qui suit.

```
aws dynamodb get-item \
     --table-name ProductCatalog \
     --key '{"Id":{"N":"123"}}' \
     --projection-expression "#c" \
     --expression-attribute-names '{"#c":"Comment"}'
```

**Note**  
Si un nom d’attribut commence par un nombre ou comporte un espace ou un mot réservé, vous *devez* remplacer ce nom d’attribut dans l’expression à l’aide d’un nom d’attribut d’expression.

## Noms d’attributs comportant des caractères spéciaux
<a name="Expressions.ExpressionAttributeNames.AttributeNamesContainingSpecialCharacters"></a>

Dans une expression, un point (« . ») est interprété comme un caractère de séparation dans un chemin d’accès à un document. Cependant, DynamoDB vous permet également d’utiliser un caractère point et d’autres caractères spéciaux tels qu’un trait d’union (« - ») dans le cadre d’un nom d’attribut. Cela peut être ambigu dans certains cas. À titre d’illustration, supposons que vous souhaitiez récupérer l’attribut `Safety.Warning` d’un élément `ProductCatalog`. (Consultez [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](Expressions.Attributes.md).)

Supposons que vous souhaitiez accéder à `Safety.Warning` à l’aide d’une expression de projection.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "Safety.Warning"
```

DynamoDB renvoie un résultat vide au lieu de la chaîne attendue (« `Always wear a helmet` »). En effet, DynamoDB interprète un point dans une expression comme un caractère de séparation dans un chemin d’accès à un document. Dans ce cas, vous devez définir un nom d’attribut d’expression (tel que `#sw`) en remplacement de `Safety.Warning`. Vous pouvez ensuite utiliser l’expression de projection suivante.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#sw" \
    --expression-attribute-names '{"#sw":"Safety.Warning"}'
```

DynamoDB renvoie alors le résultat correct.

**Note**  
Si un nom d’attribut comporte un point (« . ») ou un trait d’union (« - »), vous*devez* remplacer le nom de cet attribut dans l’expression à l’aide d’un nom d’attribut d’expression.

## Attributs imbriqués
<a name="Expressions.ExpressionAttributeNames.NestedAttributes"></a>

Supposons que vous souhaitiez accéder à l’attribut imbriqué `ProductReviews.OneStar`. Dans un nom d’attribut d’expression, DynamoDB traite un point (« . ») comme un caractère dans un nom d’attribut. Pour référencer l’attribut imbriqué, définissez un nom d’attribut d’expression pour chaque élément dans le chemin d’accès au document :
+ `#pr — ProductReviews`
+ `#1star — OneStar`

Vous pouvez ensuite utiliser `#pr.#1star` pour l’expression de projection.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#pr.#1star"  \
    --expression-attribute-names '{"#pr":"ProductReviews", "#1star":"OneStar"}'
```

DynamoDB renvoie alors le résultat correct.

## Référencement répété de noms d’attributs
<a name="Expressions.ExpressionAttributeNames.RepeatingAttributeNames"></a>

Les noms d’attributs d’expression sont utiles lorsque vous devez référencer le même nom d’attribut à plusieurs reprises. Par exemple, imaginons l’expression suivante pour récupérer certains des commentaires d’un élément `ProductCatalog`.

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "ProductReviews.FiveStar, ProductReviews.ThreeStar, ProductReviews.OneStar"
```

Pour la rendre plus concise, vous pouvez remplacer `ProductReviews` par un nom d’attribut d’expression tel que `#pr`. L’expression révisée ressemblerait maintenant à ceci.
+  `#pr.FiveStar, #pr.ThreeStar, #pr.OneStar` 

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"123"}}' \
    --projection-expression "#pr.FiveStar, #pr.ThreeStar, #pr.OneStar" \
    --expression-attribute-names '{"#pr":"ProductReviews"}'
```

Si vous définissez un nom d’attribut d’expression, vous devez l’utiliser systématiquement sur l’ensemble de l’expression. En outre, vous ne pouvez pas ignorer le symbole `#`. 

# Utilisation de valeurs d’attributs d’expression dans DynamoDB
<a name="Expressions.ExpressionAttributeValues"></a>

Les *valeurs d’attributs d’expression* dans Amazon DynamoDB font office de variables. Elles remplacent les valeurs réelles que vous souhaitez comparer, valeurs que vous ne connaissez peut-être pas avant l’exécution. Une valeur d’attribut d’expression doit commencer par un signe deux-points (`:`) et être suivie d’un ou de plusieurs caractères alphanumériques.

Par exemple, supposons que vous souhaitiez renvoyer tous les éléments de `ProductCatalog` disponibles en `Black` et coûtant au maximum `500`. Vous pouvez utiliser une opération `Scan` avec une expression de filtre, comme dans cet exemple AWS Command Line Interface  (AWS CLI).

```
aws dynamodb scan \
    --table-name ProductCatalog \
    --filter-expression "contains(Color, :c) and Price <= :p" \
    --expression-attribute-values file://values.json
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.

```
{
    ":c": { "S": "Black" },
    ":p": { "N": "500" }
}
```

Si vous définissez une valeur d’attribut d’expression, vous devez l’utiliser systématiquement sur l’ensemble de l’expression. En outre, vous ne pouvez pas ignorer le symbole `:`. 

Les valeurs d’attributs d’expression sont utilisées avec des expressions de condition de clé, des expressions de condition, des expressions de mise à jour et des expressions de filtre.

# Utilisation d’expressions de projection dans DynamoDB
<a name="Expressions.ProjectionExpressions"></a>

Vous lisez des données d’une table à l’aide d’opérations telles que `GetItem`, `Query` ou `Scan`. Par défaut, Amazon DynamoDB renvoie tous les attributs d’élément. Obtenez seulement certains des attributs et non leur totalité à l’aide d’une expression de projection.

Une *expression de projection* est une chaîne qui identifie les attributs souhaités. Pour récupérer un seul attribut, spécifiez son nom. Pour plusieurs attributs, les noms doivent être séparés par des virgules.

Voici des exemples d’expressions de projection basées sur l’élément `ProductCatalog` à partir de [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](Expressions.Attributes.md) :
+ Un seul attribut de niveau supérieur.

  `Title `
+ Trois attributs de niveau supérieur. DynamoDB extrait l’ensemble `Color` tout entier.

  `Title, Price, Color`
+ Quatre attributs de niveau supérieur. DynamoDB renvoie tout le contenu de `RelatedItems` et `ProductReviews`.

  `Title, Description, RelatedItems, ProductReviews`

**Note**  
L’expression de projection n’a aucun effet sur la consommation du débit alloué. DynamoDB détermine les unités de capacité consommées en fonction de la taille d’un élément, et non du volume de données renvoyées à une application.

**Mots réservés et caractères spéciaux**

DynamoDB comporte des mots réservés et des caractères spéciaux. DynamoDB vous permet d’utiliser ces mots réservés et ces caractères spéciaux pour les noms, mais nous vous recommandons d’éviter de le faire, car vous devez utiliser des alias pour eux chaque fois que vous utilisez ces noms dans une expression. Pour obtenir la liste complète, consultez [Mots réservés dans DynamoDB](ReservedWords.md).

Vous devez utiliser des noms d’attributs d’expression à la place du nom réel si : 
+ le nom d’attribut figure dans la liste des mots réservés dans DynamoDB ;
+ le nom d’attribut ne répond pas à l’exigence que le premier caractère soit `a-z` ou `A-Z` et le second (le cas échéant) soit `a-Z`, `A-Z` ou `0-9` ;
+ le nom d’attribut comporte un signe **\$1** (dièse) ou **:** (deux-points).

L' AWS CLI exemple suivant montre comment utiliser une expression de projection avec une `GetItem` opération. Cette expression de projection récupère un attribut scalaire de niveau supérieur (`Description`), le premier élément d’une liste (`RelatedItems[0]`) et une liste imbriquée dans un mappage (`ProductReviews.FiveStar`).

```
aws dynamodb get-item \
    --table-name ProductCatalog \
    --key '"Id": { "N": "123" } \
    --projection-expression "Description, RelatedItems[0], ProductReviews.FiveStar"
```

Le code JSON suivant serait renvoyé pour cet exemple.

```
{
    "Item": {
        "Description": {
            "S": "123 description"
        },
        "ProductReviews": {
            "M": {
                "FiveStar": {
                    "L": [
                        {
                            "S": "Excellent! Can't recommend it highly enough! Buy it!"
                        },
                        {
                            "S": "Do yourself a favor and buy this."
                        }
                    ]
                }
            }
        },
        "RelatedItems": {
            "L": [
                {
                    "N": "341"
                }
            ]
        }
    }
}
```

# Utilisation d’expressions de mise à jour dans DynamoDB
<a name="Expressions.UpdateExpressions"></a>

L’opération `UpdateItem` met à jour un élément existant ou ajoute un nouvel élément à la table si celui-ci n’existe pas déjà. Vous devez fournir la clé de l’élément que vous souhaitez mettre à jour. Vous devez également fournir une expression de mise à jour, en indiquant les attributs que vous souhaitez modifier et les valeurs que vous souhaitez leur affecter. 

Une *expression de mise à jour* spécifie comment l’opération `UpdateItem` doit modifier les attributs d’un élément, par exemple en définissant une valeur scalaire ou en supprimant des éléments d’une liste ou d’un mappage.

Voici un résumé de la syntaxe des expressions de mise à jour :

```
update-expression ::=
    [ SET action [, action] ... ]
    [ REMOVE action [, action] ...]
    [ ADD action [, action] ... ]
    [ DELETE action [, action] ...]
```

Une expression de mise à jour se compose d’une ou de plusieurs clauses. Chaque clause commence par un mot clé `SET`, `REMOVE`, `ADD` ou `DELETE`. Vous pouvez inclure l’une de ces clauses dans une expression de mise à jour, dans n’importe quel ordre. Toutefois, chaque mot clé d’action peut n’apparaître qu’une seule fois.

Chaque clause comporte une ou plusieurs actions, séparées par des virgules. Chaque action représente une modification de données.

Les exemples de cette section sont basés sur l’élément `ProductCatalog` présenté dans [Utilisation d’expressions de projection dans DynamoDB](Expressions.ProjectionExpressions.md).

Les rubriques ci-dessous couvrent différents cas d’utilisation de l’action `SET`.

**Topics**
+ [SET – Modification ou ajout d’attributs d’élément](#Expressions.UpdateExpressions.SET)
+ [REMOVE – Suppression d’attributs d’un élément](#Expressions.UpdateExpressions.REMOVE)
+ [ADD – Mise à jour de nombres et d’ensembles](#Expressions.UpdateExpressions.ADD)
+ [DELETE – Suppression d’éléments d’un ensemble](#Expressions.UpdateExpressions.DELETE)
+ [Utilisation de plusieurs expressions de mise à jour](#Expressions.UpdateExpressions.Multiple)

## SET – Modification ou ajout d’attributs d’élément
<a name="Expressions.UpdateExpressions.SET"></a>

Ajoutez un ou plusieurs attributs à un élément à l’aide de l’action `SET` dans une expression de mise à jour. Si l’un de ces attributs existe déjà, il est remplacé par les nouvelles valeurs. Si vous souhaitez éviter de remplacer un attribut existant, vous pouvez utiliser l’action `SET` avec la fonction `if_not_exists`. La fonction `if_not_exists` est spécifique à l’action `SET` et utilisable uniquement dans une expression de mise à jour.

Lorsque vous utilisez `SET` pour mettre à jour un élément de la liste, le contenu de cet élément est remplacé par les nouvelles données que vous spécifiez. Si l’élément n’existe pas déjà, `SET` ajoute le nouvel élément à la fin de la liste.

Si vous ajoutez plusieurs éléments dans une seule opération `SET`, les éléments sont triés dans l’ordre par numéro d’élément.

Vous pouvez également effectuer un ajout ou une soustraction à un attribut de type `Number` à l’aide de `SET`. Afin d’effectuer plusieurs actions `SET`, séparez-les par des virgules.

Dans le récapitulatif de la syntaxe suivante :
+ L'*path*élément est le chemin du document vers l'élément.
+ Un **operand**élément peut être un chemin de document vers un élément ou une fonction.

```
set-action ::=
    path = value

value ::=
    operand
    | operand '+' operand
    | operand '-' operand

operand ::=
    path | function

function ::=
    if_not_exists (path, value)
```

Si l’élément ne contient pas d’attribut au chemin d’accès spécifié, la fonction `if_not_exists` prend la valeur `value`. Dans le cas contraire, elle prend la valeur `path`.

L’opération `PutItem` suivante crée un exemple d’élément auquel nous ferons référence dans les exemples.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

Les arguments de la fonction `--item` sont stockés dans le fichier `item.json`. Dans un souci de simplicité, seuls quelques attributs sont utilisés.

```
{
    "Id": {"N": "789"},
    "ProductCategory": {"S": "Home Improvement"},
    "Price": {"N": "52"},
    "InStock": {"BOOL": true},
    "Brand": {"S": "Acme"}
}
```

**Topics**
+ [Modification d’attributs](#Expressions.UpdateExpressions.SET.ModifyingAttributes)
+ [Ajout de listes et de mappages](#Expressions.UpdateExpressions.SET.AddingListsAndMaps)
+ [Ajout d’éléments à une liste](#Expressions.UpdateExpressions.SET.AddingListElements)
+ [Ajout d’attributs de mappage imbriqués](#Expressions.UpdateExpressions.SET.AddingNestedMapAttributes)
+ [Incrémentation et décrémentation d’attributs numériques](#Expressions.UpdateExpressions.SET.IncrementAndDecrement)
+ [Ajout d’éléments à une liste](#Expressions.UpdateExpressions.SET.UpdatingListElements)
+ [Empêcher le remplacement d’un attribut existant](#Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites)

### Modification d’attributs
<a name="Expressions.UpdateExpressions.SET.ModifyingAttributes"></a>

**Example**  
Mettez à jour les attributs `ProductCategory` et `Price`.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET ProductCategory = :c, Price = :p" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":c": { "S": "Hardware" },
    ":p": { "N": "60" }
}
```

**Note**  
Dans l’opération `UpdateItem`, `--return-values ALL_NEW` amène DynamoDB à renvoyer l’élément tel qu’il s’affiche après la mise à jour.

### Ajout de listes et de mappages
<a name="Expressions.UpdateExpressions.SET.AddingListsAndMaps"></a>

**Example**  
Ajoutez une nouvelle liste et un nouveau mappage.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems = :ri, ProductReviews = :pr" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":ri": {
        "L": [
            { "S": "Hammer" }
        ]
    },
    ":pr": {
        "M": {
            "FiveStar": {
                "L": [
                    { "S": "Best product ever!" }
                ]
            }
        }
    }
}
```

### Ajout d’éléments à une liste
<a name="Expressions.UpdateExpressions.SET.AddingListElements"></a>

**Example**  
Ajoutez un nouvel attribut à la liste `RelatedItems`. (N’oubliez pas que les éléments de liste sont en base zéro, donc [0] représente le premier élément dans la liste, [1] représente le deuxième et ainsi de suite.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :ri" \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":ri": { "S": "Nails" }
}
```

**Note**  
Lorsque vous utilisez `SET` pour mettre à jour un élément de la liste, le contenu de cet élément est remplacé par les nouvelles données que vous spécifiez. Si l’élément n’existe pas déjà, `SET` ajoute le nouvel élément à la fin de la liste.  
Si vous ajoutez plusieurs éléments dans une seule opération `SET`, les éléments sont triés dans l’ordre par numéro d’élément.

### Ajout d’attributs de mappage imbriqués
<a name="Expressions.UpdateExpressions.SET.AddingNestedMapAttributes"></a>

**Example**  
Ajoutez certains attributs de mappage imbriqués.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #pr.#5star[1] = :r5, #pr.#3star = :r3" \
    --expression-attribute-names file://names.json \
    --expression-attribute-values file://values.json \
    --return-values ALL_NEW
```
Les arguments de la fonction `--expression-attribute-names` sont stockés dans le fichier `names.json`.  

```
{
    "#pr": "ProductReviews",
    "#5star": "FiveStar",
    "#3star": "ThreeStar"
}
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":r5": { "S": "Very happy with my purchase" },
    ":r3": {
        "L": [
            { "S": "Just OK - not that great" }
        ]
    }
}
```

**Important**  
Vous ne pouvez pas mettre à jour les attributs de carte imbriqués si la carte parent n'existe pas. Si vous tentez de mettre à jour un attribut imbriqué (par exemple,`ProductReviews.FiveStar`) alors que la carte parent (`ProductReviews`) n'existe pas, DynamoDB renvoie `ValidationException` un avec le *message « Le chemin du document fourni dans l'expression de mise à jour n'est pas valide pour la mise à jour* ».  
Lorsque vous créez des éléments dont les attributs de carte imbriqués seront mis à jour ultérieurement, initialisez des cartes vides pour les attributs parents. Par exemple :  

```
{
    "Id": {"N": "789"},
    "ProductReviews": {"M": {}},
    "Metadata": {"M": {}}
}
```
Cela vous permet de mettre à jour les attributs imbriqués `ProductReviews.FiveStar` sans erreur.

### Incrémentation et décrémentation d’attributs numériques
<a name="Expressions.UpdateExpressions.SET.IncrementAndDecrement"></a>

Vous pouvez effectuer un ajout ou une soustraction à un attribut numérique existant. Pour ce faire, utilisez les opérateurs `+` (plus) et `-` (moins).

**Example**  
Réduisez l’attribut `Price` d’un élément.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```
Augmentez l’attribut `Price` à l’aide de l’opérateur `+` dans l’expression de mise à jour.

### Ajout d’éléments à une liste
<a name="Expressions.UpdateExpressions.SET.UpdatingListElements"></a>

Vous pouvez ajouter des éléments à la fin d’une liste. Pour ce faire, utilisez `SET` avec la fonction `list_append`. (Le nom de fonction respecte la casse.) La fonction `list_append` est spécifique à l’action `SET` et utilisable uniquement dans une expression de mise à jour. La syntaxe est la suivante.
+ `list_append (list1, list2)`

La fonction prend deux listes en entrée et ajoute tous les éléments de `list2` à ` list1`.

**Example**  
Dans [Ajout d’éléments à une liste](#Expressions.UpdateExpressions.SET.AddingListElements), vous créez la liste `RelatedItems` et la renseignez avec deux éléments : `Hammer` et `Nails`. Vous allez maintenant ajouter deux autres éléments à la fin de `RelatedItems`.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(#ri, :vals)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values file://values.json  \
    --return-values ALL_NEW
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":vals": {
        "L": [
            { "S": "Screwdriver" },
            {"S": "Hacksaw" }
        ]
    }
}
```
Enfin, vous allez ajouter un autre élément au *début* de `RelatedItems`. Pour ce faire, permutez l’ordre des éléments `list_append`. (N’oubliez pas que la fonction `list_append` prend deux listes en entrée, puis ajoute la seconde liste à la première.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET #ri = list_append(:vals, #ri)" \
    --expression-attribute-names '{"#ri": "RelatedItems"}' \
    --expression-attribute-values '{":vals": {"L": [ { "S": "Chisel" }]}}' \
    --return-values ALL_NEW
```
L’attribut `RelatedItems` résultant comporte maintenant cinq éléments, dans l’ordre suivant : `Chisel`, `Hammer`, `Nails`, `Screwdriver`, `Hacksaw`.

### Empêcher le remplacement d’un attribut existant
<a name="Expressions.UpdateExpressions.SET.PreventingAttributeOverwrites"></a>

**Example**  
Définissez l’attribut `Price` d’un élément, mais seulement si l’élément ne possède pas déjà un attribut `Price`. (Si `Price` existe déjà, il ne se passe rien.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = if_not_exists(Price, :p)" \
    --expression-attribute-values '{":p": {"N": "100"}}' \
    --return-values ALL_NEW
```

## REMOVE – Suppression d’attributs d’un élément
<a name="Expressions.UpdateExpressions.REMOVE"></a>

Supprimez un ou plusieurs attributs d’un élément dans Amazon DynamoDB à l’aide de l’action `REMOVE` dans une expression de mise à jour. Afin d’effectuer plusieurs actions `REMOVE`, séparez-les par des virgules.

Voici un résumé de la syntaxe pour `REMOVE` dans une expression de mise à jour. Le seul opérande est le chemin d’accès au document pour l’attribut que vous souhaitez supprimer.

```
remove-action ::=
    path
```

**Example**  
Supprimez des attributs d’un élément. (Si les attributs n’existent pas, il ne se passe rien.)  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE Brand, InStock, QuantityOnHand" \
    --return-values ALL_NEW
```

### Suppression d’éléments d’une liste
<a name="Expressions.UpdateExpressions.REMOVE.RemovingListElements"></a>

Vous pouvez supprimer des éléments d’une liste à l’aide de `REMOVE`.

**Example**  
Dans [Ajout d’éléments à une liste](#Expressions.UpdateExpressions.SET.UpdatingListElements), vous avez modifié un attribut de liste (`RelatedItems`) de sorte qu’il comporte les cinq éléments suivants :   
+ `[0]`—`Chisel`
+ `[1]`—`Hammer`
+ `[2]`—`Nails`
+ `[3]`—`Screwdriver`
+ `[4]`—`Hacksaw`
L'exemple suivant AWS Command Line Interface (AWS CLI) supprime `Hammer` et `Nails` de la liste.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "REMOVE RelatedItems[1], RelatedItems[2]" \
    --return-values ALL_NEW
```
Après la suppression de `Hammer` et `Nails`, les éléments restants sont déplacés. La liste comporte désormais les éléments suivants :  
+ `[0]`—`Chisel`
+ `[1]`—`Screwdriver`
+ `[2]`—`Hacksaw`

## ADD – Mise à jour de nombres et d’ensembles
<a name="Expressions.UpdateExpressions.ADD"></a>

**Note**  
En général, nous recommandons d'utiliser `SET` plutôt que de `ADD` garantir des opérations idempotentes.

Ajoutez un nouvel attribut et ses valeurs à un élément à l’aide de l’action `ADD` dans une expression de mise à jour.

Si l’attribut existe déjà, le comportement d’`ADD` dépend du type de données de l’attribut :
+ Si l’attribut est un nombre et que la valeur que vous ajoutez est également un nombre, la valeur est ajoutée mathématiquement à l’attribut existant. (Si la valeur est un nombre négatif, elle est soustraite de l’attribut existant.)
+ Si l’attribut est un ensemble et que la valeur que vous ajoutez est également un ensemble, la valeur est ajoutée à l’ensemble existant.

**Note**  
L’action `ADD` prend uniquement en charge les données de type nombre et ensemble.

Afin d’effectuer plusieurs actions `ADD`, séparez-les par des virgules.

Dans le récapitulatif de la syntaxe suivante :
+ L'*path*élément est le chemin du document vers un attribut. L’attribut doit être un `Number` ou un type de données ensemble. 
+ L'*value*élément est un nombre que vous souhaitez ajouter à l'attribut (pour les types de `Number` données) ou un ensemble à ajouter à l'attribut (pour les types d'ensembles).

```
add-action ::=
    path value
```

Les rubriques ci-dessous couvrent différents cas d’utilisation de l’action `ADD`.

**Topics**
+ [Ajout d’un nombre](#Expressions.UpdateExpressions.ADD.Number)
+ [Ajout d’éléments à un ensemble](#Expressions.UpdateExpressions.ADD.Set)

### Ajout d’un nombre
<a name="Expressions.UpdateExpressions.ADD.Number"></a>

Supposons que l’attribut `QuantityOnHand` n’existe pas. L' AWS CLI exemple suivant définit `QuantityOnHand` la valeur 5.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD QuantityOnHand :q" \
    --expression-attribute-values '{":q": {"N": "5"}}' \
    --return-values ALL_NEW
```

Maintenant que `QuantityOnHand` existe, vous pouvez réexécuter l’exemple pour incrémenter `QuantityOnHand` de 5 chaque fois.

### Ajout d’éléments à un ensemble
<a name="Expressions.UpdateExpressions.ADD.Set"></a>

Supposons que l’attribut `Color` n’existe pas. L’exemple AWS CLI suivant définit `Color` sur un ensemble de chaîne avec deux éléments.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Orange", "Purple"]}}' \
    --return-values ALL_NEW
```

Maintenant que `Color` existe, vous pouvez lui ajouter de nouveaux éléments.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "ADD Color :c" \
    --expression-attribute-values '{":c": {"SS":["Yellow", "Green", "Blue"]}}' \
    --return-values ALL_NEW
```

## DELETE – Suppression d’éléments d’un ensemble
<a name="Expressions.UpdateExpressions.DELETE"></a>

**Important**  
L’action `DELETE` prend uniquement en charge les types de données `Set`.

Supprimez un ou plusieurs éléments d’un ensemble à l’aide de l’action `DELETE` dans une expression de mise à jour. Afin d’effectuer plusieurs actions `DELETE`, séparez-les par des virgules.

Dans le récapitulatif de la syntaxe suivante :
+ L'*path*élément est le chemin du document vers un attribut. L’attribut doit être un type de données ensemble.
+ *subset*Il s'agit d'un ou de plusieurs éléments que vous souhaitez supprimer*path*. Vous devez le spécifier *subset* en tant que type d'ensemble.

```
delete-action ::=
    path subset
```

**Example**  
Dans [Ajout d’éléments à un ensemble](#Expressions.UpdateExpressions.ADD.Set), vous créez l’ensemble de chaînes `Color`. Cet exemple supprime certains des éléments de cet ensemble.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "DELETE Color :p" \
    --expression-attribute-values '{":p": {"SS": ["Yellow", "Purple"]}}' \
    --return-values ALL_NEW
```

## Utilisation de plusieurs expressions de mise à jour
<a name="Expressions.UpdateExpressions.Multiple"></a>

Vous pouvez utiliser plusieurs actions dans une seule expression de mise à jour. Toutes les références d'attributs sont résolues en fonction de l'état de l'élément avant que l'une des actions ne soit appliquée.

**Example**  
Étant donné un élément`{"id": "1", "a": 1, "b": 2, "c": 3}`, l'expression suivante supprime `a` et déplace les valeurs de `b` et `c` :  

```
aws dynamodb update-item \
    --table-name test \
    --key '{"id":{"S":"1"}}' \
    --update-expression "REMOVE a SET b = a, c = b" \
    --return-values ALL_NEW
```
Le résultat est`{"id": "1", "b": 1, "c": 2}`. Même si elle `a` est supprimée et `b` réaffectée dans la même expression, les deux références retrouvent leurs valeurs d'origine.

**Example**  
Vous pouvez modifier la valeur d’un attribut et supprimer complètement un autre attribut à l’aide d’une action SET et d’une action REMOVE dans une seule instruction. Cette opération réduirait la valeur de l’attribut `Price` à 15 tout en supprimant l’attribut `InStock` de l’élément.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET Price = Price - :p REMOVE InStock" \
    --expression-attribute-values '{":p": {"N":"15"}}' \
    --return-values ALL_NEW
```

**Example**  
Vous pouvez ajouter des éléments à une liste tout en modifiant la valeur d’un autre attribut à l’aide de deux actions SET dans une seule instruction. Cette opération ajouterait « Nails » à l’attribut de liste `RelatedItems` et définirait également la valeur de l’attribut `Price` sur 21.  

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"789"}}' \
    --update-expression "SET RelatedItems[1] = :newValue, Price = :newPrice" \
    --expression-attribute-values '{":newValue": {"S":"Nails"}, ":newPrice": {"N":"21"}}'  \
    --return-values ALL_NEW
```

# Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB
<a name="Expressions.OperatorsAndFunctions"></a>

Manipulez les données d’une table DynamoDB à l’aide des opérations `PutItem`, `UpdateItem` et `DeleteItem`. Pour ces opérations de manipulation de données, vous pouvez préciser une expression de condition afin de déterminer les éléments à modifier. Si l’expression de condition a la valeur true, l’opération aboutit. Sinon, l’opération échoue.

Cette section traite des fonctions et mots clés intégrés pour l’écriture des expressions de filtre et de condition dans Amazon DynamoDB. Pour en savoir plus sur les fonctions et la programmation avec DynamoDB, consultez [Programmation avec DynamoDB et le AWS SDKs](Programming.md) et le [guide de référence de l’API DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/).

**Topics**
+ [Syntaxe des expressions de filtre et de condition](#Expressions.OperatorsAndFunctions.Syntax)
+ [Comparaisons](#Expressions.OperatorsAndFunctions.Comparators)
+ [Fonctions](#Expressions.OperatorsAndFunctions.Functions)
+ [Évaluations logiques](#Expressions.OperatorsAndFunctions.LogicalEvaluations)
+ [Parenthèses](#Expressions.OperatorsAndFunctions.Parentheses)
+ [Priorité des conditions](#Expressions.OperatorsAndFunctions.Precedence)

## Syntaxe des expressions de filtre et de condition
<a name="Expressions.OperatorsAndFunctions.Syntax"></a>

Dans le résumé de syntaxe suivant, un *operand* peut être le suivant : 
+ Nom d’attribut de niveau supérieur, par exemple `Id`, `Title`, `Description` ou `ProductCategory`
+ Chemin d’accès au document référençant un attribut imbriqué

```
condition-expression ::=
      operand comparator operand
    | operand BETWEEN operand AND operand
    | operand IN ( operand (',' operand (, ...) ))
    | function
    | condition AND condition
    | condition OR condition
    | NOT condition
    | ( condition )

comparator ::=
    =
    | <>
    | <
    | <=
    | >
    | >=

function ::=
    attribute_exists (path)
    | attribute_not_exists (path)
    | attribute_type (path, type)
    | begins_with (path, substr)
    | contains (path, operand)
    | size (path)
```

## Comparaisons
<a name="Expressions.OperatorsAndFunctions.Comparators"></a>

Comparez un opérande à une valeur unique à l’aide de ces comparateurs :
+ `a = b`— Vrai s'*a*il est égal à*b*.
+ `a <> b`— Vrai s'il n'*a*est pas égal à*b*.
+ `a < b`— C'est vrai si *a* c'est inférieur à*b*.
+ `a <= b`— Vrai s'*a*il est inférieur ou égal à*b*.
+ `a > b`— Vrai si la valeur *a* est supérieure à*b*.
+ `a >= b`— Vrai s'*a*il est supérieur ou égal à*b*.

Comparez un opérande à une plage de valeurs ou une liste énumérée de valeurs à l’aide des mots clés `BETWEEN` et `IN` :
+ `a BETWEEN b AND c`— Vrai s'*a*il est supérieur ou égal à*b*, et inférieur ou égal à*c*.
+ `a IN (b, c, d) `— Vrai s'il *a* est égal à n'importe quelle valeur de la liste, par exemple, n'importe laquelle de *b**c*, ou. *d* La liste peut comporter jusqu’à 100 valeurs séparées par des virgules.

## Fonctions
<a name="Expressions.OperatorsAndFunctions.Functions"></a>

Déterminez si un attribut existe dans un élément ou évaluez la valeur d’un attribut à l’aide des fonctions suivantes. Ces noms de fonction respectent la casse. Pour un attribut imbriqué, vous devez fournir le chemin d’accès au document complet.


****  

| Fonction | Description | 
| --- | --- | 
|  `attribute_exists (path)`  | True si l’élément comporte l’attribut spécifié par `path`. Exemple : Vérifier si un élément de la table `Product` a une image de vue de côté. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 
|  `attribute_not_exists (path)`  | True si l’attribut spécifié par `path` n’existe pas dans l’élément. Exemple : Vérifier si un élément possède un attribut `Manufacturer`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 
|  `attribute_type (path, type)`  |  True si l’attribut à l’emplacement spécifié est d’un type de données particulier. Le paramètre `type` doit avoir l’une des valeurs suivantes : [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Vous devez utiliser une valeur d’attribut d’expression pour le paramètre `type`. Exemple : Vérifier si l’attribut `QuantityOnHand` est de type List (liste). Dans cet exemple, `:v_sub` est un espace réservé pour la chaîne `L`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Vous devez utiliser une valeur d’attribut d’expression pour le paramètre `type`.   | 
|  `begins_with (path, substr)`  |  True si l’attribut spécifié par `path` commence par une sous-chaîne particulière. Exemple : Vérifier si les tout premiers caractères de l’URL de l’image de vue avant sont `http://`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `http://`.  | 
|  `contains (path, operand)`  | True si l’attribut spécifié par `path` est l’un des attributs suivants : [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) Si l’attribut spécifié par `path` est de type `String`, `operand` doit être de type `String`. Si l’attribut spécifié par `path` est de type `Set`, l’`operand` doit être le type d’élément de l’ensemble. Le chemin d’accès et l’opérande doivent être distincts. Autrement dit, `contains (a, a)` renvoie une erreur. Exemple : Vérifier si l’attribut `Brand` comporte la sous-chaîne `Company`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `Company`. Exemple : Vérifier si le produit est disponible en rouge. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html) La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `Red`. | 
|  `size (path)`  | Renvoie un nombre qui représente la taille d’un attribut. Voici les types de données valides à utiliser avec `size`.  Si l’attribut est de type `String`, `size` renvoie la longueur de la chaîne. Exemple : Vérifier si la longueur de la chaîne `Brand` est inférieure ou égale à 20 caractères. La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `20`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Si l’attribut est de type `Binary`, `size` renvoie le nombre d’octets de la valeur d’attribut. Exemple : supposez que l’élément `ProductCatalog` comporte un binary attribute nommé `VideoClip` qui comporte une courte vidéo du produit utilisé. L’expression suivante vérifie si `VideoClip` dépasse 64 000 octets. La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `64000`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Si l’attribut est un type de données `Set`, `size` renvoie le nombre d’éléments dans l’ensemble.  Exemple : Vérifier si le produit est disponible dans plusieurs couleurs. La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `1`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  Si l’attribut est de type `List` ou `Map`, `size` renvoie le nombre d’éléments enfants. Exemple : Vérifier si le nombre de révisions `OneStar` a dépassé un certain seuil. La valeur d’attribut d’expression `:v_sub` est un espace réservé pour `3`. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html)  | 

## Évaluations logiques
<a name="Expressions.OperatorsAndFunctions.LogicalEvaluations"></a>

Effectuez les évaluations logiques à l’aide des mots clés `AND`, `OR` et `NOT`. Dans la liste suivante, *a* et *b* représentez les conditions à évaluer.
+ `a AND b`— C'est vrai si *a* les deux *b* sont vrais.
+ `a OR b`— Vrai si l'un *a* ou l'autre *b* (ou les deux) sont vrais.
+ `NOT a`— Vrai si *a* c'est faux. Faux si *a* c'est vrai.

Voici un exemple de code avec AND dans une opération.

`dynamodb-local (*)> select * from exprtest where a > 3 and a < 5;`

## Parenthèses
<a name="Expressions.OperatorsAndFunctions.Parentheses"></a>

Modifiez la priorité d’une évaluation logique à l’aide de parenthèses. Supposons, par exemple, que les conditions *b* 1 *a* et 2 soient vraies et que cette condition *c* soit fausse. L’expression suivante a la valeur true :
+ `a OR b AND c`

Toutefois, si vous placez une condition entre parenthèses, elle est évaluée en premier. Par exemple, l’expression suivante a la valeur false :
+  `(a OR b) AND c`

**Note**  
Vous pouvez imbriquer des parenthèses dans une expression. Les parenthèses les plus intérieures sont évaluées en premier.

Voici un exemple de code avec des parenthèses dans une évaluation logique.

`dynamodb-local (*)> select * from exprtest where attribute_type(b, string) or ( a = 5 and c = “coffee”);`

## Priorité des conditions
<a name="Expressions.OperatorsAndFunctions.Precedence"></a>

 DynamoDB évalue les conditions de gauche à droite à l’aide des règles de priorité suivantes :
+ `= <> < <= > >=`
+ `IN`
+ `BETWEEN`
+ `attribute_exists attribute_not_exists begins_with contains`
+ Parenthèses
+ `NOT`
+ `AND`
+ `OR`

# Exemple de commande CLI d’expression de condition DynamoDB
<a name="Expressions.ConditionExpressions"></a>

Voici quelques AWS Command Line Interface (AWS CLI) exemples d'utilisation d'expressions de condition. Ces exemples sont basés sur la table `ProductCatalog`, qui a été présentée dans [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](Expressions.Attributes.md). La clé de partition de cette table est `Id` ; il n’y a aucune clé de tri. L’opération `PutItem` suivante crée un exemple d’élément `ProductCatalog` auquel nous ferons référence dans les exemples.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json
```

Les arguments de la fonction `--item` sont stockés dans le fichier `item.json`. Dans un souci de simplicité, seuls quelques attributs sont utilisés.

```
{
    "Id": {"N": "456" },
    "ProductCategory": {"S": "Sporting Goods" },
    "Price": {"N": "650" }
}
```

**Topics**
+ [Insertion conditionnelle](#Expressions.ConditionExpressions.PreventingOverwrites)
+ [Suppressions conditionnelles](#Expressions.ConditionExpressions.AdvancedComparisons)
+ [Mises à jour conditionnelles](#Expressions.ConditionExpressions.SimpleComparisons)
+ [Exemples d’expressions conditionnelles](#Expressions.ConditionExpressions.ConditionalExamples)

## Insertion conditionnelle
<a name="Expressions.ConditionExpressions.PreventingOverwrites"></a>

L’opération `PutItem` remplace un élément avec la même clé primaire (le cas échéant). Vous pouvez éviter cela à l’aide d’une expression de condition. Elle permet la poursuite de l’écriture seulement si l’élément en question ne possède pas déjà la même clé primaire.

L’exemple suivant vérifie si la clé primaire existe dans la table à l’aide de la fonction `attribute_not_exists()` avant de tenter l’opération d’écriture. 

**Note**  
Si votre clé primaire comprend à la fois une clé de partition (pk) et une clé de tri (sk), le paramètre vérifie si `attribute_not_exists(pk)` ET `attribute_not_exists(sk)` prennent la valeur true ou false avant de tenter l’opération d’écriture.

```
aws dynamodb put-item \
    --table-name ProductCatalog \
    --item file://item.json \
    --condition-expression "attribute_not_exists(Id)"
```

Si l’expression de condition prend la valeur false, DynamoDB renvoie le message d’erreur suivant : The conditional request failed (Échec de la demande conditionnelle).

**Note**  
Pour en savoir plus sur `attribute_not_exists` et d’autres fonctions, consultez [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md).

## Suppressions conditionnelles
<a name="Expressions.ConditionExpressions.AdvancedComparisons"></a>

Effectuez une suppression conditionnelle à l’aide d’une opération `DeleteItem` avec une expression de condition. L’expression de condition doit avoir la valeur true afin que l’opération aboutisse. Dans le cas contraire, l’opération échoue.

Tenez compte de l’élément défini ci-dessus.

Supposons maintenant que vous souhaitiez supprimer l’élément, mais uniquement dans les conditions suivantes :
+  L’attribut `ProductCategory` est soit « Sporting Goods » (Matériels de sport), soit « Gardening Supplies » (Articles de jardinerie).
+  La valeur de l’attribut `Price` est comprise entre 500 et 600.

L’exemple suivant tente de supprimer l’élément.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id":{"N":"456"}}' \
    --condition-expression "(ProductCategory IN (:cat1, :cat2)) and (Price between :lo and :hi)" \
    --expression-attribute-values file://values.json
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.

```
{
    ":cat1": {"S": "Sporting Goods"},
    ":cat2": {"S": "Gardening Supplies"},
    ":lo": {"N": "500"},
    ":hi": {"N": "600"}
}
```

**Note**  
Dans l’expression de condition, le signe `:` (deux points) indique une *valeur d’attribut d’expression*, c’est-à-dire un espace réservé pour une valeur réelle. Pour de plus amples informations, veuillez consulter [Utilisation de valeurs d’attributs d’expression dans DynamoDB](Expressions.ExpressionAttributeValues.md).  
Pour en savoir plus sur `IN`, `AND` et d’autres mots clés, consultez [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md).

Dans cet exemple, la comparaison `ProductCategory` a la valeur true, mais la comparaison `Price` a la valeur false. Par conséquent, l’expression de condition prend la valeur false et l’opération `DeleteItem` échoue.

## Mises à jour conditionnelles
<a name="Expressions.ConditionExpressions.SimpleComparisons"></a>

Effectuez une mise à jour conditionnelle à l’aide d’une opération `UpdateItem` avec une expression de condition. L’expression de condition doit avoir la valeur true afin que l’opération aboutisse. Dans le cas contraire, l’opération échoue.

**Note**  
`UpdateItem` prend également en charge les *expressions de mise à jour*, dans lesquelles vous spécifiez les modifications à apporter à un élément. Pour de plus amples informations, veuillez consulter [Utilisation d’expressions de mise à jour dans DynamoDB](Expressions.UpdateExpressions.md).

Supposons que vous commenciez avec l’élément défini ci-dessus.

L’exemple suivant effectue une opération `UpdateItem`. Elle tente de réduire la valeur de l’attribut `Price` d’un produit de 75, mais l’expression de condition empêche la mise à jour si la valeur actuelle de l’attribut `Price` est inférieure à 500.

```
aws dynamodb update-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --update-expression "SET Price = Price - :discount" \
    --condition-expression "Price > :limit" \
    --expression-attribute-values file://values.json
```

Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.

```
{
    ":discount": { "N": "75"},
    ":limit": {"N": "500"}
}
```

Si la valeur de départ de l’attribut `Price` est 650, l’opération `UpdateItem` réduit la valeur de l’attribut `Price` à 575. Si vous réexécutez l’opération `UpdateItem`, la valeur de l’attribut `Price` est réduite à 500. Si vous l’exécutez une troisième fois, l’expression de condition prend la valeur false et l’opération de mise à jour échoue.

**Note**  
Dans l’expression de condition, le signe `:` (deux points) indique une *valeur d’attribut d’expression*, c’est-à-dire un espace réservé pour une valeur réelle. Pour de plus amples informations, veuillez consulter [Utilisation de valeurs d’attributs d’expression dans DynamoDB](Expressions.ExpressionAttributeValues.md).  
Pour en savoir plus sur « *>* » et d’autres opérateurs, consultez [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md).

## Exemples d’expressions conditionnelles
<a name="Expressions.ConditionExpressions.ConditionalExamples"></a>

Pour en savoir plus sur les fonctions utilisées dans les exemples suivants, consultez [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md). Pour en savoir plus sur la spécification de différents types d’attributs dans une expression, consultez [Référencement d’attributs d’élément lors de l’utilisation d’expressions dans DynamoDB](Expressions.Attributes.md). 

### Vérification des attributs d’un élément
<a name="Expressions.ConditionExpressions.CheckingForAttributes"></a>

Vous pouvez vérifier l’existence (ou la non-existence) d’un attribut. Si l’expression de condition a la valeur true, l’opération aboutit. Dans le cas contraire, l’opération échoue.

L’exemple suivant supprime un produit seulement s’il ne possède pas d’attribut `Price` à l’aide de `attribute_not_exists`.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_not_exists(Price)"
```

DynamoDB fournit également une fonction `attribute_exists`. L’exemple suivant supprime un produit seulement si les commentaires le concernant sont négatifs.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_exists(ProductReviews.OneStar)"
```

### Vérification du type d’attribut
<a name="Expressions.ConditionExpressions.CheckingForAttributeType"></a>

Vous pouvez vérifier le type de données d’une valeur d’attribut à l’aide de la fonction `attribute_type`. Si l’expression de condition a la valeur true, l’opération aboutit. Dans le cas contraire, l’opération échoue.

L’exemple suivant supprime un produit seulement s’il possède un attribut `Color` de type String Set à l’aide de `attribute_type`. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "attribute_type(Color, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments pour `--expression-attribute-values` sont stockés dans le fichier expression-attribute-values .json.

```
{
    ":v_sub":{"S":"SS"}
}
```

### Vérification de la valeur de début de la chaîne
<a name="Expressions.ConditionExpressions.CheckingBeginsWith"></a>

Vous pouvez vérifier si une valeur d’attribut String commence par une sous-chaîne spécifique à l’aide de la fonction `begins_with`. Si l’expression de condition a la valeur true, l’opération aboutit. Dans le cas contraire, l’opération échoue. 

L’exemple suivant supprime un produit seulement si l’élément `FrontView` de la carte `Pictures` commence par une valeur spécifique à l’aide de `begins_with`.

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "begins_with(Pictures.FrontView, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments pour `--expression-attribute-values` sont stockés dans le fichier expression-attribute-values .json.

```
{
    ":v_sub":{"S":"http://"}
}
```

### Recherche d’un élément dans un ensemble
<a name="Expressions.ConditionExpressions.CheckingForContains"></a>

Vous pouvez rechercher un élément dans un ensemble ou rechercher une sous-chaîne dans une chaîne à l’aide de la fonction `contains`. Si l’expression de condition a la valeur true, l’opération aboutit. Dans le cas contraire, l’opération échoue. 

L’exemple suivant supprime un produit seulement si l’attribut de type String Set `Color` comporte un élément avec une valeur spécifique à l’aide de `contains`. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "contains(Color, :v_sub)" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments pour `--expression-attribute-values` sont stockés dans le fichier expression-attribute-values .json.

```
{
    ":v_sub":{"S":"Red"}
}
```

### Vérification de la taille d’une valeur d’attribut
<a name="Expressions.ConditionExpressions.CheckingForSize"></a>

Vous pouvez vérifier la taille d’une valeur d’attribut à l’aide de la fonction `size`. Si l’expression de condition a la valeur true, l’opération aboutit. Dans le cas contraire, l’opération échoue. 

L’exemple suivant supprime un produit seulement si la taille du binary attribute `VideoClip` est supérieure à `64000` octets à l’aide de `size`. 

```
aws dynamodb delete-item \
    --table-name ProductCatalog \
    --key '{"Id": {"N": "456"}}' \
    --condition-expression "size(VideoClip) > :v_sub" \
    --expression-attribute-values file://expression-attribute-values.json
```

Les arguments pour `--expression-attribute-values` sont stockés dans le fichier expression-attribute-values .json.

```
{
    ":v_sub":{"N":"64000"}
}
```

# Utilisation de la durée de vie (TTL) dans DynamoDB
<a name="TTL"></a>

La durée de vie (TTL) de DynamoDB est une méthode économique pour supprimer les éléments qui ne sont plus pertinents. Elle vous permet de définir un horodatage d’expiration par élément pour indiquer quand cet élément n’est plus nécessaire. DynamoDB supprime automatiquement les éléments ayant expiré quelques jours après leur date d’expiration, sans consommer de débit d’écriture. 

Pour utiliser la TTL, activez-la d’abord sur une table, puis définissez un attribut spécifique pour stocker l’horodatage d’expiration de la TTL. L'horodatage doit être stocké sous la forme d'un type de données [numérique](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes) au [format Epoch Time Unix](https://en.wikipedia.org/wiki/Unix_time) avec une granularité en secondes. Les éléments dont l'attribut TTL n'est pas de type numérique sont ignorés par le processus TTL. Chaque fois qu’un élément est créé ou mis à jour, vous pouvez calculer le délai d’expiration et l’enregistrer dans l’attribut TTL.

Les éléments dont les attributs TTL sont valides et ayant expiré peuvent être supprimés par le système à tout moment, généralement quelques jours après leur expiration. Vous pouvez à tout moment mettre à jour les éléments ayant expiré qui sont en attente de suppression, notamment en modifiant ou en supprimant leurs attributs TTL. Lors de la mise à jour d’un élément ayant expiré, nous vous recommandons d’utiliser une expression conditionnelle pour vous assurer que l’élément n’a pas été supprimé ultérieurement. Utilisez des expressions de filtre pour supprimer les éléments ayant expiré des résultats [Scan](Scan.md#Scan.FilterExpression) et [Query](Query.FilterExpression.md).

Les éléments supprimés fonctionnent de la même manière que ceux supprimés par le biais d’opérations de suppression classiques. Une fois supprimés, les éléments sont placés dans DynamoDB Streams sous forme de suppression de service au lieu d’être supprimés par l’utilisateur, et sont supprimés des index secondaires locaux et globaux comme avec les autres opérations de suppression. 

Si vous utilisez des [tables globales version 2019.11.21 (actuelle)](GlobalTables.md) et que vous utilisez également la fonctionnalité TTL, DynamoDB réplique les suppressions par TTL sur toutes les tables de réplica. La suppression par TTL initiale ne consomme pas d’unités de capacité d’écriture (WCU) dans la région dans laquelle l’expiration de la TTL a lieu. Toutefois, la suppression par TTL répliquée dans les tables de réplica consomme une unité de capacité d’écriture répliquée lorsque vous utilisez la capacité provisionnée ou une unité d’écriture répliquée lorsque vous utilisez le mode de capacité à la demande, dans chacune des régions de réplica, et des frais s’appliquent.

Pour plus d’informations sur TTL, veuillez consulter les rubriques suivantes :

**Topics**
+ [Activation de la durée de vie (TTL) dans DynamoDB](time-to-live-ttl-how-to.md)
+ [Calcul de la durée de vie (TTL) dans DynamoDB](time-to-live-ttl-before-you-start.md)
+ [Utilisation des éléments ayant expiré et de la durée de vie (TTL)](ttl-expired-items.md)

# Activation de la durée de vie (TTL) dans DynamoDB
<a name="time-to-live-ttl-how-to"></a>

**Note**  
Pour faciliter le débogage et la vérification de la fonctionnalité TTL, les valeurs fournies pour la TTL de l’élément sont journalisées en texte brut dans les journaux de diagnostic DynamoDB.

Vous pouvez activer le TTL dans la console Amazon DynamoDB, le () AWS Command Line Interface , ou en utilisant AWS CLI le [Amazon DynamoDB API Reference avec n'importe lequel des supposés](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/). AWS SDKs L’activation de la durée de vie (TTL) sur toutes les partitions prend environ une heure.

## Activer DynamoDB TTL à l'aide de la console AWS
<a name="time-to-live-ttl-how-to-enable-console"></a>

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Choisissez **Tables**, puis choisissez la table à modifier.

1. Dans l’onglet **Paramètres supplémentaires**, dans la section **Durée de vie (TTL)**, choisissez **Activer**.

1. Lorsque vous activez TTL sur une table, vous devez identifier un nom d’attribut spécifique que le service DynamoDB recherchera pour déterminer si un élément peut faire l’objet d’une expiration. Le nom de l’attribut TTL, illustré ci-dessous, distingue les majuscules et minuscules et doit correspondre à l’attribut défini dans vos opérations de lecture et d’écriture. En cas de non-concordance, les éléments ayant expiré ne seront pas supprimés. Pour renommer l’attribut TTL, vous devez le désactiver, puis le réactiver avec le nouveau nom. La TTL continue à traiter les suppressions pendant environ 30 minutes après sa désactivation. Elle doit être reconfigurée sur les tables restaurées.  
![\[Nom d’attribut TTL (distinguant majuscules et minuscules) utilisé par DynamoDB pour déterminer si un élément doit expirer.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/EnableTTL-Settings.png)

1. (Facultatif) Vous pouvez effectuer un test en simulant la date et l’heure de l’expiration et en faisant correspondre quelques éléments. Cela vous fournit un exemple de liste d’éléments et confirme qu’il existe des éléments contenant le nom d’attribut TTL fourni avec la date d’expiration.

Une fois que la TTL est activée, l’attribut TTL est marqué **TTL** lorsque vous affichez les éléments dans la console DynamoDB. Vous pouvez afficher la date et l’heure d’expiration d’un élément en faisant passer votre souris au-dessus de l’attribut. 

## Activation de la TTL DynamoDB à l’aide de l’API
<a name="time-to-live-ttl-how-to-enable-api"></a>

------
#### [ Python ]

Vous pouvez activer le TTL avec du code à l'aide de l'[UpdateTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/update_time_to_live.html)opération.

```
import boto3


def enable_ttl(table_name, ttl_attribute_name):
    """
    Enables TTL on DynamoDB table for a given attribute name
        on success, returns a status code of 200
        on error, throws an exception

    :param table_name: Name of the DynamoDB table
    :param ttl_attribute_name: The name of the TTL attribute being provided to the table.
    """
    try:
        dynamodb = boto3.client('dynamodb')

        # Enable TTL on an existing DynamoDB table
        response = dynamodb.update_time_to_live(
            TableName=table_name,
            TimeToLiveSpecification={
                'Enabled': True,
                'AttributeName': ttl_attribute_name
            }
        )

        # In the returned response, check for a successful status code.
        if response['ResponseMetadata']['HTTPStatusCode'] == 200:
            print("TTL has been enabled successfully.")
        else:
            print(f"Failed to enable TTL, status code {response['ResponseMetadata']['HTTPStatusCode']}")
    except Exception as ex:
        print("Couldn't enable TTL in table %s. Here's why: %s" % (table_name, ex))
        raise


# your values
enable_ttl('your-table-name', 'expirationDate')
```

Vous pouvez confirmer que le TTL est activé à l'aide de l'[DescribeTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/describe_time_to_live.html)opération, qui décrit l'état du TTL sur une table. L’état `TimeToLive` est `ENABLED` ou `DISABLED`.

```
# create a DynamoDB client
dynamodb = boto3.client('dynamodb')

# set the table name
table_name = 'YourTable'

# describe TTL
response = dynamodb.describe_time_to_live(TableName=table_name)
```

------
#### [ JavaScript ]

Vous pouvez activer le TTL avec du code à l'aide de l'[UpdateTimeToLiveCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-dynamodb/Class/UpdateTimeToLiveCommand/)opération.

```
import { DynamoDBClient, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";

const enableTTL = async (tableName, ttlAttribute) => {

    const client = new DynamoDBClient({});

    const params = {
        TableName: tableName,
        TimeToLiveSpecification: {
            Enabled: true,
            AttributeName: ttlAttribute
        }
    };

    try {
        const response = await client.send(new UpdateTimeToLiveCommand(params));
        if (response.$metadata.httpStatusCode === 200) {
            console.log(`TTL enabled successfully for table ${tableName}, using attribute name ${ttlAttribute}.`);
        } else {
            console.log(`Failed to enable TTL for table ${tableName}, response object: ${response}`);
        }
        return response;
    } catch (e) {
        console.error(`Error enabling TTL: ${e}`);
        throw e;
    }
};

// call with your own values
enableTTL('ExampleTable', 'exampleTtlAttribute');
```

------

## Activez Time to Live à l'aide du AWS CLI
<a name="time-to-live-ttl-how-to-enable-cli-sdk"></a>

1. Active TTL sur la table `TTLExample`.

   ```
   aws dynamodb update-time-to-live --table-name TTLExample --time-to-live-specification "Enabled=true, AttributeName=ttl"
   ```

1. Décrit TTL sur la table `TTLExample`.

   ```
   aws dynamodb describe-time-to-live --table-name TTLExample
   {
       "TimeToLiveDescription": {
           "AttributeName": "ttl",
           "TimeToLiveStatus": "ENABLED"
       }
   }
   ```

1. Ajoutez un élément à la table `TTLExample` avec l’attribut de TTL défini à l’aide du shell BASH et de l’ AWS CLI. 

   ```
   EXP=`date -d '+5 days' +%s`
   aws dynamodb put-item --table-name "TTLExample" --item '{"id": {"N": "1"}, "ttl": {"N": "'$EXP'"}}'
   ```

Cet exemple démarre par la date actuelle à laquelle cinq jours sont ajoutés pour créer une date d’expiration. Il a ensuite converti l’heure d’expiration en heure au format epoch pour ajouter en dernier lieu un élément à la table « `TTLExample` ». 

**Note**  
 Pour définir des valeurs d’expiration pour TTL, l’une des méthodes à votre disposition consiste à calculer le nombre de secondes à ajouter à l’heure d’expiration. Par exemple, 5 jours équivalent à 432 000 secondes. Toutefois, il est souvent préférable de commencer par une date et de définir le reste en fonction de celle-ci.

Il est relativement simple d’obtenir l’heure actuelle au format epoch, comme dans l’exemple suivant.
+ Terminal Linux : `date +%s`
+ Python: `import time; int(time.time())`
+ Java: `System.currentTimeMillis() / 1000L`
+ JavaScript: `Math.floor(Date.now() / 1000)`

## Activez DynamoDB TTL à l'aide de CloudFormation
<a name="time-to-live-ttl-how-to-enable-cf"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  TTLExampleTable:
    Type: AWS::DynamoDB::Table
    Description: "A DynamoDB table with TTL Specification enabled"
    Properties:
      AttributeDefinitions:
        - AttributeName: "Album"
          AttributeType: "S"
        - AttributeName: "Artist"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Album"
          KeyType: "HASH"
        - AttributeName: "Artist"
          KeyType: "RANGE"
      ProvisionedThroughput:
        ReadCapacityUnits: "5"
        WriteCapacityUnits: "5"
      TimeToLiveSpecification:
        AttributeName: "TTLExampleAttribute"
        Enabled: true
```

Vous trouverez des informations supplémentaires sur l'utilisation du TTL dans vos CloudFormation modèles [ici](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html).

# Calcul de la durée de vie (TTL) dans DynamoDB
<a name="time-to-live-ttl-before-you-start"></a>

Une méthode courante pour implémenter la durée de vie, ou TTL, consiste à définir un délai d’expiration pour les éléments en fonction de leur date de création ou de dernière mise à jour. Cela peut être fait en ajoutant l’heure aux horodatages `createdAt` et `updatedAt`. Par exemple, la TTL des éléments qui viennent d’être créés peut être défini sur `createdAt` \$1 90 jours. Lorsque l’élément est mis à jour, la TTL peut être recalculée sur `updatedAt` \$1 90 jours.

Le délai d’expiration calculé doit être au format epoch, en secondes. Pour que l’expiration et la suppression soient prises en compte, la TTL ne doit pas dater de plus de cinq ans. Si vous utilisez un autre format, les processus TTL ignorent l’élément. Si vous définissez le délai d'expiration à un moment futur où vous souhaitez que l'article expire, l'article expirera après cette date. Supposons, par exemple, que vous définissiez l'heure d'expiration sur 1724241326 (c'est-à-dire le lundi 21 août 2024 11:55:26 (UTC)). L'article expire après le délai spécifié. Il n'y a pas de durée TTL minimale. Vous pouvez définir l'heure d'expiration à n'importe quelle date future, par exemple 5 minutes à compter de l'heure actuelle. Toutefois, DynamoDB supprime généralement les éléments expirés dans les 48 heures suivant leur date d'expiration, et non immédiatement après leur expiration.

**Topics**
+ [Création d’un élément et définition de la durée de vie (TTL)](#time-to-live-ttl-before-you-start-create)
+ [Mise à jour d’un élément et actualisation de la durée de vie (TTL)](#time-to-live-ttl-before-you-start-update)

## Création d’un élément et définition de la durée de vie (TTL)
<a name="time-to-live-ttl-before-you-start-create"></a>

L’exemple suivant montre comment calculer le délai d’expiration lors de la création d’un élément, en utilisant `expireAt` comme nom d’attribut TTL. Une instruction d’affectation obtient l’heure actuelle sous forme de variable. Dans l’exemple, le délai d’expiration est calculé comme étant de 90 jours à compter de l’heure actuelle. L’heure est ensuite convertie au format epoch et enregistrée sous forme de type de données « entier » dans l’attribut TTL.

Les exemples de code suivants montrent comment créer un élément avec une TTL.

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

**SDK pour Java 2.x**  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * Creates an item in a DynamoDB table with TTL attributes.
 * This class demonstrates how to add TTL expiration timestamps to DynamoDB items.
 */
public class CreateTTL {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String CREATION_DATE_ATTR = "creationDate";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String SUCCESS_MESSAGE = "%s PutItem operation with TTL successful.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs a CreateTTL instance with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public CreateTTL(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Constructs a CreateTTL with a default DynamoDB client.
     */
    public CreateTTL() {
        this.dynamoDbClient = null;
    }

    /**
     * Main method to demonstrate creating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new CreateTTL().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and create an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final CreateTTL createTTL = new CreateTTL(ddb);
            createTTL.createItemWithTTL(tableName, primaryKey, sortKey);
            return 0;
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * Creates an item in the specified table with TTL attributes.
     *
     * @param tableName The name of the table
     * @param primaryKeyValue The value for the primary key
     * @param sortKeyValue The value for the sort key
     * @return The response from the PutItem operation
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     */
    public PutItemResponse createItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long createDate = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = createDate + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        final Map<String, AttributeValue> itemMap = new HashMap<>();
        itemMap.put(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        itemMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());
        itemMap.put(
            CREATION_DATE_ATTR,
            AttributeValue.builder().n(String.valueOf(createDate)).build());
        itemMap.put(
            EXPIRE_AT_ATTR,
            AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final PutItemRequest request =
            PutItemRequest.builder().tableName(tableName).item(itemMap).build();

        try {
            final PutItemResponse response = dynamoDbClient.putItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  Pour plus de détails sur l'API, reportez-vous [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)à la section *Référence des AWS SDK for Java 2.x API*. 

------
#### [ JavaScript ]

**SDK pour JavaScript (v3)**  

```
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";

export function createDynamoDBItem(table_name, region, partition_key, sort_key) {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    // Get the current time in epoch second format
    const current_time = Math.floor(new Date().getTime() / 1000);

    // Calculate the expireAt time (90 days from now) in epoch second format
    const expire_at = Math.floor((new Date().getTime() + 90 * 24 * 60 * 60 * 1000) / 1000);

    // Create DynamoDB item
    const item = {
        'partitionKey': {'S': partition_key},
        'sortKey': {'S': sort_key},
        'createdAt': {'N': current_time.toString()},
        'expireAt': {'N': expire_at.toString()}
    };

    const putItemCommand = new PutItemCommand({
        TableName: table_name,
        Item: item,
        ProvisionedThroughput: {
            ReadCapacityUnits: 1,
            WriteCapacityUnits: 1,
        },
    });

    client.send(putItemCommand, function(err, data) {
        if (err) {
            console.log("Exception encountered when creating item %s, here's what happened: ", data, err);
            throw err;
        } else {
            console.log("Item created successfully: %s.", data);
            return data;
        }
    });
}

// Example usage (commented out for testing)
// createDynamoDBItem('your-table-name', 'us-east-1', 'your-partition-key-value', 'your-sort-key-value');
```
+  Pour plus de détails sur l'API, reportez-vous [PutItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/PutItemCommand)à la section *Référence des AWS SDK pour JavaScript API*. 

------
#### [ Python ]

**Kit SDK for Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def create_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Creates a DynamoDB item with an attached expiry attribute.

    :param table_name: Table name for the boto3 resource to target when creating an item
    :param region: string representing the AWS region. Example: `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :return: Void (nothing)
    """
    try:
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expiration time (90 days from now) in epoch second format
        expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())

        item = {
            "primaryKey": primary_key,
            "sortKey": sort_key,
            "creationDate": current_time,
            "expireAt": expiration_time,
        }
        response = table.put_item(Item=item)

        print("Item created successfully.")
        return response
    except Exception as e:
        print(f"Error creating item: {e}")
        raise e


# Use your own values
create_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Pour plus de détails sur l'API, consultez [PutItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/PutItem)le *AWS manuel de référence de l'API SDK for Python (Boto3*). 

------

## Mise à jour d’un élément et actualisation de la durée de vie (TTL)
<a name="time-to-live-ttl-before-you-start-update"></a>

Cet exemple est la suite de la [section précédente](#time-to-live-ttl-before-you-start-create). Le délai d’expiration peut être recalculé si l’élément est mis à jour. L’exemple suivant recalcule l’horodatage `expireAt` pour qu’il corresponde à 90 jours à partir de l’heure actuelle.

Les exemples de code suivants montrent comment mettre à jour la TTL d’un élément.

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

**SDK pour Java 2.x**  
Mise à jour de la TTL sur un élément DynamoDB existant dans une table.  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

    public UpdateItemResponse updateItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = new HashMap<>();
        keyMap.put(PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        keyMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build());
        expressionAttributeValues.put(
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try {
            final UpdateItemResponse response = dynamoDbClient.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
```
+  Pour plus de détails sur l'API, reportez-vous [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)à la section *Référence des AWS SDK for Java 2.x API*. 

------
#### [ JavaScript ]

**SDK pour JavaScript (v3)**  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItem = async (tableName, partitionKey, sortKey, region = 'us-east-1') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);
    const expireAt = Math.floor((Date.now() + 90 * 24 * 60 * 60 * 1000) / 1000);

    const params = {
        TableName: tableName,
        Key: marshall({
            partitionKey: partitionKey,
            sortKey: sortKey
        }),
        UpdateExpression: "SET updatedAt = :c, expireAt = :e",
        ExpressionAttributeValues: marshall({
            ":c": currentTime,
            ":e": expireAt
        }),
    };

    try {
        const data = await client.send(new UpdateItemCommand(params));
        const responseData = unmarshall(data.Attributes);
        console.log("Item updated successfully: %s", responseData);
        return responseData;
    } catch (err) {
        console.error("Error updating item:", err);
        throw err;
    }
}

// Example usage (commented out for testing)
// updateItem('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Pour plus de détails sur l'API, reportez-vous [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)à la section *Référence des AWS SDK pour JavaScript API*. 

------
#### [ Python ]

**Kit SDK for Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def update_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Update an existing DynamoDB item with a TTL.
    :param table_name: Name of the DynamoDB table
    :param region: AWS Region of the table - example `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :return: Void (nothing)
    """
    try:
        # Create the DynamoDB resource.
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expireAt time (90 days from now) in epoch second format
        expire_at = int((datetime.now() + timedelta(days=90)).timestamp())

        table.update_item(
            Key={"partitionKey": primary_key, "sortKey": sort_key},
            UpdateExpression="set updatedAt=:c, expireAt=:e",
            ExpressionAttributeValues={":c": current_time, ":e": expire_at},
        )

        print("Item updated successfully.")
    except Exception as e:
        print(f"Error updating item: {e}")


# Replace with your own values
update_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Pour plus de détails sur l'API, consultez [UpdateItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)le *AWS manuel de référence de l'API SDK for Python (Boto3*). 

------

Les exemples de TTL présentés dans cette introduction illustrent une méthode permettant de garantir que seuls les éléments récemment mis à jour sont conservés dans une table. Les éléments mis à jour voient leur durée de vie prolongée, tandis que les éléments non mis à jour après leur création expirent et sont supprimés gratuitement, ce qui réduit le stockage utilisé et permet de maintenir les tables propres.

# Utilisation des éléments ayant expiré et de la durée de vie (TTL)
<a name="ttl-expired-items"></a>

Les éléments ayant expiré qui sont en attente de suppression peuvent être exclus des opérations de lecture et d’écriture. Cela est utile dans les scénarios où les données ayant expiré ne sont plus valides et ne doivent pas être utilisées. S’ils ne sont pas exclus, ils continueront à s’afficher dans les opérations de lecture et d’écriture jusqu’à ce qu’ils soient supprimés par le processus en arrière-plan.

**Note**  
Ces éléments sont toujours pris en compte dans les coûts de stockage et de lecture jusqu’à ce qu’ils soient supprimés.

Les suppressions par TTL peuvent être identifiées dans DynamoDB Streams, mais uniquement dans la région où la suppression a eu lieu. Les suppressions par TTL qui sont répliquées dans les régions de tables globales ne sont pas identifiables dans les flux DynamoDB des régions vers lesquelles la suppression est répliquée.

## Exclusion des éléments ayant expiré des opérations de lecture
<a name="ttl-expired-items-filter"></a>

Pour les opérations de lecture telles que [Scan](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) et [Query](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html), une expression de filtre peut exclure les éléments ayant expiré qui sont en attente de suppression. Comme indiqué dans l’extrait de code suivant, l’expression de filtre peut exclure les éléments dont la durée de vie, ou TTL, est inférieure ou égale à l’heure actuelle. Par exemple, le code du kit SDK Python inclut une instruction d’affectation qui obtient l’heure actuelle sous forme de variable (`now`) et la convertit en `int` au format d’heure epoch.

Les exemples de code suivants montrent l’interrogation d’éléments TTL.

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

**SDK pour Java 2.x**  
Expression filtrée par requête pour rassembler des éléments TTL dans une table DynamoDB à l'aide de. AWS SDK for Java 2.x  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.Map;
import java.util.Optional;

        final QueryRequest request = QueryRequest.builder()
            .tableName(tableName)
            .keyConditionExpression(KEY_CONDITION_EXPRESSION)
            .filterExpression(FILTER_EXPRESSION)
            .expressionAttributeNames(expressionAttributeNames)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final QueryResponse response = ddb.query(request);
            System.out.println("Query successful. Found " + response.count() + " items that have not expired yet.");

            // Print each item
            response.items().forEach(item -> {
                System.out.println("Item: " + item);
            });

            return 0;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
```
+  Pour plus d’informations sur l’API, consultez [Requête](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/Query) dans la *référence d’API AWS SDK for Java 2.x *. 

------
#### [ JavaScript ]

**SDK pour JavaScript (v3)**  
Expression filtrée par requête pour rassembler des éléments TTL dans une table DynamoDB à l'aide de. AWS SDK pour JavaScript  

```
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const queryFiltered = async (tableName, primaryKey, region = 'us-east-1') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);

    const params = {
        TableName: tableName,
        KeyConditionExpression: "#pk = :pk",
        FilterExpression: "#ea > :ea",
        ExpressionAttributeNames: {
            "#pk": "primaryKey",
            "#ea": "expireAt"
        },
        ExpressionAttributeValues: marshall({
            ":pk": primaryKey,
            ":ea": currentTime
        })
    };

    try {
        const { Items } = await client.send(new QueryCommand(params));
        Items.forEach(item => {
            console.log(unmarshall(item))
        });
        return Items;
    } catch (err) {
        console.error(`Error querying items: ${err}`);
        throw err;
    }
}

// Example usage (commented out for testing)
// queryFiltered('your-table-name', 'your-partition-key-value');
```
+  Pour plus d’informations sur l’API, consultez [Requête](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/QueryCommand) dans la *référence d’API AWS SDK pour JavaScript *. 

------
#### [ Python ]

**Kit SDK for Python (Boto3)**  
Expression filtrée par requête pour rassembler des éléments TTL dans une table DynamoDB à l'aide de. AWS SDK pour Python (Boto3)  

```
from datetime import datetime

import boto3


def query_dynamodb_items(table_name, partition_key):
    """

    :param table_name: Name of the DynamoDB table
    :param partition_key:
    :return:
    """
    try:
        # Initialize a DynamoDB resource
        dynamodb = boto3.resource("dynamodb", region_name="us-east-1")

        # Specify your table
        table = dynamodb.Table(table_name)

        # Get the current time in epoch format
        current_time = int(datetime.now().timestamp())

        # Perform the query operation with a filter expression to exclude expired items
        # response = table.query(
        #    KeyConditionExpression=boto3.dynamodb.conditions.Key('partitionKey').eq(partition_key),
        #    FilterExpression=boto3.dynamodb.conditions.Attr('expireAt').gt(current_time)
        # )
        response = table.query(
            KeyConditionExpression=dynamodb.conditions.Key("partitionKey").eq(partition_key),
            FilterExpression=dynamodb.conditions.Attr("expireAt").gt(current_time),
        )

        # Print the items that are not expired
        for item in response["Items"]:
            print(item)

    except Exception as e:
        print(f"Error querying items: {e}")


# Call the function with your values
query_dynamodb_items("Music", "your-partition-key-value")
```
+  Pour de plus amples informations sur l’API, consultez [Requête](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/Query) dans la *référence d’API AWS du kit SDK pour Python (Boto3)*. 

------

## Écriture conditionnelle sur les éléments ayant expiré
<a name="ttl-expired-items-conditional-write"></a>

Une expression conditionnelle peut être utilisée pour éviter les écritures sur les éléments ayant expiré. L’extrait de code ci-dessous est une mise à jour conditionnelle qui vérifie si le délai d’expiration est supérieur à l’heure actuelle. Si tel est le cas, l’opération d’écriture se poursuit.

Les exemples de code suivants montrent comment mettre à jour la TTL d’un élément de manière conditionnelle.

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

**SDK pour Java 2.x**  
Mettez à jour de la TTL sur un élément DynamoDB existant dans une table, avec une condition.  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.Map;
import java.util.Optional;

/**
 * Updates an item in a DynamoDB table with TTL attributes using a conditional expression.
 * This class demonstrates how to conditionally update TTL expiration timestamps.
 */
public class UpdateTTLConditional {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String UPDATED_AT_ATTR = "updatedAt";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String UPDATE_EXPRESSION = "SET " + UPDATED_AT_ATTR + "=:c, " + EXPIRE_AT_ATTR + "=:e";
    private static final String CONDITION_EXPRESSION = "attribute_exists(" + PRIMARY_KEY_ATTR + ")";
    private static final String SUCCESS_MESSAGE = "%s UpdateItem operation with TTL successful.";
    private static final String CONDITION_FAILED_MESSAGE = "Condition check failed. Item does not exist.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs an UpdateTTLConditional with a default DynamoDB client.
     */
    public UpdateTTLConditional() {
        this.dynamoDbClient = null;
    }

    /**
     * Constructs an UpdateTTLConditional with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public UpdateTTLConditional(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Main method to demonstrate conditionally updating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new UpdateTTLConditional().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and conditionally update an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = Map.of(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKey).build(),
            SORT_KEY_ATTR, AttributeValue.builder().s(sortKey).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = Map.of(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build(),
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .conditionExpression(CONDITION_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final UpdateItemResponse response = ddb.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return 0;
        } catch (ConditionalCheckFailedException e) {
            System.err.println(CONDITION_FAILED_MESSAGE);
            throw e;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  Pour plus de détails sur l'API, reportez-vous [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)à la section *Référence des AWS SDK for Java 2.x API*. 

------
#### [ JavaScript ]

**SDK pour JavaScript (v3)**  
Mettez à jour de la TTL sur un élément DynamoDB existant dans une table, avec une condition.  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItemConditional = async (tableName, partitionKey, sortKey, region = 'us-east-1', newAttribute = 'default-value') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);

    const params = {
        TableName: tableName,
        Key: marshall({
            artist: partitionKey,
            album: sortKey
        }),
        UpdateExpression: "SET newAttribute = :newAttribute",
        ConditionExpression: "expireAt > :expiration",
        ExpressionAttributeValues: marshall({
            ':newAttribute': newAttribute,
            ':expiration': currentTime
        }),
        ReturnValues: "ALL_NEW"
    };

    try {
        const response = await client.send(new UpdateItemCommand(params));
        const responseData = unmarshall(response.Attributes);
        console.log("Item updated successfully: ", responseData);
        return responseData;
    } catch (error) {
        if (error.name === "ConditionalCheckFailedException") {
            console.log("Condition check failed: Item's 'expireAt' is expired.");
        } else {
            console.error("Error updating item: ", error);
        }
        throw error;
    }
};

// Example usage (commented out for testing)
// updateItemConditional('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Pour plus de détails sur l'API, reportez-vous [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)à la section *Référence des AWS SDK pour JavaScript API*. 

------
#### [ Python ]

**Kit SDK for Python (Boto3)**  
Mettez à jour de la TTL sur un élément DynamoDB existant dans une table, avec une condition.  

```
from datetime import datetime, timedelta

import boto3
from botocore.exceptions import ClientError


def update_dynamodb_item_ttl(table_name, region, primary_key, sort_key, ttl_attribute):
    """
    Updates an existing record in a DynamoDB table with a new or updated TTL attribute.

    :param table_name: Name of the DynamoDB table
    :param region: AWS Region of the table - example `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :param ttl_attribute: name of the TTL attribute in the target DynamoDB table
    :return:
    """
    try:
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Generate updated TTL in epoch second format
        updated_expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())

        # Define the update expression for adding/updating a new attribute
        update_expression = "SET newAttribute = :val1"

        # Define the condition expression for checking if 'expireAt' is not expired
        condition_expression = "expireAt > :val2"

        # Define the expression attribute values
        expression_attribute_values = {":val1": ttl_attribute, ":val2": updated_expiration_time}

        response = table.update_item(
            Key={"primaryKey": primary_key, "sortKey": sort_key},
            UpdateExpression=update_expression,
            ConditionExpression=condition_expression,
            ExpressionAttributeValues=expression_attribute_values,
        )

        print("Item updated successfully.")
        return response["ResponseMetadata"]["HTTPStatusCode"]  # Ideally a 200 OK
    except ClientError as e:
        if e.response["Error"]["Code"] == "ConditionalCheckFailedException":
            print("Condition check failed: Item's 'expireAt' is expired.")
        else:
            print(f"Error updating item: {e}")
    except Exception as e:
        print(f"Error updating item: {e}")


# replace with your values
update_dynamodb_item_ttl(
    "your-table-name",
    "us-east-1",
    "your-partition-key-value",
    "your-sort-key-value",
    "your-ttl-attribute-value",
)
```
+  Pour plus de détails sur l'API, consultez [UpdateItem](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)le *AWS manuel de référence de l'API SDK for Python (Boto3*). 

------

## Identification des éléments supprimés dans DynamoDB Streams
<a name="ttl-expired-items-identifying"></a>

L’enregistrement de flux contient un champ d’identité utilisateur `Records[<index>].userIdentity`. Les éléments qui sont supprimés par le processus TTL ont les champs suivants :

```
Records[<index>].userIdentity.type
"Service"

Records[<index>].userIdentity.principalId
"dynamodb.amazonaws.com"
```

L’extrait JSON suivant montre la partie pertinente d’un seul enregistrement de flux :

```
"Records": [ 
  { 
	... 
		"userIdentity": {
		"type": "Service", 
      	"principalId": "dynamodb.amazonaws.com" 
   	} 
   ... 
	} 
]
```

# Interrogation de tables dans DynamoDB
<a name="Query"></a>

Vous pouvez utiliser l’opération d’API `Query` dans Amazon DynamoDB pour rechercher des éléments en fonction de valeurs de clé primaire.

Vous devez fournir le nom de l’attribut de clé de partition et une valeur unique pour cet attribut. `Query` retourne tous les éléments avec cette valeur de clé de partition. Vous pouvez le cas échéant fournir un attribut de clé de tri et utiliser un opérateur de comparaison pour affiner les résultats de recherche.

Pour plus d’informations sur l’utilisation`Query`, tels que la syntaxe de requête, les paramètres de réponse et d’autres exemples, voir[Interrogation](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)dans le*Amazon DynamoDB API Reference*.

**Topics**
+ [Expressions de condition clé pour l’opération Query dans DynamoDB](Query.KeyConditionExpressions.md)
+ [Expressions de filtre pour l’opération Query dans DynamoDB](Query.FilterExpression.md)
+ [Pagination des résultats de requête de table dans DynamoDB](Query.Pagination.md)
+ [Autres aspects de l’utilisation de l’opération Query dans DynamoDB](Query.Other.md)

# Expressions de condition clé pour l’opération Query dans DynamoDB
<a name="Query.KeyConditionExpressions"></a>

Vous pouvez utiliser n’importe quel nom dans une expression de condition de clé, sous réserve que le premier caractère soit `a-z` ou `A-Z` et que les autres caractères (à compter du deuxième caractère s’il y en a un) soit `a-z`, `A-Z` ou `0-9`. En outre, le nom d’attribut ne doit pas être un mot réservé DynamoDB. (Pour en obtenir la liste complète, consultez [Mots réservés dans DynamoDB](ReservedWords.md).) Si un nom d’attribut ne répond pas à ces exigences, vous devez définir un nom d’attribut d’expression comme espace réservé. Pour de plus amples informations, veuillez consulter [Noms d’attributs d’expression (alias) dans DynamoDB](Expressions.ExpressionAttributeNames.md).

Pour les éléments avec une valeur de clé de partition donnée, DynamoDB stocke ces éléments proches les uns des autres, triés par valeur de clé de tri. Dans une opération `Query`, DynamoDB récupère les éléments en ordre trié, puis traite les éléments à l’aide d’une `KeyConditionExpression` et d’une `FilterExpression` éventuellement présente. Alors seulement les résultats de `Query` sont renvoyés au client.

Une opération `Query` retourne toujours un ensemble de résultats. Si aucun élément correspondant n’est trouvé, le jeu de résultats est vide.

Les résultats de `Query` sont toujours triés sur la valeur de la clé de tri. Si le type de données de la clé de tri est `Number`, les résultats sont retournés par ordre numérique. Sinon, les résultats sont retournés dans l’ordre des octets UTF-8. Par défaut, l’ordre de tri est croissant. Pour inverser l’ordre, définissez le paramètre `ScanIndexForward` sur `false`.

Une seule opération `Query` peut extraire au maximum 1 Mo de données. Cette limite s’applique avant qu’une `FilterExpression` ou `ProjectionExpression` ne soit appliquée aux résultats. Si `LastEvaluatedKey` est présent dans la réponse et n’a pas la valeur null, vous devez paginer le jeu de résultats (voir [Pagination des résultats de requête de table dans DynamoDB](Query.Pagination.md)).

## Exemples d’expression de condition clé
<a name="Query.KeyConditionExpressions-example"></a>

Pour spécifier les critères de recherche, vous utilisez une *expression de condition de clé*, c’est-à-dire une chaîne qui détermine les éléments à lire dans la table ou l’index.

Vous devez spécifier le nom de la clé de partition et la valeur comme condition d’égalité. Vous ne pouvez pas utiliser d’attribut non-clé dans une expression de condition clé.

Le cas échéant, vous pouvez fournir une deuxième condition pour la clé de tri (si elle est présente). La condition de la clé de tri doit être l’un des opérateurs de comparaison suivants :
+ `a = b`— vrai si l'attribut *a* est égal à la valeur *b*
+ `a < b`— vrai s'il *a* est inférieur à *b*
+ `a <= b`— vrai s'*a*il est inférieur ou égal à *b*
+ `a > b`— vrai s'il *a* est supérieur à *b*
+ `a >= b`— vrai s'*a*il est supérieur ou égal à *b*
+ `a BETWEEN b AND c`— vrai s'*a*il est supérieur ou égal à*b*, et inférieur ou égal à*c*.

La fonction suivante est également prise en charge :
+ `begins_with (a, substr)` – True si la valeur de l’attribut `a` commence par une sous-chaîne particulière.

Les exemples suivants AWS Command Line Interface (AWS CLI) illustrent l'utilisation d'expressions de conditions clés. Ces expressions utilisent des espaces réservés (tels que `:name` et `:sub`) au lieu de valeurs réelles. Pour plus d’informations, consultez [Noms d’attributs d’expression (alias) dans DynamoDB](Expressions.ExpressionAttributeNames.md) et [Utilisation de valeurs d’attributs d’expression dans DynamoDB](Expressions.ExpressionAttributeValues.md).

**Example**  
Interrogez la table `Thread` pour un `ForumName` (clé de partition) particulier. Tous les éléments ayant cette valeur `ForumName` sont lus par la requête, car la clé de tri (`Subject`) n’est pas incluse dans `KeyConditionExpression`.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name" \
    --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
```

**Example**  
Interrogez la table `Thread` en quête d’un `ForumName` (clé de partition) particulier, mais cette fois ne retournez que les éléments avec un `Subject` (clé de tri) donné.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name and Subject = :sub" \
    --expression-attribute-values  file://values.json
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":name":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"}
}
```

**Example**  
Interrogez la table `Reply` en quête d’un `Id` (clé de partition) particulier, mais retournez uniquement les éléments dont `ReplyDateTime` (clé de tri) commence par certains caractères.  

```
aws dynamodb query \
    --table-name Reply \
    --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
    --expression-attribute-values  file://values.json
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
    ":dt":{"S":"2015-09"}
}
```

# Expressions de filtre pour l’opération Query dans DynamoDB
<a name="Query.FilterExpression"></a>

Si vous avez besoin d’affiner davantage les résultats de l’opération `Query`, vous pouvez fournir une expression de filtre facultative. Une *expression de filtre* détermine les éléments dans les résultats de l’opération `Query` qui doivent vous être renvoyés. Tous les autres résultats sont ignorés.

Une expression de filtre est appliquée après la fin de l’opération `Query`, mais avant que les résultats soient renvoyés. Par conséquent, une opération `Query` utilise la même capacité de lecture, qu’une expression de filtre soit présente ou non.

Une opération `Query` permet d’extraire au maximum 1 Mo de données. Cette limite s’applique avant que l’expression de filtre soit évaluée.

Une expression de filtre ne peut pas contenir d’attributs de clé de partition ou de clé de tri. Vous devez préciser ces attributs dans l’expression de condition de clé, pas dans l’expression de filtre.

La syntaxe d’un expression de filtre est similaire à celle d’une expression de condition de clé. Les expressions de filtre peuvent utiliser les mêmes comparateurs, fonctions et opérateurs logiques qu’une expression de condition de clé. En outre, les expressions de filtre peuvent utiliser l’opérateur non égal (`<>`), l’opérateur `OR`, l’opérateur `CONTAINS`, l’opérateur `IN`, l’opérateur `BEGINS_WITH`, l’opérateur `BETWEEN`, l’opérateur `EXISTS` et l’opérateur `SIZE`. Pour plus d’informations, consultez [Expressions de condition clé pour l’opération Query dans DynamoDB](Query.KeyConditionExpressions.md) et [Syntaxe des expressions de filtre et de condition](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Syntax).

**Example**  
L' AWS CLI exemple suivant interroge la `Thread` table pour une `ForumName` (clé de partition) et une `Subject` (clé de tri) particulières. Parmi les éléments trouvés, seules les unités d’exécution de discussion les plus populaires sont renvoyés, c’est-à-dire les threads ayant plus qu’un certain nombre de `Views`.  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :fn and Subject begins_with :sub" \
    --filter-expression "#v >= :num" \
    --expression-attribute-names '{"#v": "Views"}' \
    --expression-attribute-values file://values.json
```
Les arguments de la fonction `--expression-attribute-values` sont stockés dans le fichier `values.json`.  

```
{
    ":fn":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"},
    ":num":{"N":"3"}
}
```
Notez que `Views` étant un mot réservé dans DynamoDB (consultez [Mots réservés dans DynamoDB](ReservedWords.md)), cet exemple utilise `#v` comme espace réservé. Pour de plus amples informations, veuillez consulter [Noms d’attributs d’expression (alias) dans DynamoDB](Expressions.ExpressionAttributeNames.md).

**Note**  
Une expression de filtre supprime des éléments du jeu de résultats de `Query`. Dans la mesure du possible, évitez d’utiliser `Query` lorsque vous pensez extraire un grand nombre d’éléments mais que vous devrez en supprimer une grande partie.

# Pagination des résultats de requête de table dans DynamoDB
<a name="Query.Pagination"></a>

DynamoDB *pagine* les résultats des opérations `Query`. Avec la pagination, les résultats de l’opération `Query` sont répartis en « pages » de données d’une taille maximum de 1 Mo. Une application peut traiter la première page des résultats, puis la deuxième, et ainsi de suite.

Une opération `Query` retourne uniquement un ensemble de résultats correspondant à la limite de taille de 1 Mo. Pour déterminer si le nombre de résultats est plus important et pour récupérer une page à la fois, les applications doivent procéder de la manière suivante : 

1. Examinez le résultat de l’opération `Query` de niveau inférieur :
   + Si le résultat contient un élément `LastEvaluatedKey` dont la valeur n’est pas null, passez à l’étape 2.
   + S’il n’y a *pas* de `LastEvaluatedKey` dans le résultat, il n’y a plus aucun élément à récupérer.

1. Construisez une `Query` avec la même `KeyConditionExpression`. Cependant, cette fois, acceptez la valeur `LastEvaluatedKey` de l’étape 1 et utilisez-la comme paramètre `ExclusiveStartKey` dans la nouvelle demande `Query`.

1. Exécutez la nouvelle demande `Query`.

1. Passez à l’étape 1.

En d’autres termes, l’élément `LastEvaluatedKey` provenant d’une réponse `Query` doit être utilisé comme `ExclusiveStartKey` pour la demande `Query` suivante. Si aucun élément `LastEvaluatedKey` n’est présent dans la réponse `Query`, vous avez extrait la dernière page de résultats. Si `LastEvaluatedKey` n’est pas vide, cela ne signifie pas nécessairement qu’il y a plus de données dans le jeu de résultats. Le seul moyen de savoir que vous avez atteint la fin du jeu de résultats est lorsque `LastEvaluatedKey` est vide.

Vous pouvez utiliser le AWS CLI pour visualiser ce comportement. AWS CLI envoie des `Query` requêtes de bas niveau à DynamoDB à plusieurs reprises, `LastEvaluatedKey` jusqu'à ce qu'elles ne soient plus présentes dans les résultats. Prenons l' AWS CLI exemple suivant qui récupère les titres de films d'une année donnée.

```
aws dynamodb query --table-name Movies \
    --projection-expression "title" \
    --key-condition-expression "#y = :yyyy" \
    --expression-attribute-names '{"#y":"year"}' \
    --expression-attribute-values '{":yyyy":{"N":"1993"}}' \
    --page-size 5 \
    --debug
```

Normalement, il AWS CLI gère automatiquement la pagination. Toutefois, dans cet exemple, le AWS CLI `--page-size` paramètre limite le nombre d'éléments par page. La paramètre `--debug` imprime les informations de bas niveau relatives aux demandes et aux réponses.

Si vous exécutez l’exemple, la première réponse de DynamoDB est à similaire à ce qui suit.

```
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'
```

Le `LastEvaluatedKey` de la réponse indique que certains éléments n’ont pas été récupérés. Il envoie AWS CLI ensuite une autre `Query` demande à DynamoDB. Ce modèle de requête et de réponse se poursuit jusqu’à l’obtention d’une réponse finale.

```
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'
```

L’absence de `LastEvaluatedKey` indique qu’il n’y a pas plus de d’élément à récupérer.

**Note**  
Ils AWS SDKs gèrent les réponses DynamoDB de bas niveau (y compris la présence ou l'absence de) et fournissent diverses abstractions pour `LastEvaluatedKey` la pagination des résultats. `Query` Par exemple, l’interface de document du kit SDK pour Java fournit le support `java.util.Iterator` pour vous permettre de parcourir les résultats un par un.  
Pour des exemples de code dans divers langages de programmation, consultez le [Guide de prise en main d’Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/) et la documentation du kit SDK  AWS pour votre langage.

Vous pouvez également réduire la taille de la page en limitant le nombre d’éléments dans l’ensemble de résultats, avec le paramètre `Limit` de l’opération `Query`.

Pour plus d’informations sur l’interrogation avec DynamoDB, consultez [Interrogation de tables dans DynamoDB](Query.md).

# Autres aspects de l’utilisation de l’opération Query dans DynamoDB
<a name="Query.Other"></a>

Cette section couvre d’autres aspects de l’opération Query DynamoDB, notamment la limitation de la taille des résultats, le comptage des éléments analysés par rapport aux éléments renvoyés, la surveillance de la consommation de capacité de lecture et le contrôle de la cohérence en lecture.

## Limiter le nombre d’éléments dans le jeu de résultats
<a name="Query.Limit"></a>

Avec l’opération `Query`, vous pouvez limiter le nombre d’éléments qu’elle lit. Pour ce faire, définissez le paramètre `Limit` sur le nombre maximal d’éléments souhaité.

Par exemple, supposons que vous effectuiez une opération `Query` sur une table, avec une valeur `Limit` de `6` et sans expression de filtre. Le résultat `Query` contient les six premiers éléments de la table qui correspondent à l’expression de condition de clé de la demande.

Supposons maintenant que vous ajoutiez une expression de filtre à l’opération `Query`. Dans ce cas, DynamoDB lit jusqu’à six éléments, puis renvoie uniquement ceux qui correspondent à l’expression de filtre. Le résultat `Query` final contient au maximum six éléments, même si davantage d’éléments auraient correspondu à l’expression de filtre si DynamoDB avait continué à lire plus d’éléments.

## Comptabilisation des éléments dans les résultats
<a name="Query.Count"></a>

Outre les éléments qui correspondent à vos critères, la réponse d’une opération `Query` contient les éléments suivants :
+ `ScannedCount` – Nombre d’éléments qui correspondaient à l’expression de condition de clé *avant* qu’une expression de filtre (le cas échéant) soit appliquée.
+ `Count` – Nombre d’éléments qui restent *après* l’application d’une expression de filtre (le cas échéant).

**Note**  
Si vous n’utilisez pas d’expression de filtre, alors `ScannedCount` et `Count` ont la même valeur.

Si la taille de l’ensemble de résultats `Query` est supérieure à 1 Mo, les opérations `ScannedCount` et `Count` représentent seulement un compte partiel du total des éléments. Vous devez effectuer plusieurs opérations `Query` pour extraire tous les résultats. (Consultez [Pagination des résultats de requête de table dans DynamoDB](Query.Pagination.md).)

Chaque réponse `Query` comporte les `ScannedCount` et `Count` des éléments traités par cette demande `Query` particulière. Pour obtenir les totaux de toutes les demandes `Query`, vous pouvez garder un compte actif de `ScannedCount` et de `Count`.

## Unités de capacité consommées par la requête
<a name="Query.CapacityUnits"></a>

Vous pouvez interroger n’importe quelle table ou n’importe quel index secondaire avec `Query`, à condition de fournir le nom de l’attribut de clé de partition et une valeur unique pour cet attribut. `Query` renvoie tous les éléments contenant cette valeur de clé de partition. Vous pouvez éventuellement fournir un attribut de clé de tri et utiliser un opérateur de comparaison pour affiner les résultats de recherche. Les opérations d’API `Query` consomment des unités de capacité de lecture, comme suit.


****  

| Si vous effectuez une opération `Query` sur… | DynamoDB consomme des unités de capacité de lecture de… | 
| --- | --- | 
| Table | Capacité de lecture allouée de la table. | 
| GSI | Capacité de lecture allouée à l’index. | 
| Index secondaire local | Capacité de lecture allouée de la table de base. | 

Par défaut, l’opération `Query` ne renvoie pas de données concernant la consommation de capacité de lecture. Vous pouvez toutefois spécifier le paramètre `ReturnConsumedCapacity` dans une demande `Query` pour obtenir ces informations. Voici les paramètres valides pour `ReturnConsumedCapacity` :
+ `NONE` – Aucune donnée de capacité consommée n’est renvoyée. (Il s’agit de l’option par défaut.)
+ `TOTAL` – La réponse inclut le nombre agrégé d’unités de capacité de lecture consommées.
+ `INDEXES` – La réponse indique le nombre agrégé d’unités de capacité de lecture consommées, ainsi que la capacité consommée pour chaque table et index consultés.

DynamoDB calcule le nombre d’unités de capacité de lecture consommées en fonction du nombre d’éléments et de la taille de ces éléments, et non du volume de données renvoyées à une application. Pour cette raison, le nombre d’unités de capacité consommées sera le même que vous demandiez tous les attributs (comportement par défaut) ou seulement certains d’entre eux (avec une expression de projection). Le nombre est également le même, que vous utilisiez ou non une expression de filtre. `Query` consomme une unité de capacité de lecture minimale pour effectuer une lecture fortement cohérente par seconde ou deux lectures cohérentes à terme par seconde pour un élément d’une taille maximale de 4 Ko. Si vous devez lire un élément d’une taille supérieure à 4 Ko, DynamoDB a besoin d’unités de demande de lecture supplémentaires. Les tables vides et les très grandes tables contenant peu de clés de partition peuvent entraîner des RCUs frais supplémentaires au-delà de la quantité de données demandées. Cela couvre les frais de traitement de la demande `Query`, même en l’absence de données.

## Cohérence en lecture de la requête
<a name="Query.ReadConsistency"></a>

Par défaut, une opération `Query` effectue des lectures cohérentes à terme. Autrement dit, les résultats de l’opération `Query` peuvent ne pas refléter des modifications apportées par des opérations `PutItem` ou `UpdateItem` récentes. Pour de plus amples informations, veuillez consulter [Cohérence en lecture DynamoDB](HowItWorks.ReadConsistency.md).

Si vous avez besoin de lectures fortement cohérentes, définissez le paramètre `ConsistentRead` sur `true` dans la demande `Query`.

# Analyse de tables dans DynamoDB
<a name="Scan"></a>

Une opération `Scan` dans Amazon DynamoDB lit tous les éléments d’une table ou d’un index secondaire. Par défaut, une opération `Scan` renvoie tous les attributs de données pour chaque élément de la table ou de l’index. Vous pouvez utiliser le paramètre `ProjectionExpression` de sorte que `Scan` renvoie uniquement certains des attributs, plutôt que leur totalité.

`Scan` renvoie toujours un ensemble de résultats. Si aucun élément correspondant n’est trouvé, l’ensemble de résultats est vide.

Une seule demande `Scan` permet d’extraire un maximum de 1 Mo de données. Le cas échéant, DynamoDB peut appliquer une expression de filtre à ces données, en affinant les résultats avant qu’ils soient renvoyés à l’utilisateur.

**Topics**
+ [Filtrer les expressions à des fins d’analyse](#Scan.FilterExpression)
+ [Limiter le nombre d’éléments dans l’ensemble de résultats](#Scan.Limit)
+ [Pagination des résultats](#Scan.Pagination)
+ [Comptabilisation des éléments dans les résultats](#Scan.Count)
+ [Unités de capacité consommées par l’opération d’analyse](#Scan.CapacityUnits)
+ [Cohérence en lecture de l’opération d’analyse](#Scan.ReadConsistency)
+ [Analyse parallèle](#Scan.ParallelScan)

## Filtrer les expressions à des fins d’analyse
<a name="Scan.FilterExpression"></a>

Si vous devez affiner davantage les résultats de l’opération `Scan`, vous pouvez également fournir une expression de filtre. Une *expression de filtre* détermine les éléments dans les résultats de l’opération `Scan` qui doivent vous être renvoyés. Tous les autres résultats sont ignorés.

Une expression de filtre est appliquée après la fin de l’opération `Scan`, mais avant que les résultats soient renvoyés. Par conséquent, une opération `Scan` consomme la même capacité de lecture, qu’une expression de filtre soit présente ou non.

Une opération `Scan` permet d’extraire au maximum 1 Mo de données. Cette limite s’applique avant que l’expression de filtre soit évaluée.

Avec `Scan`, vous pouvez spécifier tous les attributs dans une expression de filtre, y compris les attributs de clé de partition et de clé de tri.

La syntaxe d’un expression de filtre est identique à celle d’une expression de condition. Les expressions de filtre peuvent utiliser les mêmes comparateurs, fonctions et opérateurs logiques qu’une expression de condition. Pour en savoir plus sur les opérateurs, consultez [Expressions de condition et de filtre, opérateurs et fonctions dans DynamoDB](Expressions.OperatorsAndFunctions.md).

**Example**  
L'exemple suivant AWS Command Line Interface (AWS CLI) analyse le `Thread` tableau et renvoie uniquement les derniers éléments publiés par un utilisateur en particulier.  

```
aws dynamodb scan \
     --table-name Thread \
     --filter-expression "LastPostedBy = :name" \
     --expression-attribute-values '{":name":{"S":"User A"}}'
```

## Limiter le nombre d’éléments dans l’ensemble de résultats
<a name="Scan.Limit"></a>

L’opération `Scan` permet de limiter le nombre d’éléments renvoyés dans le résultat. Pour ce faire, définissez le paramètre `Limit` sur le nombre maximal d’éléments que vous souhaitez que l’opération `Scan` renvoie, avant l’évaluation de l’expression de filtre.

Par exemple, supposons que vous effectuiez une opération `Scan` sur une table, avec une valeur `Limit` de `6` et sans expression de filtre. Le résultat de l’opération `Scan` comporte les six premiers éléments de la table.

Supposons maintenant que vous ajoutiez une expression de filtre à l’opération `Scan`. Dans ce cas, DynamoDB applique l’expression de filtre aux six éléments renvoyés et supprime ceux qui ne correspondent pas. Le résultat final de l’opération `Scan` comporte six éléments au plus, selon le nombre d’éléments filtrés.

## Pagination des résultats
<a name="Scan.Pagination"></a>

DynamoDB *pagine* les résultats des opérations `Scan`. Avec la pagination, les résultats de l’opération `Scan` sont répartis en « pages » de données d’une taille maximum de 1 Mo. Une application peut traiter la première page des résultats, puis la deuxième, et ainsi de suite.

Une opération `Scan` renvoie uniquement un ensemble de résultats correspondant à la limite de taille de 1 Mo. 

Pour déterminer si le nombre de résultats est plus important et récupérer une page à la fois, les applications doivent procéder comme suit :

1. Examinez le résultat de l’opération `Scan` de niveau inférieur :
   + Si le résultat comporte un élément `LastEvaluatedKey`, passez à l’étape 2.
   + S’il n’y a *pas* de `LastEvaluatedKey` dans le résultat, il n’y a plus aucun élément à récupérer.

1. Construisez une nouvelle demande `Scan`, avec les mêmes paramètres que la précédente. Cependant, cette fois-ci, acceptez la valeur `LastEvaluatedKey` de l’étape 1 et utilisez-la comme paramètre `ExclusiveStartKey` dans la nouvelle demande `Scan`.

1. Exécutez la nouvelle demande `Scan`.

1. Passez à l’étape 1.

Autrement dit, l’élément `LastEvaluatedKey` provenant d’une réponse de l’opération `Scan` doit être utilisé comme `ExclusiveStartKey` pour la demande `Scan` suivante. Si aucun élément `LastEvaluatedKey` n’est présent dans la réponse de l’opération `Scan`, vous avez extrait la dernière page de résultats. (L’absence de `LastEvaluatedKey` est le seul moyen de savoir que vous avez atteint la fin de l’ensemble de résultats.)

Vous pouvez utiliser le AWS CLI pour visualiser ce comportement. AWS CLI envoie des `Scan` requêtes de bas niveau à DynamoDB, à plusieurs reprises, `LastEvaluatedKey` jusqu'à ce qu'elles ne soient plus présentes dans les résultats. Prenons l' AWS CLI exemple suivant qui scanne l'intégralité du `Movies` tableau mais ne renvoie que les films d'un genre particulier.

```
aws dynamodb scan \
    --table-name Movies \
    --projection-expression "title" \
    --filter-expression 'contains(info.genres,:gen)' \
    --expression-attribute-values '{":gen":{"S":"Sci-Fi"}}' \
    --page-size 100  \
    --debug
```

Normalement, il AWS CLI gère automatiquement la pagination. Toutefois, dans cet exemple, le AWS CLI `--page-size` paramètre limite le nombre d'éléments par page. La paramètre `--debug` imprime les informations de bas niveau relatives aux demandes et aux réponses.

**Note**  
Vos résultats de pagination diffèrent également en fonction des paramètres d’entrée que vous transmettez.   
L’utilisation de `aws dynamodb scan --table-name Prices --max-items 1` renvoie un `NextToken`
L’utilisation de `aws dynamodb scan --table-name Prices --limit 1` renvoie un `LastEvaluatedKey`.
Sachez également que l’utilisation de `--starting-token` en particulier requiert la valeur `NextToken`. 

Si vous exécutez l’exemple, la première réponse de DynamoDB est similaire à ce qui suit.

```
2017-07-07 12:19:14,389 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":7,"Items":[{"title":{"S":"Monster on the Campus"}},{"title":{"S":"+1"}},
{"title":{"S":"100 Degrees Below Zero"}},{"title":{"S":"About Time"}},{"title":{"S":"After Earth"}},
{"title":{"S":"Age of Dinosaurs"}},{"title":{"S":"Cloudy with a Chance of Meatballs 2"}}],
"LastEvaluatedKey":{"year":{"N":"2013"},"title":{"S":"Curse of Chucky"}},"ScannedCount":100}'
```

Le `LastEvaluatedKey` de la réponse indique que certains éléments n’ont pas été récupérés. Il envoie AWS CLI ensuite une autre `Scan` demande à DynamoDB. Ce modèle de requête et de réponse se poursuit jusqu’à l’obtention d’une réponse finale.

```
2017-07-07 12:19:17,830 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"WarGames"}}],"ScannedCount":6}'
```

L’absence de `LastEvaluatedKey` indique qu’il n’y a pas plus de d’élément à récupérer.

**Note**  
Ils AWS SDKs gèrent les réponses DynamoDB de bas niveau (y compris la présence ou l'absence de) et fournissent diverses abstractions pour `LastEvaluatedKey` la pagination des résultats. `Scan` Par exemple, l’interface de document du kit SDK pour Java fournit le support `java.util.Iterator` pour vous permettre de parcourir les résultats un par un.  
Pour des exemples de code dans divers langages de programmation, consultez le [Guide de prise en main d’Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/) et la documentation du kit SDK  AWS pour votre langage.

## Comptabilisation des éléments dans les résultats
<a name="Scan.Count"></a>

Outre les éléments qui correspondent à vos critères, la réponse d’une opération `Scan` comporte les éléments suivants :
+ `ScannedCount` – Nombre d’éléments évalués avant l’application de `ScanFilter`. Une valeur `ScannedCount` élevée avec un nombre faible ou nul de résultats `Count` indique une opération `Scan` inefficace. Si vous n’avez pas utilisé de filtre dans la demande, `ScannedCount` et `Count` ont la même valeur. 
+ `Count` – Nombre d’éléments qui restent *après* l’application d’une expression de filtre (le cas échéant).

**Note**  
Si vous n’utilisez pas d’expression de filtre, `ScannedCount` et `Count` ont la même valeur.

Si la taille de l’ensemble de résultats `Scan` est supérieure à 1 Mo, les opérations `ScannedCount` et `Count` représentent seulement un décompte partiel du nombre total d’éléments. Vous devez effectuer plusieurs opérations `Scan` pour extraire tous les résultats. (Consultez [Pagination des résultats](#Scan.Pagination).)

Chaque réponse `Scan` comporte les `ScannedCount` et `Count` des éléments traités par cette demande `Scan` particulière. Pour obtenir les totaux de toutes les demandes `Scan`, vous pouvez garder un compte actif de `ScannedCount` et `Count`.

## Unités de capacité consommées par l’opération d’analyse
<a name="Scan.CapacityUnits"></a>

Vous pouvez effectuer une opération `Scan` sur toute table ou tout index secondaire. Les opérations `Scan` consomment des unités de capacité de lecture, comme suit.


****  

| Si vous effectuez une opération `Scan` sur… | DynamoDB consomme des unités de capacité de lecture de… | 
| --- | --- | 
| Table | Capacité de lecture allouée de la table. | 
| GSI | Capacité de lecture allouée à l’index. | 
| Index secondaire local | Capacité de lecture allouée de la table de base. | 

**Note**  
L’accès intercompte pour les opérations d’analyse d’index secondaires n’est actuellement pas pris en charge par les [politiques basées sur les ressources](access-control-resource-based.md).

Par défaut, une opération `Scan` ne renvoie pas de données concernant la consommation de capacité de lecture. Vous pouvez toutefois spécifier le paramètre `ReturnConsumedCapacity` dans une demande `Scan` pour obtenir ces informations. Voici les paramètres valides pour `ReturnConsumedCapacity` :
+ `NONE` – Aucune donnée de capacité consommée n’est renvoyée. (Il s’agit de l’option par défaut.)
+ `TOTAL` – La réponse inclut le nombre agrégé d’unités de capacité de lecture consommées.
+ `INDEXES` – La réponse indique le nombre agrégé d’unités de capacité de lecture consommées, ainsi que la capacité consommée pour chaque table et index consultés.

DynamoDB calcule le nombre d’unités de capacité de lecture consommées en fonction du nombre d’éléments et de la taille de ces éléments, et non du volume de données renvoyées à une application. Pour cette raison, le nombre d’unités de capacité consommées sera le même que vous demandiez tous les attributs (comportement par défaut) ou seulement certains d’entre eux (avec une expression de projection). Le nombre est également le même, que vous utilisiez ou non une expression de filtre. `Scan` consomme une unité de capacité de lecture minimale pour effectuer une lecture fortement cohérente par seconde ou deux lectures cohérentes à terme par seconde pour un élément d’une taille maximale de 4 Ko. Si vous devez lire un élément d’une taille supérieure à 4 Ko, DynamoDB a besoin d’unités de demande de lecture supplémentaires. Les tables vides et les très grandes tables contenant peu de clés de partition peuvent entraîner des RCUs frais supplémentaires au-delà de la quantité de données numérisées. Cela couvre les frais de traitement de la demande `Scan`, même en l’absence de données.

## Cohérence en lecture de l’opération d’analyse
<a name="Scan.ReadConsistency"></a>

Par défaut, une opération `Scan` effectue des lectures cohérentes à terme. Autrement dit, les résultats de l’opération `Scan` peuvent ne pas refléter des modifications apportées par des opérations `PutItem` ou `UpdateItem` récentes. Pour de plus amples informations, veuillez consulter [Cohérence en lecture DynamoDB](HowItWorks.ReadConsistency.md).

Si vous avez besoin de lectures fortement cohérentes au moment où l’opération `Scan` commence, définissez le paramètre `ConsistentRead` sur la valeur `true` dans la demande `Scan`. Ainsi, toutes les opérations d’écriture terminées avant le début de l’opération `Scan` sont incluses dans la réponse `Scan`. 

La définition de `ConsistentRead` sur `true` peut être utile dans la sauvegarde des tables ou les scénarios de réplication, conjointement avec [DynamoDB Streams](./Streams.html). Vous utilisez d’abord `Scan` avec le paramètre `ConsistentRead` défini sur la valeur true pour obtenir une copie cohérente des données de la table. Pendant l’opération `Scan`, DynamoDB Streams enregistre toute activité d’écriture supplémentaire qui se produit sur la table. Une fois l’opération `Scan` terminée, vous pouvez appliquer l’activité d’écriture du flux vers la table.

**Note**  
Notez qu’une opération `Scan` avec le paramètre `ConsistentRead` défini sur la valeur `true` consomme deux fois plus d’unités de capacité de lecture, par rapport au fait de laisser la paramètre `ConsistentRead` défini sur sa valeur par défaut (`false`).

## Analyse parallèle
<a name="Scan.ParallelScan"></a>

Par défaut, l’opération `Scan` traite les données de manière séquentielle. Amazon DynamoDB renvoie des données à l’application par incréments de 1 Mo, et une application effectue des opérations `Scan` supplémentaires pour extraire le Mo de données suivant. 

Plus la table ou l’index en cours d’analyse est grand(e), plus l’opération `Scan` prend du temps. En outre, il arrive qu’une opération `Scan` séquentielle ne puisse pas utiliser pleinement la capacité de débit de lecture alloué. Même si DynamoDB répartit les données d’une grande table sur plusieurs partitions physiques, une opération `Scan` ne peut lire qu’une seule partition à la fois. C’est pourquoi le débit d’une opération `Scan` est limité par le débit maximum d’une partition.

Pour résoudre ce problème, l’opération `Scan` peut diviser logiquement une table ou un index secondaire en plusieurs *segments*, avec plusieurs workers d’application qui analysent les segments en parallèle. Chaque worker peut être un thread (lorsque le langage de programmation prend en charge le multithreading) ou un processus de système d’exploitation. Pour effectuer une analyse en parallèle, chaque worker émet sa propre demande `Scan` avec les paramètres suivants :
+ `Segment` – Segment à analyser par un worker particulier. Chaque worker doit utiliser une valeur différente pour `Segment`.
+ `TotalSegments` – Nombre total de segments pour l’analyse en parallèle. Cette valeur doit être identique au nombre de workers que votre application va utiliser.

Le diagramme suivant illustre la manière dont une application multithread exécute une opération `Scan` en parallèle avec trois degrés de parallélisme.

![\[Application multithread qui effectue une analyse en parallèle en divisant une table en trois segments.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/ParallelScan.png)




Dans ce diagramme, l’application produit trois threads auxquels elle affecte un numéro. (Les segments étant de base zéro, le premier numéro est toujours 0.) Chaque thread émet une demande `Scan`, définissant le paramètre `Segment` sur son numéro désigné, et le paramètre `TotalSegments` sur 3. Chaque thread analyse son segment désigné en extrayant 1 Mo de données à la fois, puis renvoie les données au thread principal de l’application.

DynamoDB affecte des éléments *à des segments en appliquant une fonction de hachage à* la clé de partition de chaque élément. Pour une `TotalSegments` valeur donnée, tous les éléments ayant la même clé de partition sont toujours assignés à la même valeur`Segment`. Cela signifie que dans un tableau où les *éléments 1*, *2* et *3* se partagent tous `pk="account#123"` (mais ont des clés de tri différentes), ces éléments seront traités par le même opérateur, quelles que soient les valeurs des clés de tri ou la taille de la *collection d'articles*.

L'attribution des *segments* étant basée uniquement sur le hachage de la clé de partition, les segments peuvent être répartis de manière inégale. Certains segments peuvent ne contenir aucun élément, tandis que d'autres peuvent contenir de nombreuses clés de partition avec de grandes collections d'éléments. Par conséquent, l'augmentation du nombre total de segments ne garantit pas des performances d'analyse plus rapides, en particulier lorsque les clés de partition ne sont pas réparties uniformément dans l'espace de touches.

Les valeurs des paramètres `Segment` et `TotalSegments` s’appliquent à des demandes `Scan` individuelles et vous pouvez utiliser différentes valeurs à tout moment. Il se peut que vous deviez tester ces valeurs et le nombre de workers que vous utilisez, jusqu’à ce que votre application atteigne des performances optimales.

**Note**  
Une analyse en parallèle avec de nombreux threads peut facilement consommer tout le débit alloué pour la table ou l’index analysé(e). Il est préférable d’éviter de telles analyses si d’autres applications soumettent également la table ou l’index à une intense activité de lecture ou d’écriture.  
Ccontrôlez le volume de données renvoyées par demande à l’aide du paramètre `Limit`. Cela vous permet d’éviter des situations où un worker consomme tout le débit alloué, au détriment des autres.

# PartiQL – Langage de requête compatible SQL pour Amazon DynamoDB
<a name="ql-reference"></a>

Amazon DynamoDB prend en charge [PartiQL](https://partiql.org/), un langage de requête compatible SQL, pour sélectionner, insérer, mettre à jour et supprimer des données dans Amazon DynamoDB. Grâce à PartiQL, vous pouvez facilement interagir avec les tables DynamoDB et exécuter des requêtes ad hoc à l'aide de AWS Management Console NoSQL Workbench et de DynamoDB pour PartiQL. AWS Command Line Interface APIs 

Les opérations PartiQL offrent une disponibilité, une latence et des performances identiques aux autres opérations de plan de données DynamoDB.

Les sections suivantes décrivent l’implémentation DynamoDB de PartiQL.

**Topics**
+ [Qu’est-ce que PartiQL ?](#ql-reference.what-is)
+ [PartiQL dans Amazon DynamoDB](#ql-reference.what-is)
+ [Prise en main](ql-gettingstarted.md)
+ [Types de données](ql-reference.data-types.md)
+ [Instructions](ql-reference.statements.md)
+ [Fonctions](ql-functions.md)
+ [Opérateurs](ql-operators.md)
+ [Transactions](ql-reference.multiplestatements.transactions.md)
+ [Opérations par lots](ql-reference.multiplestatements.batching.md)
+ [politiques IAM](ql-iam.md)

## Qu’est-ce que PartiQL ?
<a name="ql-reference.what-is"></a>

Le langage *PartiQL* fournit un accès aux requêtes compatible SQL sur plusieurs magasins de données contenant des données structurées, des données semi-structurées et des données imbriquées. Il est largement utilisé au sein d'Amazon et est désormais disponible dans le cadre de nombreux AWS services, dont DynamoDB.

Pour la spécification de PartiQL et un didacticiel sur le langage de requête de base, consultez la [Documentation PartiQL](https://partiql.org/docs.html).

**Note**  
Amazon DynamoDB prend en charge un *sous-ensemble* du langage de requête [PartiQL](https://partiql.org/).
Amazon DynamoDB ne prend pas en charge le format de données [Amazon Ion](http://amzn.github.io/ion-docs/) ou les littéraux Amazon Ion.

## PartiQL dans Amazon DynamoDB
<a name="ql-reference.what-is"></a>

Pour exécuter des requêtes PartiQL dans DynamoDB, vous pouvez utiliser les ressources suivantes :
+ La console DynamoDB
+ Le NoSQL Workbench
+ Le AWS Command Line Interface (AWS CLI)
+ Le DynamoDB APIs

Pour plus d’informations sur l’utilisation de ces méthodes pour accéder à DynamoDB, consultez [Accès à DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html).

# Mise en route avec PartiQL pour DynamoDB
<a name="ql-gettingstarted"></a>

Cette section décrit comment utiliser PartiQL pour DynamoDB à partir de la console Amazon DynamoDB, du () et de DynamoDB. AWS Command Line Interface AWS CLI APIs

Dans les exemples suivants, la table DynamoDB définie dans le didacticiel [Mise en route avec DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html) est un prérequis.

[Pour plus d'informations sur l'utilisation de la console DynamoDB ou de DynamoDB pour accéder à DynamoDB AWS Command Line Interface, consultez la section Accès à APIs DynamoDB.](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/AccessingDynamoDB.html)

Pour [télécharger](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.settingup.html) et utiliser le [NoSQL Workbench](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html) afin de créer des instructions [PartiQL pour DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.html), choisissez **PartiQL operations** (Opérations PartiQL) dans l’angle supérieur droit du NoSQL Workbench pour DynamoDB [Operation Builder](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.querybuilder.operationbuilder.html) (Créateur d’opérations).

------
#### [ Console ]

![\[Interface d’éditeur PartiQL qui affiche le résultat de l’exécution de l’opération Query sur la table Music.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/partiqlgettingstarted.png)


1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le panneau de navigation sur le côté gauche de la console, choisissez **PartiQL editor (Editeur PartiQL)**.

1. Choisissez la table **Music**.

1. Choisissez **Query table (Table de requête)**. Cette action génère une requête qui n’entraîne pas d’analyse de table complète.

1. Remplacez `partitionKeyValue` par la valeur de chaîne `Acme Band`. Remplacez `sortKeyValue` par la valeur de chaîne `Happy Day`.

1. Choisissez le bouton **Run (Exécuter)**. 

1. Vous pouvez afficher les résultats de la requête en choisissant les boutons **Table view (Vue tableau)** ou **JSON view (Vue JSON)**. 

------
#### [ NoSQL workbench ]

![\[Interface NoSQL Workbench. Il affiche une instruction PartiQL SELECT que vous pouvez exécuter sur la table Music.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/workbench/partiql.single.png)


1. Choisissez **PartiQL statement (Instruction PartiQL)**.

1. Entrez l’instruction PartiQL [SELECT](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html) suivante 

   ```
   SELECT *                                         
   FROM Music  
   WHERE Artist=? and SongTitle=?
   ```

1. Pour spécifier une valeur pour les paramètres `Artist` et `SongTitle` :

   1. Choisissez **Optional request parameters (Paramètres de demande facultatifs)**.

   1. Choisissez **Add new parameters (Ajouter de nouveaux paramètres)**.

   1. Choisissez le type d’attribut **string (chaîne)** et la valeur `Acme Band`.

   1. Répétez les étapes b et c, puis choisissez le type **string (chaîne)** et la valeur `PartiQL Rocks`. 

1. Si vous souhaitez générer un code, choisissez **Generate code (Générer un code)**.

   Sélectionnez votre langage souhaité dans les onglets affichés. Vous pouvez désormais copier ce code et l’utiliser dans votre application.

1. Si vous souhaitez que l’opération soit exécutée immédiatement, choisissez **Run (Exécuter)**.

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

1. Créez un élément dans la table `Music` à l’aide de l’instruction INSERT PartiQL. 

   ```
   aws dynamodb execute-statement --statement "INSERT INTO Music  \
   					    VALUE  \
   					    {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"
   ```

1. Extrayez un élément de la table Music à l’aide de l’instruction SELECT PartiQL.

   ```
   aws dynamodb execute-statement --statement "SELECT * FROM Music   \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. Créez un élément dans la table `Music` à l’aide de l’instruction UPDATE PartiQL.

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardsWon=1  \
                                               SET AwardDetail={'Grammys':[2020, 2018]}  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Ajoutez une valeur de liste pour un élément dans la table `Music`. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Supprimez une valeur de liste pour un élément dans la table `Music`. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               REMOVE AwardDetail.Grammys[2]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Ajoutez un nouveau membre de mappage pour un élément dans la table `Music`. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET AwardDetail.BillBoard=[2020]  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Ajoutez un nouvel attribut d’ensemble de chaînes pour un élément dans la table `Music`. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =<<'member1', 'member2'>>  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

   Mettez à jour un attribut d’ensemble de chaînes pour un élément dans la table `Music`. 

   ```
   aws dynamodb execute-statement --statement "UPDATE Music  \
                                               SET BandMembers =set_add(BandMembers, <<'newmember'>>)  \
                                               WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

1. Supprimez un élément de la table `Music` à l’aide de l’instruction PartiQL DELETE.

   ```
   aws dynamodb execute-statement --statement "DELETE  FROM Music  \
       WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
   ```

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

```
import java.util.ArrayList;
import java.util.List;

import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import software.amazon.dynamodb.AmazonDynamoDB;
import software.amazon.dynamodb.AmazonDynamoDBClientBuilder;
import software.amazon.dynamodb.model.AttributeValue;
import software.amazon.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.dynamodb.model.ExecuteStatementRequest;
import software.amazon.dynamodb.model.ExecuteStatementResult;
import software.amazon.dynamodb.model.InternalServerErrorException;
import software.amazon.dynamodb.model.ItemCollectionSizeLimitExceededException;
import software.amazon.dynamodb.model.ProvisionedThroughputExceededException;
import software.amazon.dynamodb.model.RequestLimitExceededException;
import software.amazon.dynamodb.model.ResourceNotFoundException;
import software.amazon.dynamodb.model.TransactionConflictException;

public class DynamoDBPartiQGettingStarted {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-1");

        try {
            // Create ExecuteStatementRequest
            ExecuteStatementRequest executeStatementRequest = new ExecuteStatementRequest();
            List<AttributeValue> parameters= getPartiQLParameters();

            //Create an item in the Music table using the INSERT PartiQL statement
            processResults(executeStatementRequest(dynamoDB, "INSERT INTO Music value {'Artist':?,'SongTitle':?}", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //Update an item in the Music table using the UPDATE PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist=? and SongTitle=?", parameters));

            //Add a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  where Artist=? and SongTitle=?", parameters));

            //Remove a list value for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music REMOVE AwardDetail.Grammys[2]   where Artist=? and SongTitle=?", parameters));

            //Add a new map member for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music set AwardDetail.BillBoard=[2020] where Artist=? and SongTitle=?", parameters));

            //Add a new string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =<<'member1', 'member2'>> where Artist=? and SongTitle=?", parameters));

            //update a string set attribute for an item in the Music table.
            processResults(executeStatementRequest(dynamoDB, "UPDATE Music SET BandMembers =set_add(BandMembers, <<'newmember'>>) where Artist=? and SongTitle=?", parameters));

            //Retrieve an item from the Music table using the SELECT PartiQL statement.
            processResults(executeStatementRequest(dynamoDB, "SELECT * FROM Music  where Artist=? and SongTitle=?", parameters));

            //delete an item from the Music Table
            processResults(executeStatementRequest(dynamoDB, "DELETE  FROM Music  where Artist=? and SongTitle=?", parameters));
        } catch (Exception e) {
            handleExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {
        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static List<AttributeValue> getPartiQLParameters() {
        List<AttributeValue> parameters = new ArrayList<AttributeValue>();
        parameters.add(new AttributeValue("Acme Band"));
        parameters.add(new AttributeValue("PartiQL Rocks"));
        return parameters;
    }

    private static ExecuteStatementResult executeStatementRequest(AmazonDynamoDB client, String statement, List<AttributeValue> parameters ) {
        ExecuteStatementRequest request = new ExecuteStatementRequest();
        request.setStatement(statement);
        request.setParameters(parameters);
        return client.executeStatement(request);
    }

    private static void processResults(ExecuteStatementResult executeStatementResult) {
        System.out.println("ExecuteStatement successful: "+ executeStatementResult.toString());

    }

    // Handles errors during ExecuteStatement execution. Use recommendations in error messages below to add error handling specific to
    // your application use-case.
    private static void handleExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (ConditionalCheckFailedException ccfe) {
            System.out.println("Condition check specified in the operation failed, review and update the condition " +
                                       "check before retrying. Error: " + ccfe.getErrorMessage());
        } catch (TransactionConflictException tce) {
            System.out.println("Operation was rejected because there is an ongoing transaction for the item, generally " +
                                       "safe to retry with exponential back-off. Error: " + tce.getErrorMessage());
        } catch (ItemCollectionSizeLimitExceededException icslee) {
            System.out.println("An item collection is too large, you\'re using Local Secondary Index and exceeded " +
                                       "size limit of items per partition key. Consider using Global Secondary Index instead. Error: " + icslee.getErrorMessage());
        } catch (Exception e) {
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " +
                                       "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                                       "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " +
                                       ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " +
                                       "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                                       "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                                       "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                                       "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

## Utilisation d'instructions paramétrées
<a name="ql-gettingstarted.parameterized"></a>

Au lieu d'intégrer des valeurs directement dans une chaîne d'instruction PartiQL, vous pouvez utiliser des espaces réservés en forme de point d'interrogation `?` () et fournir les valeurs séparément dans le champ. `Parameters` Chacun `?` est remplacé par la valeur de paramètre correspondante, dans l'ordre dans lequel ils sont fournis.

L'utilisation d'instructions paramétrées est une bonne pratique car elle sépare la structure des instructions des valeurs des données, ce qui facilite la lecture et la réutilisation des instructions. Cela évite également d'avoir à formater et à ignorer manuellement les valeurs d'attribut dans la chaîne de déclaration.

Les instructions paramétrées sont prises en charge dans les `ExecuteStatement` opérations`BatchExecuteStatement`, et`ExecuteTransaction`.

Les exemples suivants extraient un élément de la `Music` table à l'aide de valeurs paramétrées pour la clé de partition et la clé de tri.

------
#### [ AWS CLI parameterized ]

```
aws dynamodb execute-statement \
    --statement "SELECT * FROM \"Music\" WHERE Artist=? AND SongTitle=?" \
    --parameters '[{"S": "Acme Band"}, {"S": "PartiQL Rocks"}]'
```

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

```
List<AttributeValue> parameters = new ArrayList<>();
parameters.add(new AttributeValue("Acme Band"));
parameters.add(new AttributeValue("PartiQL Rocks"));

ExecuteStatementRequest request = new ExecuteStatementRequest()
    .withStatement("SELECT * FROM Music WHERE Artist=? AND SongTitle=?")
    .withParameters(parameters);

ExecuteStatementResult result = dynamoDB.executeStatement(request);
```

------
#### [ Python parameterized ]

```
response = dynamodb_client.execute_statement(
    Statement="SELECT * FROM Music WHERE Artist=? AND SongTitle=?",
    Parameters=[
        {'S': 'Acme Band'},
        {'S': 'PartiQL Rocks'}
    ]
)
```

------

**Note**  
L'exemple Java présenté dans la section de démarrage précédente utilise des instructions paramétrées dans l'ensemble. La `getPartiQLParameters()` méthode crée la liste des paramètres, et chaque instruction utilise des `?` espaces réservés au lieu de valeurs intégrées.

# Types de données PartiQL pour DynamoDB
<a name="ql-reference.data-types"></a>

Le tableau suivant répertorie les types de données que vous pouvez utiliser avec PartiQL pour DynamoDB.

[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/ql-reference.data-types.html)

## Exemples
<a name="ql-reference.data-types"></a>

L’instruction suivante montre comment insérer les types de données suivants : `String`, `Number`, `Map`, `List`, `Number Set` et `String Set`.

```
INSERT INTO TypesTable value {'primarykey':'1', 
'NumberType':1,
'MapType' : {'entryname1': 'value', 'entryname2': 4}, 
'ListType': [1,'stringval'], 
'NumberSetType':<<1,34,32,4.5>>, 
'StringSetType':<<'stringval','stringval2'>>
}
```

L’instruction suivante montre comment insérer de nouveaux éléments dans les types `Map`, `List`, `Number Set` et `String Set`, et modifier la valeur d’un type `Number`.

```
UPDATE TypesTable 
SET NumberType=NumberType + 100 
SET MapType.NewMapEntry=[2020, 'stringvalue', 2.4]
SET ListType = LIST_APPEND(ListType, [4, <<'string1', 'string2'>>])
SET NumberSetType= SET_ADD(NumberSetType, <<345, 48.4>>)
SET StringSetType = SET_ADD(StringSetType, <<'stringsetvalue1', 'stringsetvalue2'>>)
WHERE primarykey='1'
```

L’instruction suivante montre comment supprimer des éléments des types `Map`, `List`, `Number Set` et `String Set`, et modifier la valeur d’un type `Number`.

```
UPDATE TypesTable 
SET NumberType=NumberType - 1
REMOVE ListType[1]
REMOVE MapType.NewMapEntry
SET NumberSetType = SET_DELETE( NumberSetType, <<345>>)
SET StringSetType = SET_DELETE( StringSetType, <<'stringsetvalue1'>>)
WHERE primarykey='1'
```

Pour plus d’informations, consultez [Types de données DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html#HowItWorks.DataTypes).

# Instructions PartiQL pour DynamoDB
<a name="ql-reference.statements"></a>

Amazon DynamoDB prend en charge les instructions PartiQL suivantes.

**Note**  
DynamoDB ne prend pas en charge toutes les instructions PartiQL.  
Cette référence fournit des exemples de syntaxe de base et d'utilisation des instructions partiQL que vous exécutez manuellement à l'aide de la AWS CLI commande or. APIs

Le *langage de manipulation des données* (Data manipulation language, DML) est l’ensemble d’instructions PartiQL que vous utilisez pour gérer les données dans des tables DynamoDB. Vous utilisez des instructions DML pour ajouter, modifier ou supprimer des données dans une table.

Les instructions DML et de langage de requête prises en charge sont les suivantes :
+ [Instructions PartiQL de sélection pour DynamoDB](ql-reference.select.md)
+ [Instructions de mise à jour de PartiQL pour DynamoDB](ql-reference.update.md)
+ [Instructions d’insertion de PartiQL pour DynamoDB](ql-reference.insert.md)
+ [Instructions de suppression de PartiQL pour DynamoDB](ql-reference.delete.md)

Les instructions [Exécution de transactions avec PartiQL pour DynamoDB](ql-reference.multiplestatements.transactions.md) et [Exécution d’opérations par lot avec PartiQL pour DynamoDB](ql-reference.multiplestatements.batching.md) sont également prises en charge par PartiQL pour DynamoDB.

# Instructions PartiQL de sélection pour DynamoDB
<a name="ql-reference.select"></a>

Utilisez l’instruction `SELECT` pour extraire des données d’une table dans Amazon DynamoDB.

L’utilisation de l’instruction `SELECT` peut entraîner une analyse de table complète si une condition IN avec une clé de partition n’est pas fournie dans la clause WHERE. Une opération d’analyse examine chaque élément en lien avec les valeurs demandées, et peut utiliser tout le débit approvisionné pour une table ou un index volumineux en une seule opération. 

Si vous voulez éviter une analyse de table complète dans PartiQL, vous pouvez :
+ Créer vos instructions `SELECT` de façon à ce qu’elle n’entraînent pas d’analyse de table complète en vous assurant que votre [condition de clause WHERE](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/ql-reference.select.html#ql-reference.select.parameters) est configurée en conséquence.
+ Désactiver l’analyse de table complète à l’aide de la politique IAM spécifiée dans [Exemple : autoriser les instructions de sélection et rejeter les instructions d’analyse de table complète dans PartiQL pour DynamoDB](ql-iam.md#access-policy-ql-iam-example6), dans le Manuel du développeur DynamoDB.

Pour plus d’informations, consultez [Bonnes pratiques pour l’interrogation et l’analyse des données](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/bp-query-scan.html) dans le Guide du développeur DynamoDB.

**Topics**
+ [Syntaxe](#ql-reference.select.syntax)
+ [Parameters](#ql-reference.select.parameters)
+ [Exemples](#ql-reference.select.examples)

## Syntaxe
<a name="ql-reference.select.syntax"></a>

```
SELECT expression  [, ...] 
FROM table[.index]
[ WHERE condition ] [ [ORDER BY key [DESC|ASC] , ...]
```

## Parameters
<a name="ql-reference.select.parameters"></a>

***expression***  
(Obligatoire) Projection formée à partir du caractère générique `*` ou d’une liste de projection d’un ou de plusieurs noms d’attributs ou chemins d’accès de documents de l’ensemble de résultats. Une expression peut être constituée d’appels à [Utilisation de fonctions PartiQL avec DynamoDB](ql-functions.md) ou de champs modifiés par [Opérateurs arithmétiques, de comparaison et logiques PartiQL pour DynamoDB](ql-operators.md).

***table***  
(Obligatoire) Nom de la table à interroger.

***index***  
(Facultatif) Nom de l’index à interroger.  
Vous devez ajouter des guillemets doubles au nom de la table et au nom de l’index lorsque vous interrogez un index.  

```
SELECT * 
FROM "TableName"."IndexName"
```

***condition***  
(Facultatif) Critères de sélection pour la requête.  
Pour s’assurer qu’une instruction `SELECT` n’entraîne pas une analyse de table complète, la condition de clause `WHERE` doit spécifier une clé de partition. Utilisez l’opérateur d’égalité ou IN (DANS).  
Par exemple, si vous avez une table `Orders` avec une clé de partition `OrderID` et des attributs autres que de clé, dont une `Address`, les instructions suivantes n’entraînent pas d’analyse de table complète :  

```
SELECT * 
FROM "Orders" 
WHERE OrderID = 100

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 and Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 or OrderID = 200

SELECT * 
FROM "Orders" 
WHERE OrderID IN [100, 300, 234]
```
En revanche, les instructions `SELECT` suivantes entraînent une analyse de table complète :  

```
SELECT * 
FROM "Orders" 
WHERE OrderID > 1

SELECT * 
FROM "Orders" 
WHERE Address='some address'

SELECT * 
FROM "Orders" 
WHERE OrderID = 100 OR Address='some address'
```

***key***  
(Facultatif) Clé de hachage ou clé de tri à utiliser pour ordonner les résultats renvoyés. L’ordre par défaut est croissant (`ASC`). Spécifiez `DESC` si vous voulez que les résultats soient réordonnés dans l’ordre décroissant.

**Note**  
Si vous omettez la clause `WHERE`, tous les éléments de la table sont extraits.

## Exemples
<a name="ql-reference.select.examples"></a>

La requête suivante renvoie un élément existant de la table `Orders` en spécifiant la clé de partition, `OrderID`, et en utilisant l’opérateur d’égalité.

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1
```

La requête suivante renvoie tous les éléments de la table `Orders` ayant une clé de partition spécifique, `OrderID`, et leurs valeurs en utilisant l’opérateur OR (OU).

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID = 1 OR OrderID = 2
```

La requête suivante renvoie tous les éléments de la table `Orders` ayant une clé de partition spécifique, `OrderID`, et leurs valeurs en utilisant l’opérateur IN (DANS). Les résultats renvoyés sont dans l’ordre décroissant de la valeur de leur attribut de clé `OrderID`.

```
SELECT OrderID, Total
FROM "Orders"
WHERE OrderID IN [1, 2, 3] ORDER BY OrderID DESC
```

La requête suivante affiche une analyse de table complète qui renvoie tous les éléments de la table `Orders` dont la valeur `Total` est supérieure à 500, où `Total` est un attribut autre que de clé.

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total > 500
```

La requête suivante affiche une analyse de table complète qui renvoie tous les éléments de la table `Orders`dans une plage `Total` spécifique, en utilisant l’opérateur IN (DANS) et un attribut autre que de clé `Total`.

```
SELECT OrderID, Total 
FROM "Orders"
WHERE Total IN [500, 600]
```

La requête suivante affiche une analyse de table complète qui renvoie tous les éléments de la table `Orders`dans une plage `Total` spécifique, en utilisant l’opérateur BETWEEN (ENTRE) et un attribut autre que de clé `Total`.

```
SELECT OrderID, Total 
FROM "Orders" 
WHERE Total BETWEEN 500 AND 600
```

La requête suivante renvoie la première date à laquelle un Firestick a été utilisé, en spécifiant la clé de partition `CustomerID` et une clé de tri `MovieID` dans la condition de clause WHERE, et en utilisant des chemins d’accès de document dans la clause SELECT.

```
SELECT Devices.FireStick.DateWatched[0] 
FROM WatchList 
WHERE CustomerID= 'C1' AND MovieID= 'M1'
```

La requête suivante affiche une analyse de table complète qui renvoie la liste des éléments pour lesquels un Firestick a été utilisé pour la première fois après le 24/12/19, en utilisant des chemins de document dans la condition de la clause WHERE.

```
SELECT Devices 
FROM WatchList 
WHERE Devices.FireStick.DateWatched[0] >= '12/24/19'
```

# Instructions de mise à jour de PartiQL pour DynamoDB
<a name="ql-reference.update"></a>

Utilisez l’instruction `UPDATE` pour modifier la valeur d’un ou de plusieurs attributs dans un élément d’une table Amazon DynamoDB. 

**Note**  
Vous ne pouvez mettre à jour qu’un seul élément à la fois et ne pouvez pas émettre une instruction PartiQL pour DynamoDB qui met à jour plusieurs éléments. Pour plus d’informations sur la mise à jour de plusieurs éléments, consultez [Exécution de transactions avec PartiQL pour DynamoDB](ql-reference.multiplestatements.transactions.md) ou [Exécution d’opérations par lot avec PartiQL pour DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntaxe](#ql-reference.update.syntax)
+ [Parameters](#ql-reference.update.parameters)
+ [Valeur renvoyée](#ql-reference.update.return)
+ [Exemples](#ql-reference.update.examples)

## Syntaxe
<a name="ql-reference.update.syntax"></a>

```
UPDATE  table  
[SET | REMOVE]  path  [=  data] […]
WHERE condition [RETURNING returnvalues]
<returnvalues>  ::= [ALL OLD | MODIFIED OLD | ALL NEW | MODIFIED NEW] *
```

## Parameters
<a name="ql-reference.update.parameters"></a>

***table***  
(Obligatoire) Table contenant les données à modifier.

***path***  
(Obligatoire) Nom d’attribut ou chemin d’accès de document à créer ou à modifier.

***data***  
(Obligatoire) Valeur d’attribut ou résultat d’une opération.  
Opérations prises en charge à utiliser avec SET :  
+ LIST\$1APPEND : ajoute une valeur à un type de liste.
+ SET\$1ADD : ajoute une valeur à un ensemble de nombres ou de chaînes.
+ SET\$1DELETE : supprime une valeur d’un ensemble de nombres ou de chaînes.

***condition***  
(Obligatoire) Critères de sélection de l’élément à modifier. Le résultat de cette condition doit être une seule valeur de clé primaire.

***returnvalues***  
(Facultatif) Utilisez `returnvalues` si vous souhaitez obtenir les attributs de l’élément avant ou après sa mise à jour. Les valeurs valides sont :   
+ `ALL OLD *` – Renvoie tous les attributs de l’élément avant l’opération de mise à jour.
+ `MODIFIED OLD *` – Renvoie uniquement les attributs mis à jour avant l’opération de mise à jour.
+ `ALL NEW *` – Renvoie tous les attributs de l’élément après l’opération de mise à jour.
+ `MODIFIED NEW *` – Renvoie uniquement les attributs mis à jour après l’opération `UpdateItem`.

## Valeur renvoyée
<a name="ql-reference.update.return"></a>

Cette instruction ne renvoie de valeur que si le paramètre `returnvalues` est spécifié.

**Note**  
Si la clause WHERE de l’instruction UPDATE ne produit le résultat true pour aucun élément de la table DynamoDB, `ConditionalCheckFailedException` est renvoyé.

## Exemples
<a name="ql-reference.update.examples"></a>

Mettez à jour une valeur d’attribut d’un élément existant. Si l’attribut n’existe pas, il est créé.

La requête suivante met à jour un élément dans la table `"Music"` en ajoutant un attribut de type Number (`AwardsWon`) et un attribut de type Map (`AwardDetail`).

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

Vous pouvez ajouter `RETURNING ALL OLD *` pour renvoyer les attributs tels qu’ils apparaissaient avant l’opération `Update`.

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL OLD *
```

Ceci renvoie les informations suivantes :

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

Vous pouvez ajouter `RETURNING ALL NEW *` pour renvoyer les attributs tels qu’ils sont apparus après l’opération `Update`.

```
UPDATE "Music" 
SET AwardsWon=1 
SET AwardDetail={'Grammys':[2020, 2018]}  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
RETURNING ALL NEW *
```

Ceci renvoie les informations suivantes :

```
{
    "Items": [
        {
            "AwardDetail": {
                "M": {
                    "Grammys": {
                        "L": [
                            {
                                "N": "2020"
                            },
                            {
                                "N": "2018"
                            }
                        ]
                    }
                }
            },
            "AwardsWon": {
                "N": "1"
            }
        }
    ]
}
```

La requête suivante met à jour un élément dans la table `"Music"` en effectuant un ajout à une liste `AwardDetail.Grammys`.

```
UPDATE "Music" 
SET AwardDetail.Grammys =list_append(AwardDetail.Grammys,[2016])  
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

La requête suivante met à jour un élément dans la table `"Music"` en effectuant une suppression d’une liste `AwardDetail.Grammys`.

```
UPDATE "Music" 
REMOVE AwardDetail.Grammys[2]   
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

La requête suivante met à jour un élément dans la table `"Music"` en ajoutant `BillBoard` au mappage `AwardDetail`.

```
UPDATE "Music" 
SET AwardDetail.BillBoard=[2020] 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

La requête suivante met à jour un élément dans la table `"Music"` en ajoutant l’attribut d’ensemble de chaînes `BandMembers`.

```
UPDATE "Music" 
SET BandMembers =<<'member1', 'member2'>> 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

La requête suivante met à jour un élément dans la table `"Music"` en ajoutant `newbandmember` à l’ensemble de chaînes `BandMembers`.

```
UPDATE "Music" 
SET BandMembers =set_add(BandMembers, <<'newbandmember'>>) 
WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'
```

# Instructions de suppression de PartiQL pour DynamoDB
<a name="ql-reference.delete"></a>

Utilisez l’instruction `DELETE` pour supprimer un élément existant de votre table Amazon DynamoDB.

**Note**  
Vous ne pouvez supprimer qu’un seul élément à la fois. Vous ne pouvez pas émettre une seule instruction PartiQL pour DynamoDB qui supprime plusieurs éléments. Pour plus d’informations sur la suppression de plusieurs éléments, consultez [Exécution de transactions avec PartiQL pour DynamoDB](ql-reference.multiplestatements.transactions.md) ou [Exécution d’opérations par lot avec PartiQL pour DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntaxe](#ql-reference.delete.syntax)
+ [Parameters](#ql-reference.delete.parameters)
+ [Valeur renvoyée](#ql-reference.delete.return)
+ [Exemples](#ql-reference.delete.examples)

## Syntaxe
<a name="ql-reference.delete.syntax"></a>

```
DELETE FROM table 
 WHERE condition [RETURNING returnvalues]
 <returnvalues>  ::= ALL OLD *
```

## Parameters
<a name="ql-reference.delete.parameters"></a>

***table***  
(Obligatoire) Table DynamoDB contenant l’élément à supprimer.

***condition***  
(Obligatoire) Critères de sélection de l’élément à supprimer. Le résultat de cette condition doit être une seule valeur de clé primaire.

***returnvalues***  
(Facultatif) Utilisez `returnvalues` si vous souhaitez obtenir les attributs de l’élément avant sa suppression. Les valeurs valides sont :   
+ `ALL OLD *` – Le contenu de l’ancien élément est renvoyé.

## Valeur renvoyée
<a name="ql-reference.delete.return"></a>

Cette instruction ne renvoie de valeur que si le paramètre `returnvalues` est spécifié.

**Note**  
Si la table DynamoDB ne contient aucun élément dont la même clé primaire est la même que celle de l’élément pour lequel l’instruction DELETE est émise, le résultat SUCCESS est renvoyé avec 0 élément supprimé. Si la table contient un élément avec la même clé primaire, mais que le résultat de la condition dans la clause WHERE de l’instruction DELETE est false (faux), l’erreur `ConditionalCheckFailedException` est renvoyée.

## Exemples
<a name="ql-reference.delete.examples"></a>

La requête suivante interroge un élément dans la table `"Music"`.

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks'
```

Vous pouvez ajouter le paramètre `RETURNING ALL OLD *` pour renvoyer les données supprimées.

```
DELETE FROM "Music" WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks' RETURNING ALL OLD *
```

L’instruction `Delete` renvoie désormais ce qui suit :

```
{
    "Items": [
        {
            "Artist": {
                "S": "Acme Band"
            },
            "SongTitle": {
                "S": "PartiQL Rocks"
            }
        }
    ]
}
```

# Instructions d’insertion de PartiQL pour DynamoDB
<a name="ql-reference.insert"></a>

Utilisez l’instruction `INSERT` pour ajouter un élément à une table dans Amazon DynamoDB.

**Note**  
Vous ne pouvez insérer qu’un seul élément à la fois et ne pouvez pas émettre une instruction PartiQL pour DynamoDB qui insère plusieurs éléments. Pour plus d’informations sur l’insertion de plusieurs éléments, consultez [Exécution de transactions avec PartiQL pour DynamoDB](ql-reference.multiplestatements.transactions.md) ou [Exécution d’opérations par lot avec PartiQL pour DynamoDB](ql-reference.multiplestatements.batching.md).

**Topics**
+ [Syntaxe](#ql-reference.insert.syntax)
+ [Parameters](#ql-reference.insert.parameters)
+ [Valeur renvoyée](#ql-reference.insert.return)
+ [Exemples](#ql-reference.insert.examples)

## Syntaxe
<a name="ql-reference.insert.syntax"></a>

Insérez un seul élément.

```
INSERT INTO table VALUE item
```

## Parameters
<a name="ql-reference.insert.parameters"></a>

***table***  
(Obligatoire) Table dans laquelle vous souhaitez insérer les données. La table doit déjà exister.

***item***  
(Obligatoire) Elément DynamoDB valide représenté sous la forme d’un [Tuple PartiqL](https://partiql.org/docs.html). Vous devez spécifier *un seul* élément. Chaque nom d’attribut dans l’élément est sensible à la casse et peut être indiqué par des *apostrophes* (`'...'`) dans PartiQL.  
Les valeurs de chaîne sont également indiquées par des *apostrophes* (`'...'`) dans PartiQL.

## Valeur renvoyée
<a name="ql-reference.insert.return"></a>

Cette instruction ne renvoie aucune valeur.

**Note**  
Si la table DynamoDB contient déjà un élément avec la même clé primaire que la clé primaire de l’élément inséré, l’erreur `DuplicateItemException` est renvoyée.

## Exemples
<a name="ql-reference.insert.examples"></a>

```
INSERT INTO "Music" value {'Artist' : 'Acme Band','SongTitle' : 'PartiQL Rocks'}
```

# Utilisation de fonctions PartiQL avec DynamoDB
<a name="ql-functions"></a>

PartiQL dans Amazon DynamoDB prend en charge les variantes intégrées suivantes des fonctions standard SQL.

**Note**  
Les fonctions SQL qui ne figurent pas dans cette liste ne sont actuellement pas prises en charge dans DynamoDB.

## Fonctions d’agrégation
<a name="ql-functions.aggregate"></a>
+ [Utilisation de la fonction SIZE avec PartiQL pour Amazon DynamoDB](ql-functions.size.md)

## Fonctions conditionnelles
<a name="ql-functions.conditional"></a>
+ [Utilisation de la fonction EXISTS avec PartiQL pour DynamoDB](ql-functions.exists.md)
+ [Utilisation de la fonction ATTRIBUTE\$1TYPE avec PartiQL pour DynamoDB](ql-functions.attribute_type.md)
+ [Utilisation de la fonction BEGINS\$1WITH avec PartiQL pour DynamoDB](ql-functions.beginswith.md)
+ [Utilisation de la fonction CONTAINS avec PartiQL pour DynamoDB](ql-functions.contains.md)
+ [Utilisation de la fonction MISSING avec PartiQL pour DynamoDB](ql-functions.missing.md)

# Utilisation de la fonction EXISTS avec PartiQL pour DynamoDB
<a name="ql-functions.exists"></a>

Vous pouvez utiliser la fonction EXISTS pour effectuer la même opération que la fonction `ConditionCheck` dans l’API [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems). Vous ne pouvez utiliser la fonction EXISTS que dans les transactions.

Pour une valeur donnée, la fonction renvoie `TRUE` si la valeur est une collection non vide. Sinon, la valeur renvoyée est `FALSE`.

**Note**  
Vous ne pouvez utiliser cette fonction que dans les opérations transactionnelles.

## Syntaxe
<a name="ql-functions.exists.syntax"></a>

```
EXISTS ( statement )
```

## Arguments
<a name="ql-functions.exists.arguments"></a>

*statement*  
(Obligatoire) Instruction SELECT que la fonction évalue.  
L’instruction SELECT doit spécifier une clé primaire complète et une autre condition.

## Type de retour
<a name="ql-functions.exists.return-type"></a>

`bool`

## Exemples
<a name="ql-functions.exists.examples"></a>

```
EXISTS(
    SELECT * FROM "Music" 
    WHERE "Artist" = 'Acme Band' AND "SongTitle" = 'PartiQL Rocks')
```

# Utilisation de la fonction BEGINS\$1WITH avec PartiQL pour DynamoDB
<a name="ql-functions.beginswith"></a>

La fonction renvoie `TRUE` si l’attribut spécifié commence par une sous-chaîne particulière.

## Syntaxe
<a name="ql-functions.beginswith.syntax"></a>

```
begins_with(path, value )
```

## Arguments
<a name="ql-functions.beginswith.arguments"></a>

*path*  
(Obligatoire) Chemin d’accès du nom d’attribut ou du document à utiliser.

*valeur*  
(Obligatoire) Chaîne à rechercher.

## Type de retour
<a name="ql-functions.beginswith.return-type"></a>

`bool`

## Exemples
<a name="ql-functions.beginswith.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND begins_with("Address", '7834 24th')
```

# Utilisation de la fonction MISSING avec PartiQL pour DynamoDB
<a name="ql-functions.missing"></a>

La fonction renvoie `TRUE` si l’élément ne contient pas l’attribut spécifié. Seuls des opérateurs d’égalité et d’inégalité peuvent être utilisés avec cette fonction.

## Syntaxe
<a name="ql-functions.missing.syntax"></a>

```
 attributename IS | IS NOT  MISSING 
```

## Arguments
<a name="ql-functions.missing.arguments"></a>

*attributename*  
(Obligatoire) Nom d’attribut à rechercher.

## Type de retour
<a name="ql-functions.missing.return-type"></a>

`bool`

## Exemples
<a name="ql-functions.missing.examples"></a>

```
SELECT * FROM Music WHERE "Awards" is MISSING
```

# Utilisation de la fonction ATTRIBUTE\$1TYPE avec PartiQL pour DynamoDB
<a name="ql-functions.attribute_type"></a>

La fonction renvoie `TRUE` si l’attribut dans le chemin d’accès spécifié est d’un type de données particulier.

## Syntaxe
<a name="ql-functions.attribute_type.syntax"></a>

```
attribute_type( attributename, type )
```

## Arguments
<a name="ql-functions.attribute_type.arguments"></a>

*attributename*  
(Obligatoire) Nom d’attribut à utiliser.

*type*  
(Obligatoire) Type d’attribut à vérifier. Pour obtenir la liste des valeurs valides, consultez [attribute\$1type](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions) DynamoDB.

## Type de retour
<a name="ql-functions.attribute_type.return-type"></a>

`bool`

## Exemples
<a name="ql-functions.attribute_type.examples"></a>

```
SELECT * FROM "Music" WHERE attribute_type("Artist", 'S')
```

# Utilisation de la fonction CONTAINS avec PartiQL pour DynamoDB
<a name="ql-functions.contains"></a>

La fonction renvoie `TRUE` si l’attribut spécifié par le chemin d’accès est l’un des attributs suivants :
+ Une chaîne contenant une sous-chaîne particulière. 
+ Un ensemble contenant un élément particulier.

Pour plus d’informations, consultez la fonction DynamoDB [contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions). 

## Syntaxe
<a name="ql-functions.contains.syntax"></a>

```
contains( path, substring )
```

## Arguments
<a name="ql-functions.contains.arguments"></a>

*path*  
(Obligatoire) Chemin d’accès du nom d’attribut ou du document à utiliser.

*substring*  
(Obligatoire) Sous-chaîne d’attribut ou membre d’ensemble à vérifier. Pour plus d’informations, consultez la fonction DynamoDB [contains](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

## Type de retour
<a name="ql-functions.contains.return-type"></a>

`bool`

## Exemples
<a name="ql-functions.contains.examples"></a>

```
SELECT * FROM "Orders" WHERE "OrderID"=1 AND contains("Address", 'Kirkland')
```

# Utilisation de la fonction SIZE avec PartiQL pour Amazon DynamoDB
<a name="ql-functions.size"></a>

Renvoie un nombre représentant la taille en octets d’un attribut. Les types de données valides à utiliser avec la fonction Size sont les suivants. Pour plus d’informations, consultez la fonction DynamoDB [size](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

## Syntaxe
<a name="ql-functions.size.syntax"></a>

```
size( path)
```

## Arguments
<a name="ql-functions.size.arguments"></a>

*path*  
(Obligatoire) Chemin d’accès du nom d’attribut ou du document à utiliser.   
Pour les types pris en charge, consultez la fonction DynamoDB [size](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.OperatorsAndFunctions.html#Expressions.OperatorsAndFunctions.Functions).

## Type de retour
<a name="ql-functions.size.return-type"></a>

`int`

## Exemples
<a name="ql-functions.size.examples"></a>

```
 SELECT * FROM "Orders" WHERE "OrderID"=1 AND size("Image") >300
```

# Opérateurs arithmétiques, de comparaison et logiques PartiQL pour DynamoDB
<a name="ql-operators"></a>

PartiQL dans Amazon DynamoDB prend en charge les [opérateurs standard SQL](https://www.w3schools.com/sql/sql_operators.asp) suivants.

**Note**  
Les opérateurs SQL qui ne figurent pas dans cette liste ne sont actuellement pas pris en charge dans DynamoDB.

## Opérateurs arithmétiques
<a name="ql-operators.arithmetic"></a>


****  

| Opérateur | Description | 
| --- | --- | 
| \$1 | Addition | 
| - | Soustraction | 

## Opérateurs de comparaison
<a name="ql-operators.comparison"></a>


****  

| Opérateur | Description | 
| --- | --- | 
| = | Egal à | 
| <> | Non égal à | 
| \$1= | Non égal à | 
| > | Supérieure à | 
| < | Inférieur à | 
| >= | Supérieur ou égal à | 
| <= | Inférieur ou égal à | 

## Opérateurs logiques
<a name="ql-operators.logical"></a>


****  

| Opérateur | Description | 
| --- | --- | 
| AND | TRUE si toutes les conditions séparées par AND sont TRUE | 
| BETWEEN |  `TRUE` si l’opérande est comprise dans la plage des comparaisons. Cet opérateur inclut les limites inférieure et supérieure des opérandes auxquels vous l’appliquez.  | 
| IN | `TRUE`si l'opérande est égal à l'une d'une liste d'expressions (au maximum 50 valeurs d'attribut de hachage ou au maximum 100 valeurs d'attributs non clés). Les résultats sont affichés sous forme de pages contenant jusqu'à 10 éléments. Si la `IN` liste contient plus de valeurs, vous devez utiliser les valeurs `NextToken` renvoyées dans la réponse pour récupérer les pages suivantes. | 
| IS | TRUE si l’opérande est un type de données PartiQL spécifique, dont NULL ou MISSING | 
| NOT | Inverse la valeur d’une expression booléenne donnée | 
| OR | TRUE si une ou plusieurs des conditions séparées par OR sont TRUE | 

Pour plus d’informations sur l’utilisation des opérateurs logiques, consultez [Comparaisons](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Comparators) et [Évaluations logiques](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.LogicalEvaluations).

# Exécution de transactions avec PartiQL pour DynamoDB
<a name="ql-reference.multiplestatements.transactions"></a>

Cette section décrit comment utiliser des transactions avec PartiQL pour DynamoDB. Les transactions PartiQL sont limitées à 100 instructions (actions) au total.

Pour plus d’informations sur les transactions DynamoDB, consultez [Gestion des flux de travail complexes avec les transactions DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transactions.html).

**Note**  
La transaction entière doit être composée d’instructions de lecture ou d’instructions d’écriture. Vous ne pouvez pas mélanger les deux dans une seule transaction. La fonction EXISTS est une exception. Vous pouvez l'utiliser pour vérifier l'état d'attributs spécifiques de l'article de la même manière que dans le cadre de `ConditionCheck` l'opération [TransactWriteItems](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/transaction-apis.html#transaction-apis-txwriteitems)d'API.

**Topics**
+ [Syntaxe](#ql-reference.multiplestatements.transactions.syntax)
+ [Parameters](#ql-reference.multiplestatements.transactions.parameters)
+ [Valeurs renvoyées](#ql-reference.multiplestatements.transactions.return)
+ [Exemples](#ql-reference.multiplestatements.transactions.examples)

## Syntaxe
<a name="ql-reference.multiplestatements.transactions.syntax"></a>

```
[
   {
      "Statement":" statement ",
      "Parameters":[
         {
            " parametertype " : " parametervalue "
         }, ...]
   } , ...
]
```

## Parameters
<a name="ql-reference.multiplestatements.transactions.parameters"></a>

***statement***  
(Obligatoire) Instruction prise en charge PartiQL pour DynamoDB.  
La transaction entière doit être composée d’instructions de lecture ou d’instructions d’écriture. Vous ne pouvez pas mélanger les deux dans une seule transaction.

***parametertype***  
(Facultatif) Type DynamoDB, si des paramètres ont été utilisés lors de la spécification de l’instruction PartiQL.

***parametervalue***  
(Facultatif) Valeur de paramètre si des paramètres ont été utilisés lors de la spécification de l’instruction PartiQL.

## Valeurs renvoyées
<a name="ql-reference.multiplestatements.transactions.return"></a>

Cette instruction ne renvoie aucune valeur pour les opérations d’écriture (INSERT, UPDATE ou DELETE). Toutefois, elle renvoie différentes valeurs pour les opérations de lecture (SELECT) en fonction des conditions spécifiées dans la clause WHERE.

**Note**  
Si l’une des opérations singleton INSERT, UPDATE ou DELETE renvoie une erreur, les transactions sont annulées avec l’exception `TransactionCanceledException`, et le code de motif d’annulation inclut les erreurs des opérations singleton individuelles.

## Exemples
<a name="ql-reference.multiplestatements.transactions.examples"></a>

L’exemple suivant exécute plusieurs instructions sous forme de transaction.

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

1. Enregistrez le code JSON suivant dans un fichier nommé partiql.json. 

   ```
   [
       {
           "Statement": "EXISTS(SELECT * FROM \"Music\" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is  MISSING)"
       },
       {
           "Statement": "INSERT INTO Music value {'Artist':?,'SongTitle':'?'}",
           "Parameters": [{\"S\": \"Acme Band\"}, {\"S\": \"Best Song\"}]
       },
       {
           "Statement": "UPDATE \"Music\" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist='Acme Band' and SongTitle='PartiQL Rocks'"
       }
   ]
   ```

1. Dans une invite de commande, exécutez la commande suivante.

   ```
   aws dynamodb execute-transaction --transact-statements  file://partiql.json
   ```

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

```
public class DynamoDBPartiqlTransaction {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2");
        
        try {
            // Create ExecuteTransactionRequest
            ExecuteTransactionRequest executeTransactionRequest = createExecuteTransactionRequest();
            ExecuteTransactionResult executeTransactionResult = dynamoDB.executeTransaction(executeTransactionRequest);
            System.out.println("ExecuteTransaction successful.");
            // Handle executeTransactionResult

        } catch (Exception e) {
            handleExecuteTransactionErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {
        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static ExecuteTransactionRequest createExecuteTransactionRequest() {
        ExecuteTransactionRequest request = new ExecuteTransactionRequest();
        
        // Create statements
        List<ParameterizedStatement> statements = getPartiQLTransactionStatements();

        request.setTransactStatements(statements);
        return request;
    }

    private static List<ParameterizedStatement> getPartiQLTransactionStatements() {
        List<ParameterizedStatement> statements = new ArrayList<ParameterizedStatement>();

        statements.add(new ParameterizedStatement()
                               .withStatement("EXISTS(SELECT * FROM "Music" where Artist='No One You Know' and SongTitle='Call Me Today' and Awards is  MISSING)"));

        statements.add(new ParameterizedStatement()
                               .withStatement("INSERT INTO "Music" value {'Artist':'?','SongTitle':'?'}")
                               .withParameters(new AttributeValue("Acme Band"),new AttributeValue("Best Song")));

        statements.add(new ParameterizedStatement()
                               .withStatement("UPDATE "Music" SET AwardsWon=1 SET AwardDetail={'Grammys':[2020, 2018]}  where Artist='Acme Band' and SongTitle='PartiQL Rocks'"));

        return statements;
    }

    // Handles errors during ExecuteTransaction execution. Use recommendations in error messages below to add error handling specific to 
    // your application use-case.
    private static void handleExecuteTransactionErrors(Exception exception) {
        try {
            throw exception;
        } catch (TransactionCanceledException tce) {
            System.out.println("Transaction Cancelled, implies a client issue, fix before retrying. Error: " + tce.getErrorMessage());
        } catch (TransactionInProgressException tipe) {
            System.out.println("The transaction with the given request token is already in progress, consider changing " +
                "retry strategy for this type of error. Error: " + tipe.getErrorMessage());
        } catch (IdempotentParameterMismatchException ipme) {
            System.out.println("Request rejected because it was retried with a different payload but with a request token that was already used, " +
                "change request token for this payload to be accepted. Error: " + ipme.getErrorMessage());
        } catch (Exception e) {
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " + 
                "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " + 
                ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " + 
                "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

L’exemple suivant montre les différentes valeurs renvoyées lorsque DynamoDB lit des éléments avec des conditions différentes spécifiées dans la clause WHERE.

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

1. Enregistrez le code JSON suivant dans un fichier nommé partiql.json.

   ```
   [
       // Item exists and projected attribute exists
       {
           "Statement": "SELECT * FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'"
       },
       // Item exists but projected attributes do not exist
       {
           "Statement": "SELECT non_existent_projected_attribute FROM "Music" WHERE Artist='No One You Know' and SongTitle='Call Me Today'"
       },
       // Item does not exist
       {
           "Statement": "SELECT * FROM "Music" WHERE Artist='No One I Know' and SongTitle='Call You Today'"
       }
   ]
   ```

1.  commande suivante, dans une invite de commande.

   ```
   aws dynamodb execute-transaction --transact-statements  file://partiql.json
   ```

1. La réponse suivante est renvoyée :

   ```
   {
       "Responses": [
           // Item exists and projected attribute exists
           {
               "Item": {
                   "Artist":{
                       "S": "No One You Know"
                   },
                   "SongTitle":{
                       "S": "Call Me Today"
                   }    
               }
           },
           // Item exists but projected attributes do not exist
           {
               "Item": {}
           },
           // Item does not exist
           {}
       ]
   }
   ```

------

# Exécution d’opérations par lot avec PartiQL pour DynamoDB
<a name="ql-reference.multiplestatements.batching"></a>

Cette section décrit comment utiliser des opérations par lot avec PartiQL pour DynamoDB.

**Note**  
Le lot entier doit être composé d'instructions de lecture ou d'instructions d'écriture. Vous ne pouvez pas mélanger les deux dans une seule opération par lot.
`BatchExecuteStatement` et `BatchWriteItem` ne peuvent pas exécuter plus de 25 instructions par lot.
`BatchExecuteStatement` utilise `BatchGetItem` ce qui prend une liste de clés primaires dans des instructions séparées.

**Topics**
+ [Syntaxe](#ql-reference.multiplestatements.batching.syntax)
+ [Parameters](#ql-reference.multiplestatements.batching.parameters)
+ [Exemples](#ql-reference.multiplestatements.batching.examples)

## Syntaxe
<a name="ql-reference.multiplestatements.batching.syntax"></a>

```
[
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#9StkWHYTxm7x2AqSXcrfu7' AND sk = 'info'"
  },
  {
    "Statement": "SELECT pk FROM ProblemSet WHERE pk = 'p#isC2ChceGbxHgESc4szoTE' AND sk = 'info'"
  }
]
```

```
[
   {
      "Statement":" statement ",
      "Parameters":[
         {
            " parametertype " : " parametervalue "
         }, ...]
   } , ...
]
```

## Parameters
<a name="ql-reference.multiplestatements.batching.parameters"></a>

***statement***  
(Obligatoire) Instruction prise en charge PartiQL pour DynamoDB.  
+ Le lot entier doit être composé d'instructions de lecture ou d'instructions d'écriture. Vous ne pouvez pas mélanger les deux dans une seule opération par lot.
+ `BatchExecuteStatement` et `BatchWriteItem` ne peuvent pas exécuter plus de 25 instructions par lot.

***parametertype***  
(Facultatif) Type DynamoDB, si des paramètres ont été utilisés lors de la spécification de l’instruction PartiQL.

***parametervalue***  
(Facultatif) Valeur de paramètre si des paramètres ont été utilisés lors de la spécification de l’instruction PartiQL.

## Exemples
<a name="ql-reference.multiplestatements.batching.examples"></a>

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

1. Enregistrez le JSON suivant dans un fichier nommé partiql.json

   ```
   [
      {
   	 "Statement": "INSERT INTO Music VALUE {'Artist':?,'SongTitle':?}",
   	  "Parameters": [{"S": "Acme Band"}, {"S": "Best Song"}]
   	},
   	{
   	 "Statement": "UPDATE Music SET AwardsWon=1, AwardDetail={'Grammys':[2020, 2018]} WHERE Artist='Acme Band' AND SongTitle='PartiQL Rocks'"
       }
   ]
   ```

1. Dans une invite de commande, exécutez la commande suivante.

   ```
   aws dynamodb batch-execute-statement  --statements  file://partiql.json
   ```

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

```
public class DynamoDBPartiqlBatch {

    public static void main(String[] args) {
        // Create the DynamoDB Client with the region you want
        AmazonDynamoDB dynamoDB = createDynamoDbClient("us-west-2");
        
        try {
            // Create BatchExecuteStatementRequest
            BatchExecuteStatementRequest batchExecuteStatementRequest = createBatchExecuteStatementRequest();
            BatchExecuteStatementResult batchExecuteStatementResult = dynamoDB.batchExecuteStatement(batchExecuteStatementRequest);
            System.out.println("BatchExecuteStatement successful.");
            // Handle batchExecuteStatementResult

        } catch (Exception e) {
            handleBatchExecuteStatementErrors(e);
        }
    }

    private static AmazonDynamoDB createDynamoDbClient(String region) {

        return AmazonDynamoDBClientBuilder.standard().withRegion(region).build();
    }

    private static BatchExecuteStatementRequest createBatchExecuteStatementRequest() {
        BatchExecuteStatementRequest request = new BatchExecuteStatementRequest();

        // Create statements
        List<BatchStatementRequest> statements = getPartiQLBatchStatements();

        request.setStatements(statements);
        return request;
    }

    private static List<BatchStatementRequest> getPartiQLBatchStatements() {
        List<BatchStatementRequest> statements = new ArrayList<BatchStatementRequest>();

        statements.add(new BatchStatementRequest()
                               .withStatement("INSERT INTO Music value {'Artist':'Acme Band','SongTitle':'PartiQL Rocks'}"));

        statements.add(new BatchStatementRequest()
                               .withStatement("UPDATE Music set AwardDetail.BillBoard=[2020] where Artist='Acme Band' and SongTitle='PartiQL Rocks'"));

        return statements;
    }

    // Handles errors during BatchExecuteStatement execution. Use recommendations in error messages below to add error handling specific to 
    // your application use-case.
    private static void handleBatchExecuteStatementErrors(Exception exception) {
        try {
            throw exception;
        } catch (Exception e) {
            // There are no API specific errors to handle for BatchExecuteStatement, common DynamoDB API errors are handled below
            handleCommonErrors(e);
        }
    }

    private static void handleCommonErrors(Exception exception) {
        try {
            throw exception;
        } catch (InternalServerErrorException isee) {
            System.out.println("Internal Server Error, generally safe to retry with exponential back-off. Error: " + isee.getErrorMessage());
        } catch (RequestLimitExceededException rlee) {
            System.out.println("Throughput exceeds the current throughput limit for your account, increase account level throughput before " + 
                "retrying. Error: " + rlee.getErrorMessage());
        } catch (ProvisionedThroughputExceededException ptee) {
            System.out.println("Request rate is too high. If you're using a custom retry strategy make sure to retry with exponential back-off. " +
                "Otherwise consider reducing frequency of requests or increasing provisioned capacity for your table or secondary index. Error: " + 
                ptee.getErrorMessage());
        } catch (ResourceNotFoundException rnfe) {
            System.out.println("One of the tables was not found, verify table exists before retrying. Error: " + rnfe.getErrorMessage());
        } catch (AmazonServiceException ase) {
            System.out.println("An AmazonServiceException occurred, indicates that the request was correctly transmitted to the DynamoDB " + 
                "service, but for some reason, the service was not able to process it, and returned an error response instead. Investigate and " +
                "configure retry strategy. Error type: " + ase.getErrorType() + ". Error message: " + ase.getErrorMessage());
        } catch (AmazonClientException ace) {
            System.out.println("An AmazonClientException occurred, indicates that the client was unable to get a response from DynamoDB " +
                "service, or the client was unable to parse the response from the service. Investigate and configure retry strategy. "+
                "Error: " + ace.getMessage());
        } catch (Exception e) {
            System.out.println("An exception occurred, investigate and configure retry strategy. Error: " + e.getMessage());
        }
    }

}
```

------

# Politiques de sécurité IAM avec PartiQL pour DynamoDB
<a name="ql-iam"></a>

Les autorisations suivantes sont requises :
+ Pour lire des éléments à l’aide de PartiQL pour DynamoDB, vous devez disposer de l’autorisation `dynamodb:PartiQLSelect` sur la table ou l’index.
+ Pour insérer des éléments à l’aide de PartiQL pour DynamoDB, vous devez disposer de l’autorisation `dynamodb:PartiQLInsert` sur la table ou l’index.
+ Pour mettre à jour des éléments à l’aide de PartiQL pour DynamoDB, vous devez disposer de l’autorisation `dynamodb:PartiQLUpdate` sur la table ou l’index.
+ Pour supprimer des éléments à l’aide de PartiQL pour DynamoDB, vous devez disposer de l’autorisation `dynamodb:PartiQLDelete` sur la table ou l’index.

## Exemple : autoriser toutes les instructions PartiQL pour DynamoDB () sur une table Select/Insert/Update/Delete
<a name="access-policy-ql-iam-example1"></a>

La politique IAM suivante accorde les autorisations nécessaires pour exécuter toutes les instructions PartiQL pour DynamoDB sur une table. 

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Exemple : Autoriser les instructions PartiQL select pour DynamoDB sur une table
<a name="access-policy-ql-iam-example2"></a>

La politique IAM suivante accorde les autorisations nécessaires pour exécuter l’instruction `select` sur une table spécifique.

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Exemple : Autoriser les instructions PartiQL insert pour DynamoDB sur un index
<a name="access-policy-ql-iam-example3"></a>

La politique IAM suivante accorde les autorisations nécessaires pour exécuter l’instruction `insert` sur un index spécifique. 

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music/index/index1"
         ]
      }
   ]
}
```

------

## Exemple : Autoriser les instructions transactionnelles PartiQL pour DynamoDB sur une table
<a name="access-policy-ql-iam-example4"></a>

La politique IAM suivante accorde les autorisations nécessaires pour exécuter uniquement des instructions transactionnelles sur une table spécifique. 

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      }
   ]
}
```

------

## Exemple : Autoriser les lectures et d’écritures non transactionnelles PartiQL pour DynamoDB, et bloquer les instructions de lectures et d’écritures transactionnelles PartiQL sur une table.
<a name="access-policy-ql-iam-example5"></a>

 La politique IAM suivante accorde des autorisations pour exécuter des lectures et des écritures non transactionnelles PartiQL pour DynamoDB tout en bloquant les lectures et écritures transactionnelles PartiQL pour DynamoDB.

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ],
         "Condition":{
            "StringEquals":{
               "dynamodb:EnclosingOperation":[
                  "ExecuteTransaction"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLInsert",
            "dynamodb:PartiQLUpdate",
            "dynamodb:PartiQLDelete",
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/Music"
         ]
      }
   ]
}
```

------

## Exemple : autoriser les instructions de sélection et rejeter les instructions d’analyse de table complète dans PartiQL pour DynamoDB
<a name="access-policy-ql-iam-example6"></a>

La politique IAM suivante accorde des autorisations pour exécuter l’instruction `select` sur une table spécifique tout en bloquant les instructions `select` qui entraînent une analyse de table complète.

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

****  

```
{
   "Version":"2012-10-17",		 	 	 
   "Statement":[
      {
         "Effect":"Deny",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ],
         "Condition":{
            "Bool":{
               "dynamodb:FullTableScan":[
                  "true"
               ]
            }
         }
      },
      {
         "Effect":"Allow",
         "Action":[
            "dynamodb:PartiQLSelect"
         ],
         "Resource":[
            "arn:aws:dynamodb:us-west-2:123456789012:table/WatchList"
         ]
      }
   ]
}
```

------

# Utilisation des éléments : Java
<a name="JavaDocumentAPIItemCRUD"></a>

Vous pouvez utiliser l'API AWS SDK pour Java Document pour effectuer des opérations classiques de création, de lecture, de mise à jour et de suppression (CRUD) sur les éléments Amazon DynamoDB d'une table.

**Note**  
Le kit SDK pour Java fournit également un modèle de persistance des objets qui vous permet de mapper vos classes côté client à des tables DynamoDB. Cette approche peut réduire la quantité de code que vous avez à écrire. Pour de plus amples informations, veuillez consulter [Java 1.x : Dynamo DBMapper](DynamoDBMapper.md).

Cette section comporte les exemples Java pour exécuter plusieurs actions d’élément d’API de document Java et plusieurs exemples opérationnels.

**Topics**
+ [Insertion d’un élément](#PutDocumentAPIJava)
+ [Obtention d’un élément](#JavaDocumentAPIGetItem)
+ [Écriture par lots : insertion et suppression de plusieurs éléments](#BatchWriteDocumentAPIJava)
+ [Obtention par lots : obtention de plusieurs éléments](#JavaDocumentAPIBatchGetItem)
+ [Mise à jour d’un élément](#JavaDocumentAPIItemUpdate)
+ [Suppression d’un élément](#DeleteMidLevelJava)
+ [Exemple : opérations CRUD à l'aide de l'API du AWS SDK pour Java document](JavaDocumentAPICRUDExample.md)
+ [Exemple : opérations par lots à l'aide de l'API AWS SDK pour Java du document](batch-operation-document-api-java.md)
+ [Exemple : gestion des attributs de type binaire à l'aide de l'API du AWS SDK pour Java document](JavaDocumentAPIBinaryTypeExample.md)

## Insertion d’un élément
<a name="PutDocumentAPIJava"></a>

La méthode `putItem` stocke un élément dans une table. Si l’élément existe, il remplace la totalité de l’élément. Au lieu de remplacer l’élément entier, vous pouvez mettre à jour uniquement des attributs spécifiques à l’aide de la méthode `updateItem`. Pour de plus amples informations, veuillez consulter [Mise à jour d’un élément](#JavaDocumentAPIItemUpdate). 

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

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import java.util.HashMap;

/**
 * Before running this Java V2 code example, set up your development
 * environment, including your credentials.
 *
 * For more information, see the following documentation topic:
 *
 * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
 *
 * To place items into an Amazon DynamoDB table using the AWS SDK for Java V2,
 * its better practice to use the
 * Enhanced Client. See the EnhancedPutItem example.
 */
public class PutItem {
    public static void main(String[] args) {
        final String usage = """

                Usage:
                    <tableName> <key> <keyVal> <albumtitle> <albumtitleval> <awards> <awardsval> <Songtitle> <songtitleval>

                Where:
                    tableName - The Amazon DynamoDB table in which an item is placed (for example, Music3).
                    key - The key used in the Amazon DynamoDB table (for example, Artist).
                    keyval - The key value that represents the item to get (for example, Famous Band).
                    albumTitle - The Album title (for example, AlbumTitle).
                    AlbumTitleValue - The name of the album (for example, Songs About Life ).
                    Awards - The awards column (for example, Awards).
                    AwardVal - The value of the awards (for example, 10).
                    SongTitle - The song title (for example, SongTitle).
                    SongTitleVal - The value of the song title (for example, Happy Day).
                **Warning** This program will  place an item that you specify into a table!
                """;

        if (args.length != 9) {
            System.out.println(usage);
            System.exit(1);
        }

        String tableName = args[0];
        String key = args[1];
        String keyVal = args[2];
        String albumTitle = args[3];
        String albumTitleValue = args[4];
        String awards = args[5];
        String awardVal = args[6];
        String songTitle = args[7];
        String songTitleVal = args[8];

        Region region = Region.US_EAST_1;
        DynamoDbClient ddb = DynamoDbClient.builder()
                .region(region)
                .build();

        putItemInTable(ddb, tableName, key, keyVal, albumTitle, albumTitleValue, awards, awardVal, songTitle,
                songTitleVal);
        System.out.println("Done!");
        ddb.close();
    }

    public static void putItemInTable(DynamoDbClient ddb,
            String tableName,
            String key,
            String keyVal,
            String albumTitle,
            String albumTitleValue,
            String awards,
            String awardVal,
            String songTitle,
            String songTitleVal) {

        HashMap<String, AttributeValue> itemValues = new HashMap<>();
        itemValues.put(key, AttributeValue.builder().s(keyVal).build());
        itemValues.put(songTitle, AttributeValue.builder().s(songTitleVal).build());
        itemValues.put(albumTitle, AttributeValue.builder().s(albumTitleValue).build());
        itemValues.put(awards, AttributeValue.builder().s(awardVal).build());

        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(itemValues)
                .build();

        try {
            PutItemResponse response = ddb.putItem(request);
            System.out.println(tableName + " was successfully updated. The request id is "
                    + response.responseMetadata().requestId());

        } catch (ResourceNotFoundException e) {
            System.err.format("Error: The Amazon DynamoDB table \"%s\" can't be found.\n", tableName);
            System.err.println("Be sure that it exists and that you've typed its name correctly!");
            System.exit(1);
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }
}
```

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

Procédez comme suit : 

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

1. Créez une instance de la classe `Table` pour représenter la table que vous souhaitez utiliser.

1. Création d’une instance de la classe `Item` pour représenter le nouvel élément. Vous devez spécifier la clé primaire du nouvel élément et ses attributs.

1. Appelez la méthode `putItem` de l’objet `Table` à l’aide de l’objet `Item` que vous avez créé à l’étape précédente.

L’exemple de code Java suivant présente les tâches précédentes. Le code écrit un nouvel élément dans la table `ProductCatalog`.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

// Build a list of related items
List<Number> relatedItems = new ArrayList<Number>();
relatedItems.add(341);
relatedItems.add(472);
relatedItems.add(649);

//Build a map of product pictures
Map<String, String> pictures = new HashMap<String, String>();
pictures.put("FrontView", "http://example.com/products/123_front.jpg");
pictures.put("RearView", "http://example.com/products/123_rear.jpg");
pictures.put("SideView", "http://example.com/products/123_left_side.jpg");

//Build a map of product reviews
Map<String, List<String>> reviews = new HashMap<String, List<String>>();

List<String> fiveStarReviews = new ArrayList<String>();
fiveStarReviews.add("Excellent! Can't recommend it highly enough!  Buy it!");
fiveStarReviews.add("Do yourself a favor and buy this");
reviews.put("FiveStar", fiveStarReviews);

List<String> oneStarReviews = new ArrayList<String>();
oneStarReviews.add("Terrible product!  Do not buy this.");
reviews.put("OneStar", oneStarReviews);

// Build the item
Item item = new Item()
    .withPrimaryKey("Id", 123)
    .withString("Title", "Bicycle 123")
    .withString("Description", "123 description")
    .withString("BicycleType", "Hybrid")
    .withString("Brand", "Brand-Company C")
    .withNumber("Price", 500)
    .withStringSet("Color",  new HashSet<String>(Arrays.asList("Red", "Black")))
    .withString("ProductCategory", "Bicycle")
    .withBoolean("InStock", true)
    .withNull("QuantityOnHand")
    .withList("RelatedItems", relatedItems)
    .withMap("Pictures", pictures)
    .withMap("Reviews", reviews);

// Write the item to the table
PutItemOutcome outcome = table.putItem(item);
```

Dans l’exemple précédent, l’élément comporte des attributs scalaires (`String`, `Number`, `Boolean` et `Null`), des ensembles (`String Set`) et des types de documents (`List`, `Map`).

------

### Spécification de paramètres facultatifs
<a name="PutItemJavaDocumentAPIOptions"></a>

Outre les paramètres obligatoires, vous pouvez également spécifier des paramètres facultatifs de la méthode `putItem`. Par exemple, l’extrait de code Java suivant spécifie une condition pour le chargement de l’élément à l’aide d’un paramètre facultatif. Si la condition que vous spécifiez n'est pas remplie, AWS SDK pour Java renvoie un`ConditionalCheckFailedException`. L’extrait de code spécifie les paramètres facultatifs suivants dans la méthode `putItem` :
+ Une `ConditionExpression` qui définit les conditions de la demande. Le code définit la condition selon laquelle l’élément existant ayant la même clé primaire est remplacé seulement s’il comporte un attribut ISBN égal à une valeur spécifique. 
+ Un mappage pour `ExpressionAttributeValues` utilisé dans la condition. Dans ce cas, une seule substitution est nécessaire : l’espace réservé `:val` dans l’expression de condition est remplacé lors de l’exécution par la valeur ISBN réelle à vérifier.

L’exemple suivant ajoute un nouvel élément livre à l’aide de ces paramètres facultatifs.

**Example**  

```
Item item = new Item()
    .withPrimaryKey("Id", 104)
    .withString("Title", "Book 104 Title")
    .withString("ISBN", "444-4444444444")
    .withNumber("Price", 20)
    .withStringSet("Authors",
        new HashSet<String>(Arrays.asList("Author1", "Author2")));

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val", "444-4444444444");

PutItemOutcome outcome = table.putItem(
    item,
    "ISBN = :val", // ConditionExpression parameter
    null,          // ExpressionAttributeNames parameter - we're not using it for this example
    expressionAttributeValues);
```

### PutItem et documents JSON
<a name="PutItemJavaDocumentAPI.JSON"></a>

Vous pouvez stocker un document JSON comme un attribut dans une table DynamoDB. Pour ce faire, utilisez la méthode `withJSON` de `Item`. Cette méthode analyse le document JSON et mappe chaque élément à un type de données DynamoDB natif.

Supposons que vous souhaitiez stocker le document JSON suivant, comportant des fournisseurs qui peuvent exécuter des commandes pour un produit spécifique.

**Example**  

```
{
    "V01": {
        "Name": "Acme Books",
        "Offices": [ "Seattle" ]
    },
    "V02": {
        "Name": "New Publishers, Inc.",
        "Offices": ["London", "New York"
        ]
    },
    "V03": {
        "Name": "Better Buy Books",
        "Offices": [ "Tokyo", "Los Angeles", "Sydney"
        ]
    }
}
```

La méthode `withJSON` vous permet de stocker cela dans la table `ProductCatalog`, dans un attribut `Map` nommé `VendorInfo`. L’extrait de code Java suivant montre comment procéder.

```
// Convert the document into a String.  Must escape all double-quotes.
String vendorDocument = "{"
    + "    \"V01\": {"
    + "        \"Name\": \"Acme Books\","
    + "        \"Offices\": [ \"Seattle\" ]"
    + "    },"
    + "    \"V02\": {"
    + "        \"Name\": \"New Publishers, Inc.\","
    + "        \"Offices\": [ \"London\", \"New York\"" + "]" + "},"
    + "    \"V03\": {"
    + "        \"Name\": \"Better Buy Books\","
    +          "\"Offices\": [ \"Tokyo\", \"Los Angeles\", \"Sydney\""
    + "            ]"
    + "        }"
    + "    }";

Item item = new Item()
    .withPrimaryKey("Id", 210)
    .withString("Title", "Book 210 Title")
    .withString("ISBN", "210-2102102102")
    .withNumber("Price", 30)
    .withJSON("VendorInfo", vendorDocument);

PutItemOutcome outcome = table.putItem(item);
```

## Obtention d’un élément
<a name="JavaDocumentAPIGetItem"></a>

Récupérez un élément unique à l’aide de la méthode `getItem` d’un objet `Table`. Procédez comme suit : 

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

1. Créez une instance de la classe `Table` pour représenter la table que vous souhaitez utiliser.

1. Appelez la méthode `getItem` de l’instance `Table`. Vous devez spécifier la clé primaire de l’élément que vous souhaitez récupérer.

L’exemple de code Java suivant illustre les tâches précédentes. Le code obtient l’élément qui possède la clé de partition spécifiée.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

Item item = table.getItem("Id", 210);
```

### Spécification de paramètres facultatifs
<a name="GetItemJavaDocumentAPIOptions"></a>

Outre les paramètres obligatoires, vous pouvez également spécifier des paramètres facultatifs de la méthode `getItem`. Par exemple, l’extrait de code Java suivant récupère uniquement une liste précise d’attributs et spécifie des lectures fortement cohérentes à l’aide d’une méthode facultative. (Pour en savoir plus sur la cohérence en lecture, consultez [Cohérence en lecture DynamoDB](HowItWorks.ReadConsistency.md).)

Une `ProjectionExpression` vous permet de récupérer uniquement certains attributs ou éléments, plutôt qu’un élément entier. Une `ProjectionExpression` peut spécifier des attributs de niveau supérieur ou imbriqués à l’aide de chemins d’accès au document. Pour de plus amples informations, veuillez consulter [Utilisation d’expressions de projection dans DynamoDB](Expressions.ProjectionExpressions.md).

Les paramètres de la méthode `getItem` ne vous permettent pas de spécifier une cohérence en lecture. Cependant, vous pouvez créer une `GetItemSpec`, qui fournit un accès complet à l’ensemble des entrées de l’opération `GetItem` de bas niveau. L’exemple de code ci-dessous crée une `GetItemSpec` et utilise cette spécification comme entrée de la méthode `getItem`.

**Example**  

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 206)
    .withProjectionExpression("Id, Title, RelatedItems[0], Reviews.FiveStar")
    .withConsistentRead(true);

Item item = table.getItem(spec);

System.out.println(item.toJSONPretty());
```

 Imprimez un `Item` dans un format contrôlable de visu à l’aide de la méthode `toJSONPretty`. La sortie de l’exemple précédent se présente comme suit.

```
{
  "RelatedItems" : [ 341 ],
  "Reviews" : {
    "FiveStar" : [ "Excellent! Can't recommend it highly enough! Buy it!", "Do yourself a favor and buy this" ]
  },
  "Id" : 123,
  "Title" : "20-Bicycle 123"
}
```

### GetItem et documents JSON
<a name="GetItemJavaDocumentAPI.JSON"></a>

Dans la section [PutItem et documents JSON](#PutItemJavaDocumentAPI.JSON),vous stockez un document JSON dans un attribut `Map` nommé `VendorInfo`. La méthode `getItem` vous permet d’extraire la totalité du document au format JSON. Vous pouvez également extraire uniquement certains éléments du document à l’aide de la notation du chemin d’accès au document. L’extrait de code Java suivant illustre ces techniques.

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 210);

System.out.println("All vendor info:");
spec.withProjectionExpression("VendorInfo");
System.out.println(table.getItem(spec).toJSON());

System.out.println("A single vendor:");
spec.withProjectionExpression("VendorInfo.V03");
System.out.println(table.getItem(spec).toJSON());

System.out.println("First office location for this vendor:");
spec.withProjectionExpression("VendorInfo.V03.Offices[0]");
System.out.println(table.getItem(spec).toJSON());
```

La sortie de l’exemple précédent se présente comme suit.

```
All vendor info:
{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]},"V02":{"Name":"New Publishers, Inc.","Offices":["London","New York"]},"V01":{"Name":"Acme Books","Offices":["Seattle"]}}}
A single vendor:
{"VendorInfo":{"V03":{"Name":"Better Buy Books","Offices":["Tokyo","Los Angeles","Sydney"]}}}
First office location for a single vendor:
{"VendorInfo":{"V03":{"Offices":["Tokyo"]}}}
```

**Note**  
La méthode `toJSON` vous permet de convertir tout élément (ou ses attributs) en une chaîne au format JSON. L’extrait de code suivant récupère plusieurs attributs de niveau supérieur et imbriqués et imprime les résultats au format JSON.  

```
GetItemSpec spec = new GetItemSpec()
    .withPrimaryKey("Id", 210)
    .withProjectionExpression("VendorInfo.V01, Title, Price");

Item item = table.getItem(spec);
System.out.println(item.toJSON());
```
Le résultat se présente comme suit.  

```
{"VendorInfo":{"V01":{"Name":"Acme Books","Offices":["Seattle"]}},"Price":30,"Title":"Book 210 Title"}
```

## Écriture par lots : insertion et suppression de plusieurs éléments
<a name="BatchWriteDocumentAPIJava"></a>

L’*écriture par lots* désigne l’insertion et la suppression de plusieurs éléments dans un lot. La méthode `batchWriteItem` vous permet d’insérer et de supprimer plusieurs éléments d’une ou de plusieurs tables en un seul appel. Voici les étapes à suivre pour placer ou supprimer plusieurs éléments à 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 `TableWriteItems` qui décrit toutes les opérations d’insertion et de suppression pour une table. Si vous souhaitez écrire sur plusieurs tables en une opération unique d’écriture par lots, vous devez créer une instance `TableWriteItems` par table.

1. Appelez la méthode `batchWriteItem` en fournissant les objets `TableWriteItems` que vous avez créés à l’étape précédente. 

1. Traitez la réponse. Vous devez vérifier si des éléments de requêtes non traités ont été renvoyés dans la réponse. Cela peut se produire si vous atteignez le quota de débit alloué ou en cas d’autre erreur temporaire. En outre, DynamoDB limite la taille de demande et le nombre d’opérations que vous pouvez spécifier dans une demande. Si vous dépassez ces limites, DynamoDB rejette la demande. Pour de plus amples informations, veuillez consulter [Quotas dans Amazon DynamoDB](ServiceQuotas.md). 

L’exemple de code Java suivant illustre les tâches précédentes. L’exemple effectue une opération `batchWriteItem` sur deux tables : `Forum` et `Thread`. Les objets `TableWriteItems` correspondants permettent de définir les actions suivantes :
+ Insérer un élément dans la table `Forum`
+ Insérer et supprimer un élément de la table `Thread`

Le code appelle ensuite `batchWriteItem` pour effectuer l’opération.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

TableWriteItems forumTableWriteItems = new TableWriteItems("Forum")
    .withItemsToPut(
        new Item()
            .withPrimaryKey("Name", "Amazon RDS")
            .withNumber("Threads", 0));

TableWriteItems threadTableWriteItems = new TableWriteItems("Thread")
    .withItemsToPut(
        new Item()
            .withPrimaryKey("ForumName","Amazon RDS","Subject","Amazon RDS Thread 1")
    .withHashAndRangeKeysToDelete("ForumName","Some partition key value", "Amazon S3", "Some sort key value");

BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems);

// Code for checking unprocessed items is omitted in this example
```

Pour obtenir un exemple pratique, consultez [Exemple : opération d'écriture par lots à l'aide de l'API du AWS SDK pour Java document](batch-operation-document-api-java.md#JavaDocumentAPIBatchWrite). 

## Obtention par lots : obtention de plusieurs éléments
<a name="JavaDocumentAPIBatchGetItem"></a>

La méthode `batchGetItem` vous permet de récupérer plusieurs éléments d’une ou de plusieurs tables. Pour récupérer un seul élément, vous pouvez utiliser la méthode `getItem`. 

Procédez comme suit : 

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

1. Créez une instance de la classe `TableKeysAndAttributes` qui décrit une liste de valeurs de clé primaire à récupérer dans une table. Si vous souhaitez lire depuis plusieurs tables dans une opération unique d’obtention par lots, vous devez créer une instance `TableKeysAndAttributes` par table.

1. Appelez la méthode `batchGetItem` en fournissant les objets `TableKeysAndAttributes` que vous avez créés à l’étape précédente.

L’exemple de code Java suivant illustre les tâches précédentes. L’exemple récupère deux éléments dans la table `Forum` et trois éléments dans la table `Thread`.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

    TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName);
    forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
    "Amazon S3",
    "Amazon DynamoDB");

TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName);
threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject",
    "Amazon DynamoDB","DynamoDB Thread 1",
    "Amazon DynamoDB","DynamoDB Thread 2",
    "Amazon S3","S3 Thread 1");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(
    forumTableKeysAndAttributes, threadTableKeysAndAttributes);

for (String tableName : outcome.getTableItems().keySet()) {
    System.out.println("Items in table " + tableName);
    List<Item> items = outcome.getTableItems().get(tableName);
    for (Item item : items) {
        System.out.println(item);
    }
}
```

### Spécification de paramètres facultatifs
<a name="BatchGetItemJavaDocumentAPIOptions"></a>

Outre les paramètres obligatoires, vous pouvez également spécifier des paramètres facultatifs lorsque vous utilisez `batchGetItem`. Par exemple, vous pouvez fournir une `ProjectionExpression` avec chaque `TableKeysAndAttributes` que vous définissez. Cela vous permet de spécifier les attributs que vous souhaitez récupérer à partir de la table.

L’exemple de code suivant extrait trois éléments de la table `Forum`. Le paramètre `withProjectionExpression` spécifie que seul l’attribut `Threads` doit être récupéré.

**Example**  

```
TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes("Forum")
    .withProjectionExpression("Threads");

forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name",
    "Amazon S3",
    "Amazon DynamoDB");

BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes);
```

## Mise à jour d’un élément
<a name="JavaDocumentAPIItemUpdate"></a>

La méthode `updateItem` d’un objet `Table` peut mettre à jour les valeurs d’attribut existantes, ajouter de nouveaux attributs ou supprimer des attributs d’un élément existant. 

La méthode `updateItem` se comporte comme suit :
+ Si un élément n’existe pas (aucun élément dans la table avec la clé primaire spécifiée), `updateItem` ajoute un nouvel élément à la table
+ Si un élément existe, `updateItem` effectue la mise à jour comme indiqué par le paramètre `UpdateExpression`.

**Note**  
Il est également possible de « mettre à jour » un élément à l’aide de `putItem`. Par exemple, si vous appelez `putItem` pour ajouter un élément à la table, mais qu’il y a déjà un élément avec la clé primaire spécifiée, `putItem` remplace l’élément entier. S’il y a des attributs dans l’élément existant non spécifiés dans l’entrée, `putItem` supprime ces attributs de l’élément.  
En général, nous vous recommandons d’utiliser `updateItem` chaque fois que vous souhaitez modifier des attributs d’élément. La méthode `updateItem` modifie uniquement les attributs d’élément que vous spécifiez dans l’entrée et les autres attributs de l’élément demeurent inchangés.

Procédez comme suit : 

1. Créez une instance de la classe `Table` pour représenter la table que vous souhaitez utiliser.

1. Appelez la méthode `updateTable` de l’instance `Table`. Vous devez spécifier la clé primaire de l’élément que vous souhaitez récupérer, avec une `UpdateExpression` qui décrit les attributs à modifier et comment les modifier.

L’exemple de code Java suivant présente les tâches précédentes. Le code met à jour un élément livre de la table `ProductCatalog`. Il ajoute un nouvel auteur à l’ensemble `Authors` et supprime l’attribut `ISBN` existant. Il permet également de réduire le prix d’une unité.

Un mappage `ExpressionAttributeValues` est utilisé dans l’`UpdateExpression`. Les espaces réservés `:val1` et `:val2` sont remplacés lors de l’exécution par les valeurs réelles pour `Authors` et `Price`.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

Map<String, String> expressionAttributeNames = new HashMap<String, String>();
expressionAttributeNames.put("#A", "Authors");
expressionAttributeNames.put("#P", "Price");
expressionAttributeNames.put("#I", "ISBN");

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1",
    new HashSet<String>(Arrays.asList("Author YY","Author ZZ")));
expressionAttributeValues.put(":val2", 1);   //Price

UpdateItemOutcome outcome =  table.updateItem(
    "Id",          // key attribute name
    101,           // key attribute value
    "add #A :val1 set #P = #P - :val2 remove #I", // UpdateExpression
    expressionAttributeNames,
    expressionAttributeValues);
```

### Spécification de paramètres facultatifs
<a name="UpdateItemJavaDocumentAPIOptions"></a>

Outre les paramètres obligatoires, vous pouvez également spécifier des paramètres facultatifs pour la méthode `updateItem`, y compris une condition à remplir afin que la mise à jour puisse se produire. Si la condition que vous spécifiez n'est pas remplie, AWS SDK pour Java renvoie un`ConditionalCheckFailedException`. Par exemple, l’extrait de code Java suivant redéfinit de façon conditionnelle le prix d’un élément livre sur la valeur 25. Il spécifie une `ConditionExpression` indiquant que le prix doit être mis à jour seulement s’il est de 20.

**Example**  

```
Table table = dynamoDB.getTable("ProductCatalog");

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

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>();
expressionAttributeValues.put(":val1", 25);  // update Price to 25...
expressionAttributeValues.put(":val2", 20);  //...but only if existing Price is 20

UpdateItemOutcome outcome = table.updateItem(
    new PrimaryKey("Id",101),
    "set #P = :val1", // UpdateExpression
    "#P = :val2",     // ConditionExpression
    expressionAttributeNames,
    expressionAttributeValues);
```

### Compteurs atomiques
<a name="AtomicCounterJavaDocumentAPI"></a>

`updateItem` vous permet d’implémenter un compteur atomique, où vous incrémentez ou décrémentez la valeur d’un attribut existant sans interférer avec d’autres demandes d’écriture. Pour incrémenter un compteur atomique, ajoutez une valeur numérique à un attribut existant de type `Number` à l’aide d’une `UpdateExpression` avec une action `set`.

L’extrait de code suivant illustre cette action, en incrémentant l’attribut `Quantity` d’une unité. Il montre également comment utiliser le paramètre `ExpressionAttributeNames` dans une `UpdateExpression`.

```
Table table = dynamoDB.getTable("ProductCatalog");

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

Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
expressionAttributeValues.put(":val", 1);

UpdateItemOutcome outcome = table.updateItem(
    "Id", 121,
    "set #p = #p + :val",
    expressionAttributeNames,
    expressionAttributeValues);
```

## Suppression d’un élément
<a name="DeleteMidLevelJava"></a>

La méthode `deleteItem` supprime un élément d’une table. Vous devez fournir la clé primaire de l’élément que vous souhaitez supprimer.

Procédez comme suit : 

1. Créez une instance du client `DynamoDB`.

1. Appelez la méthode `deleteItem` en fournissant la clé de l’élément que vous souhaitez supprimer. 

L’extrait de code Java suivant illustre ces tâches.

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("ProductCatalog");

DeleteItemOutcome outcome = table.deleteItem("Id", 101);
```

### Spécification de paramètres facultatifs
<a name="DeleteItemJavaDocumentAPIOptions"></a>

Vous pouvez spécifier des paramètres facultatifs pour `deleteItem`. Par exemple, l’extrait de code Java suivant comprend une `ConditionExpression`, indiquant qu’un élément livre dans `ProductCatalog` peut être supprimé seulement si le livre n’est plus en publication. (L’attribut `InPublication` est false.)

**Example**  

```
Map<String,Object> expressionAttributeValues = new HashMap<String,Object>();
expressionAttributeValues.put(":val", false);

DeleteItemOutcome outcome = table.deleteItem("Id",103,
    "InPublication = :val",
    null, // ExpressionAttributeNames - not used in this example
    expressionAttributeValues);
```

# Exemple : opérations CRUD à l'aide de l'API du AWS SDK pour Java document
<a name="JavaDocumentAPICRUDExample"></a>

L’exemple de code suivant illustre des opérations CRUD sur un élément Amazon DynamoDB. L’exemple crée un élément, le récupère, exécute plusieurs mises à jour et supprime finalement l’élément.

**Note**  
Le kit SDK pour Java fournit également un modèle de persistance des objets qui vous permet de mapper vos classes côté client à des tables DynamoDB. Cette approche peut réduire la quantité de code que vous avez à écrire. Pour de plus amples informations, veuillez consulter [Java 1.x : Dynamo DBMapper](DynamoDBMapper.md).

**Note**  
Cet exemple de code part du principe que vous avez déjà chargé des données dans DynamoDB pour votre compte en suivant les instructions de la section [Création de tables et chargement de données pour des exemples de code dans DynamoDB](SampleData.md).  
Pour step-by-step obtenir des instructions sur l'exécution de l'exemple suivant, reportez-vous à[Exemples de code Java](CodeSamples.Java.md).

```
package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DeleteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.UpdateItemOutcome;
import com.amazonaws.services.dynamodbv2.document.spec.DeleteItemSpec;
import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec;
import com.amazonaws.services.dynamodbv2.document.utils.NameMap;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.ReturnValue;

public class DocumentAPIItemCRUDExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String tableName = "ProductCatalog";

    public static void main(String[] args) throws IOException {

        createItems();

        retrieveItem();

        // Perform various updates.
        updateMultipleAttributes();
        updateAddNewAttribute();
        updateExistingAttributeConditionally();

        // Delete the item.
        deleteItem();

    }

    private static void createItems() {

        Table table = dynamoDB.getTable(tableName);
        try {

            Item item = new Item().withPrimaryKey("Id", 120).withString("Title", "Book 120 Title")
                    .withString("ISBN", "120-1111111111")
                    .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author12", "Author22")))
                    .withNumber("Price", 20).withString("Dimensions", "8.5x11.0x.75").withNumber("PageCount", 500)
                    .withBoolean("InPublication", false).withString("ProductCategory", "Book");
            table.putItem(item);

            item = new Item().withPrimaryKey("Id", 121).withString("Title", "Book 121 Title")
                    .withString("ISBN", "121-1111111111")
                    .withStringSet("Authors", new HashSet<String>(Arrays.asList("Author21", "Author 22")))
                    .withNumber("Price", 20).withString("Dimensions", "8.5x11.0x.75").withNumber("PageCount", 500)
                    .withBoolean("InPublication", true).withString("ProductCategory", "Book");
            table.putItem(item);

        } catch (Exception e) {
            System.err.println("Create items failed.");
            System.err.println(e.getMessage());

        }
    }

    private static void retrieveItem() {
        Table table = dynamoDB.getTable(tableName);

        try {

            Item item = table.getItem("Id", 120, "Id, ISBN, Title, Authors", null);

            System.out.println("Printing item after retrieving it....");
            System.out.println(item.toJSONPretty());

        } catch (Exception e) {
            System.err.println("GetItem failed.");
            System.err.println(e.getMessage());
        }

    }

    private static void updateAddNewAttribute() {
        Table table = dynamoDB.getTable(tableName);

        try {

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 121)
                    .withUpdateExpression("set #na = :val1").withNameMap(new NameMap().with("#na", "NewAttribute"))
                    .withValueMap(new ValueMap().withString(":val1", "Some value"))
                    .withReturnValues(ReturnValue.ALL_NEW);

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after adding new attribute...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Failed to add new attribute in " + tableName);
            System.err.println(e.getMessage());
        }
    }

    private static void updateMultipleAttributes() {

        Table table = dynamoDB.getTable(tableName);

        try {

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)
                    .withUpdateExpression("add #a :val1 set #na=:val2")
                    .withNameMap(new NameMap().with("#a", "Authors").with("#na", "NewAttribute"))
                    .withValueMap(
                            new ValueMap().withStringSet(":val1", "Author YY", "Author ZZ").withString(":val2",
                                    "someValue"))
                    .withReturnValues(ReturnValue.ALL_NEW);

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after multiple attribute update...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Failed to update multiple attributes in " + tableName);
            System.err.println(e.getMessage());

        }
    }

    private static void updateExistingAttributeConditionally() {

        Table table = dynamoDB.getTable(tableName);

        try {

            // Specify the desired price (25.00) and also the condition (price =
            // 20.00)

            UpdateItemSpec updateItemSpec = new UpdateItemSpec().withPrimaryKey("Id", 120)
                    .withReturnValues(ReturnValue.ALL_NEW).withUpdateExpression("set #p = :val1")
                    .withConditionExpression("#p = :val2").withNameMap(new NameMap().with("#p", "Price"))
                    .withValueMap(new ValueMap().withNumber(":val1", 25).withNumber(":val2", 20));

            UpdateItemOutcome outcome = table.updateItem(updateItemSpec);

            // Check the response.
            System.out.println("Printing item after conditional update to new attribute...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Error updating item in " + tableName);
            System.err.println(e.getMessage());
        }
    }

    private static void deleteItem() {

        Table table = dynamoDB.getTable(tableName);

        try {

            DeleteItemSpec deleteItemSpec = new DeleteItemSpec().withPrimaryKey("Id", 120)
                    .withConditionExpression("#ip = :val").withNameMap(new NameMap().with("#ip", "InPublication"))
                    .withValueMap(new ValueMap().withBoolean(":val", false)).withReturnValues(ReturnValue.ALL_OLD);

            DeleteItemOutcome outcome = table.deleteItem(deleteItemSpec);

            // Check the response.
            System.out.println("Printing item that was deleted...");
            System.out.println(outcome.getItem().toJSONPretty());

        } catch (Exception e) {
            System.err.println("Error deleting item in " + tableName);
            System.err.println(e.getMessage());
        }
    }
}
```

# Exemple : opérations par lots à l'aide de l'API AWS SDK pour Java du document
<a name="batch-operation-document-api-java"></a>

Cette section fournit des exemples d'opérations d'écriture et d'obtention par lots dans Amazon DynamoDB à l'aide AWS SDK pour Java de l'API Document.

**Note**  
Le kit SDK pour Java fournit également un modèle de persistance des objets qui vous permet de mapper vos classes côté client à des tables DynamoDB. Cette approche peut réduire la quantité de code que vous avez à écrire. Pour de plus amples informations, veuillez consulter [Java 1.x : Dynamo DBMapper](DynamoDBMapper.md).

**Topics**
+ [Exemple : opération d'écriture par lots à l'aide de l'API du AWS SDK pour Java document](#JavaDocumentAPIBatchWrite)
+ [Exemple : opération d'obtention par lots à l'aide de l'API du AWS SDK pour Java document](#JavaDocumentAPIBatchGet)

## Exemple : opération d'écriture par lots à l'aide de l'API du AWS SDK pour Java document
<a name="JavaDocumentAPIBatchWrite"></a>

L’exemple de code Java suivant exécute les opérations « put » et « delete » suivantes à l’aide de la méthode `batchWriteItem` :
+ Insère un élément dans la table `Forum`.
+ Insère un élément et supprime un élément de la table `Thread`. 

Vous pouvez spécifier tout nombre de demandes put et delete sur une ou plusieurs tables lors de la création de votre demande d’écriture par lots. Cependant, `batchWriteItem` limite la taille d’une demande d’écriture par lots et le nombre d’opérations « put » et « delete » d’une même opération d’écriture par lots. Si votre demande dépasse ces limites, elle est rejetée. Si votre table n’a pas suffisamment de débit alloué pour traiter cette demande, les éléments non traités de la demande sont renvoyés dans la réponse. 

L’exemple suivant vérifie la réponse pour voir si elle comporte des éléments de demande non traités. Si tel est le cas, une boucle est parcourue et la demande `batchWriteItem` est renvoyée avec les articles non traités de la demande. Si vous avez suivi les exemples de ce guide, vous devez déjà avoir créé les tables `Forum` et `Thread`. Vous pouvez également créer ces tables et charger des exemples de données par programmation. Pour de plus amples informations, veuillez consulter [Création de tableaux d'exemple et téléchargement de données à l'aide du AWS SDK pour Java](AppendixSampleDataCodeJava.md).

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.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchWriteItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableWriteItems;
import com.amazonaws.services.dynamodbv2.model.WriteRequest;

public class DocumentAPIBatchWrite {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String forumTableName = "Forum";
    static String threadTableName = "Thread";

    public static void main(String[] args) throws IOException {

        writeMultipleItemsBatchWrite();

    }

    private static void writeMultipleItemsBatchWrite() {
        try {

            // Add a new item to Forum
            TableWriteItems forumTableWriteItems = new TableWriteItems(forumTableName) // Forum
                    .withItemsToPut(new Item().withPrimaryKey("Name", "Amazon RDS").withNumber("Threads", 0));

            // Add a new item, and delete an existing item, from Thread
            // This table has a partition key and range key, so need to specify
            // both of them
            TableWriteItems threadTableWriteItems = new TableWriteItems(threadTableName)
                    .withItemsToPut(
                            new Item().withPrimaryKey("ForumName", "Amazon RDS", "Subject", "Amazon RDS Thread 1")
                                    .withString("Message", "ElastiCache Thread 1 message")
                                    .withStringSet("Tags", new HashSet<String>(Arrays.asList("cache", "in-memory"))))
                    .withHashAndRangeKeysToDelete("ForumName", "Subject", "Amazon S3", "S3 Thread 100");

            System.out.println("Making the request.");
            BatchWriteItemOutcome outcome = dynamoDB.batchWriteItem(forumTableWriteItems, threadTableWriteItems);

            do {

                // Check for unprocessed keys which could happen if you exceed
                // provisioned throughput

                Map<String, List<WriteRequest>> unprocessedItems = outcome.getUnprocessedItems();

                if (outcome.getUnprocessedItems().size() == 0) {
                    System.out.println("No unprocessed items found");
                } else {
                    System.out.println("Retrieving the unprocessed items");
                    outcome = dynamoDB.batchWriteItemUnprocessed(unprocessedItems);
                }

            } while (outcome.getUnprocessedItems().size() > 0);

        } catch (Exception e) {
            System.err.println("Failed to retrieve items: ");
            e.printStackTrace(System.err);
        }

    }

}
```

## Exemple : opération d'obtention par lots à l'aide de l'API du AWS SDK pour Java document
<a name="JavaDocumentAPIBatchGet"></a>

L’exemple de code Java suivant récupère plusieurs éléments des tables `Forum` et `Thread` à l’aide de la méthode `batchGetItem`. La demande `BatchGetItemRequest` spécifie les noms de table et une liste des clés pour chaque élément à obtenir. L’exemple traite la réponse en imprimant les éléments récupérés.

**Note**  
Cet exemple de code part du principe que vous avez déjà chargé des données dans DynamoDB pour votre compte en suivant les instructions de la section [Création de tables et chargement de données pour des exemples de code dans DynamoDB](SampleData.md).  
Pour step-by-step obtenir des instructions sur l'exécution de l'exemple suivant, reportez-vous à[Exemples de code Java](CodeSamples.Java.md).

**Example**  

```
package com.amazonaws.codesamples.document;

import java.io.IOException;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.BatchGetItemOutcome;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.TableKeysAndAttributes;
import com.amazonaws.services.dynamodbv2.model.KeysAndAttributes;

public class DocumentAPIBatchGet {
    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String forumTableName = "Forum";
    static String threadTableName = "Thread";

    public static void main(String[] args) throws IOException {
        retrieveMultipleItemsBatchGet();
    }

    private static void retrieveMultipleItemsBatchGet() {

        try {

            TableKeysAndAttributes forumTableKeysAndAttributes = new TableKeysAndAttributes(forumTableName);
            // Add a partition key
            forumTableKeysAndAttributes.addHashOnlyPrimaryKeys("Name", "Amazon S3", "Amazon DynamoDB");

            TableKeysAndAttributes threadTableKeysAndAttributes = new TableKeysAndAttributes(threadTableName);
            // Add a partition key and a sort key
            threadTableKeysAndAttributes.addHashAndRangePrimaryKeys("ForumName", "Subject", "Amazon DynamoDB",
                    "DynamoDB Thread 1", "Amazon DynamoDB", "DynamoDB Thread 2", "Amazon S3", "S3 Thread 1");

            System.out.println("Making the request.");

            BatchGetItemOutcome outcome = dynamoDB.batchGetItem(forumTableKeysAndAttributes,
                    threadTableKeysAndAttributes);

            Map<String, KeysAndAttributes> unprocessed = null;

            do {
                for (String tableName : outcome.getTableItems().keySet()) {
                    System.out.println("Items in table " + tableName);
                    List<Item> items = outcome.getTableItems().get(tableName);
                    for (Item item : items) {
                        System.out.println(item.toJSONPretty());
                    }
                }

                // Check for unprocessed keys which could happen if you exceed
                // provisioned
                // throughput or reach the limit on response size.
                unprocessed = outcome.getUnprocessedKeys();

                if (unprocessed.isEmpty()) {
                    System.out.println("No unprocessed keys found");
                } else {
                    System.out.println("Retrieving the unprocessed keys");
                    outcome = dynamoDB.batchGetItemUnprocessed(unprocessed);
                }

            } while (!unprocessed.isEmpty());

        } catch (Exception e) {
            System.err.println("Failed to retrieve items.");
            System.err.println(e.getMessage());
        }

    }

}
```

# Exemple : gestion des attributs de type binaire à l'aide de l'API du AWS SDK pour Java document
<a name="JavaDocumentAPIBinaryTypeExample"></a>

L’exemple de code Java suivant illustre la gestion des attributs de type binaire. L’exemple ajoute un élément à la table `Reply`. L’élément inclut un attribut de type binaire (`ExtendedMessage`) qui stocke les données compressées. Ensuite, l’exemple récupère l’élément et imprime toutes les valeurs d’attribut. À titre d’illustration, l’exemple compresse un exemple de flux et l’affecte à l’attribut `ExtendedMessage` à l’aide de la classe `GZIPOutputStream`. Lorsque le binary attribute est récupéré, il est décompressé à l’aide de la classe `GZIPInputStream`. 

**Note**  
Le kit SDK pour Java fournit également un modèle de persistance des objets qui vous permet de mapper vos classes côté client à des tables DynamoDB. Cette approche peut réduire la quantité de code que vous avez à écrire. Pour de plus amples informations, veuillez consulter [Java 1.x : Dynamo DBMapper](DynamoDBMapper.md).

Si vous avez suivi la section [Création de tables et chargement de données pour des exemples de code dans DynamoDB](SampleData.md), vous devez déjà avoir créé la table `Reply`. Vous pouvez également créer cette table par programmation. Pour de plus amples informations, veuillez consulter [Création de tableaux d'exemple et téléchargement de données à l'aide du AWS SDK pour Java](AppendixSampleDataCodeJava.md).

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.amazonaws.codesamples.document;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.GetItemSpec;

public class DocumentAPIItemBinaryExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    static String tableName = "Reply";
    static SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

    public static void main(String[] args) throws IOException {
        try {

            // Format the primary key values
            String threadId = "Amazon DynamoDB#DynamoDB Thread 2";

            dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
            String replyDateTime = dateFormatter.format(new Date());

            // Add a new reply with a binary attribute type
            createItem(threadId, replyDateTime);

            // Retrieve the reply with a binary attribute type
            retrieveItem(threadId, replyDateTime);

            // clean up by deleting the item
            deleteItem(threadId, replyDateTime);
        } catch (Exception e) {
            System.err.println("Error running the binary attribute type example: " + e);
            e.printStackTrace(System.err);
        }
    }

    public static void createItem(String threadId, String replyDateTime) throws IOException {

        Table table = dynamoDB.getTable(tableName);

        // Craft a long message
        String messageInput = "Long message to be compressed in a lengthy forum reply";

        // Compress the long message
        ByteBuffer compressedMessage = compressString(messageInput.toString());

        table.putItem(new Item().withPrimaryKey("Id", threadId).withString("ReplyDateTime", replyDateTime)
                .withString("Message", "Long message follows").withBinary("ExtendedMessage", compressedMessage)
                .withString("PostedBy", "User A"));
    }

    public static void retrieveItem(String threadId, String replyDateTime) throws IOException {

        Table table = dynamoDB.getTable(tableName);

        GetItemSpec spec = new GetItemSpec().withPrimaryKey("Id", threadId, "ReplyDateTime", replyDateTime)
                .withConsistentRead(true);

        Item item = table.getItem(spec);

        // Uncompress the reply message and print
        String uncompressed = uncompressString(ByteBuffer.wrap(item.getBinary("ExtendedMessage")));

        System.out.println("Reply message:\n" + " Id: " + item.getString("Id") + "\n" + " ReplyDateTime: "
                + item.getString("ReplyDateTime") + "\n" + " PostedBy: " + item.getString("PostedBy") + "\n"
                + " Message: "
                + item.getString("Message") + "\n" + " ExtendedMessage (uncompressed): " + uncompressed + "\n");
    }

    public static void deleteItem(String threadId, String replyDateTime) {

        Table table = dynamoDB.getTable(tableName);
        table.deleteItem("Id", threadId, "ReplyDateTime", replyDateTime);
    }

    private static ByteBuffer compressString(String input) throws IOException {
        // Compress the UTF-8 encoded String into a byte[]
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream os = new GZIPOutputStream(baos);
        os.write(input.getBytes("UTF-8"));
        os.close();
        baos.close();
        byte[] compressedBytes = baos.toByteArray();

        // The following code writes the compressed bytes to a ByteBuffer.
        // A simpler way to do this is by simply calling
        // ByteBuffer.wrap(compressedBytes);
        // However, the longer form below shows the importance of resetting the
        // position of the buffer
        // back to the beginning of the buffer if you are writing bytes directly
        // to it, since the SDK
        // will consider only the bytes after the current position when sending
        // data to DynamoDB.
        // Using the "wrap" method automatically resets the position to zero.
        ByteBuffer buffer = ByteBuffer.allocate(compressedBytes.length);
        buffer.put(compressedBytes, 0, compressedBytes.length);
        buffer.position(0); // Important: reset the position of the ByteBuffer
                            // to the beginning
        return buffer;
    }

    private static String uncompressString(ByteBuffer input) throws IOException {
        byte[] bytes = input.array();
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPInputStream is = new GZIPInputStream(bais);

        int chunkSize = 1024;
        byte[] buffer = new byte[chunkSize];
        int length = 0;
        while ((length = is.read(buffer, 0, chunkSize)) != -1) {
            baos.write(buffer, 0, length);
        }

        String result = new String(baos.toByteArray(), "UTF-8");

        is.close();
        baos.close();
        bais.close();

        return result;
    }
}
```

# Utilisation des élements : .NET
<a name="LowLevelDotNetItemCRUD"></a>

Vous pouvez utiliser l'API de AWS SDK pour .NET bas niveau pour effectuer des opérations classiques de création, de lecture, de mise à jour et de suppression (CRUD) sur un élément d'une table. Voici les étapes courantes à suivre pour effectuer des opérations CRUD sur des données à l’aide de l’API de bas niveau .NET :

1. Créez une instance de la classe `AmazonDynamoDBClient` (le client).

1. Fournissez les paramètres obligatoires spécifiques à l’opération dans un objet de demande correspondant.

   Par exemple, utilisez l’objet de demande `PutItemRequest` lors du chargement d’un élément, et l’objet de demande `GetItemRequest` lors de l’extraction d’un élément existant. 

   L’objet de demande vous permet de fournir les paramètres obligatoires et facultatifs. 

1. Exécutez la méthode appropriée fournie par le client en transmettant l’objet de demande que vous avez créé à l’étape précédente. 

   Le client `AmazonDynamoDBClient` fournit les méthodes `PutItem`, `GetItem`, `UpdateItem`, et `DeleteItem` pour les opérations CRUD.

**Topics**
+ [Insertion d’un élément](#PutItemLowLevelAPIDotNet)
+ [Obtention d’un élément](#GetItemLowLevelDotNET)
+ [Mise à jour d’un élément](#UpdateItemLowLevelDotNet)
+ [Compteurs atomiques](#AtomicCounterLowLevelDotNet)
+ [Suppression d’un élément](#DeleteMidLevelDotNet)
+ [Écriture par lots : insertion et suppression de plusieurs éléments](#BatchWriteLowLevelDotNet)
+ [Obtention par lots : obtention de plusieurs éléments](#BatchGetLowLevelDotNet)
+ [Exemple : opérations CRUD à l'aide de l'API de AWS SDK pour .NET bas niveau](LowLevelDotNetItemsExample.md)
+ [Exemple : opérations par lots à l'aide de l'API de AWS SDK pour .NET bas niveau](batch-operation-lowlevel-dotnet.md)
+ [Exemple : gestion des attributs de type binaire à l'aide de l'API de AWS SDK pour .NET bas niveau](LowLevelDotNetBinaryTypeExample.md)

## Insertion d’un élément
<a name="PutItemLowLevelAPIDotNet"></a>

La méthode `PutItem` charge un élément dans une table. Si l’élément existe, il remplace la totalité de l’élément.

**Note**  
Au lieu de remplacer l’élément entier, vous pouvez mettre à jour uniquement des attributs spécifiques à l’aide de la méthode `UpdateItem`. Pour de plus amples informations, veuillez consulter [Mise à jour d’un élément](#UpdateItemLowLevelDotNet).

Pour charger un élément à l’aide de l’API SDK .NET de bas niveau, procédez comme suit :

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

1. Fournissez les paramètres obligatoires en créant une instance de la classe `PutItemRequest`.

   Pour insérer un élément, vous devez fournir le nom de la table et l’élément. 

1. Appelez la méthode `PutItem` en fournissant l’objet `PutItemRequest` que vous avez créé à l’étape précédente.

L’exemple de code C\$1 suivant illustre les étapes précédentes. L’exemple charge un élément dans la table `ProductCatalog`.

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new PutItemRequest
{
   TableName = tableName,
   Item = new Dictionary<string, AttributeValue>()
      {
          { "Id", new AttributeValue { N = "201" }},
          { "Title", new AttributeValue { S = "Book 201 Title" }},
          { "ISBN", new AttributeValue { S = "11-11-11-11" }},
          { "Price", new AttributeValue { S = "20.00" }},
          {
            "Authors",
            new AttributeValue
            { SS = new List<string>{"Author1", "Author2"}   }
          }
      }
};
client.PutItem(request);
```

Dans l’exemple précédent, vous chargez un élément book (livre) qui possède les attributs `Id`, `Title`, `ISBN` et `Authors`. Notez que `Id` est un attribut de type numérique et que tous les autres attributs sont de type String (chaîne). Authors est un ensemble `String`.

### Spécification de paramètres facultatifs
<a name="PutItemLowLevelAPIDotNetOptions"></a>

Vous pouvez également fournir des paramètres facultatifs à l’aide de l’objet `PutItemRequest`, comme illustré dans l’exemple C\$1 suivant. L’exemple spécifie les paramètres facultatifs suivants :
+ `ExpressionAttributeNames`, `ExpressionAttributeValues` et `ConditionExpression` spécifient que l’élément peut être remplacé seulement si l’élément existant possède l’attribut ISBN avec une valeur spécifique.
+ Paramètre `ReturnValues` pour demander l’ancien élément dans la réponse.

**Example**  

```
var request = new PutItemRequest
 {
   TableName = tableName,
   Item = new Dictionary<string, AttributeValue>()
               {
                   { "Id", new AttributeValue { N = "104" }},
                   { "Title", new AttributeValue { S = "Book 104  Title" }},
                   { "ISBN", new AttributeValue { S = "444-4444444444" }},
                   { "Authors",
                     new AttributeValue { SS = new List<string>{"Author3"}}}
               },
    // Optional parameters.
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#I", "ISBN"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":isbn",new AttributeValue {S = "444-4444444444"}}
    },
    ConditionExpression = "#I = :isbn"

};
var response = client.PutItem(request);
```

Pour de plus amples informations, veuillez consulter [PutItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutItem.html).

## Obtention d’un élément
<a name="GetItemLowLevelDotNET"></a>

La méthode `GetItem` extrait un élément.

**Note**  
Vous pouvez extraire plusieurs éléments à l’aide de la méthode `BatchGetItem`. Pour de plus amples informations, veuillez consulter [Obtention par lots : obtention de plusieurs éléments](#BatchGetLowLevelDotNet).

Pour extraire un élément à l’aide de l’API AWS SDK pour .NET de bas niveau, procédez comme suit :

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

1. Fournissez les paramètres obligatoires en créant une instance de la classe `GetItemRequest`.

   Pour obtenir un élément, vous devez fournir le nom de la table et la clé primaire de l’élément. 

1. Appelez la méthode `GetItem` en fournissant l’objet `GetItemRequest` que vous avez créé à l’étape précédente.

L’exemple de code C\$1 suivant illustre les étapes précédentes. L’exemple extrait un élément de la table `ProductCatalog`.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new GetItemRequest
 {
   TableName = tableName,
   Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
 };
 var response = client.GetItem(request);

// Check the response.
var result = response.GetItemResult;
var attributeMap = result.Item; // Attribute list in the response.
```

### Spécification de paramètres facultatifs
<a name="GetItemLowLevelDotNETOptions"></a>

Vous pouvez également fournir des paramètres facultatifs à l’aide de l’objet `GetItemRequest`, comme illustré dans l’exemple C\$1 suivant. L’exemple spécifie les paramètres facultatifs suivants :
+ Paramètre `ProjectionExpression` pour spécifier les attributs à extraire.
+ Paramètre `ConsistentRead` pour effectuer une lecture fortement cohérente. Pour en savoir plus sur la cohérence de lecture, consultez [Cohérence en lecture DynamoDB](HowItWorks.ReadConsistency.md).

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new GetItemRequest
 {
   TableName = tableName,
   Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
   // Optional parameters.
   ProjectionExpression = "Id, ISBN, Title, Authors",
   ConsistentRead = true
 };

 var response = client.GetItem(request);

// Check the response.
var result = response.GetItemResult;
var attributeMap = result.Item;
```

Pour de plus amples informations, veuillez consulter [GetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_GetItem.html).

## Mise à jour d’un élément
<a name="UpdateItemLowLevelDotNet"></a>

La méthode `UpdateItem` met à jour un élément existant s’il est présent. L’opération `UpdateItem` vous permet de mettre à jour des valeurs d’attribut existantes, d’ajouter des attributs ou d’en supprimer dans la collection existante. Si l’élément qui possède la clé primaire spécifiée est introuvable, l’opération ajoute un nouvel élément.

L’opération `UpdateItem` suit les directives suivantes :
+ Si l’élément n’existe pas, `UpdateItem` ajoute un nouvel élément à l’aide de la clé primaire spécifiée dans l’entrée.
+ Si l’élément existe, `UpdateItem` applique les mises à jour comme suit :
  + Remplace les valeurs d’attribut existantes par les valeurs figurant dans la mise à jour.
  + Si un attribut que vous fournissez en entrée n’existe pas, l’opération ajoute un nouvel attribut à l’élément.
  + Si l’attribut en entrée a la valeur null, elle supprime l’attribut s’il est présent. 
  + Si vous utilisez `ADD` pour `Action`, vous pouvez ajouter des valeurs à un ensemble existant (ensemble de chaînes ou de nombres), ou bien ajouter (utiliser un nombre positif) ou soustraire (utiliser un nombre négatif) mathématiquement de façon à augmenter ou réduire la valeur de l’attribut numérique existant.

**Note**  
L’opération `PutItem` peut également effectuer une mise à jour. Pour de plus amples informations, veuillez consulter [Insertion d’un élément](#PutItemLowLevelAPIDotNet). Par exemple, si vous appelez `PutItem` pour charger un élément et que la clé primaire existe, l’opération `PutItem` remplace l’élément entier. Si l’élément existant comporte des attributs non spécifiés dans l’entrée, l’opération `PutItem` supprime ces attributs. Toutefois, l’opération `UpdateItem` ne met à jour que les attributs d’entrée spécifiés. Tous les autres attributs de cet élément demeurent inchangés. 

Pour mettre à jour un élément à l’aide de l’API SDK .NET de bas niveau, procédez comme suit :

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

1. Fournissez les paramètres obligatoires en créant une instance de la classe `UpdateItemRequest`.

   Il s’agit de l’objet de demande dans lequel vous décrivez toutes les mises à jour, comme l’ajout, la mise à jour ou la suppression d’attributs. Pour supprimer un attribut, spécifiez son nom avec la valeur null. 

1. Appelez la méthode `UpdateItem` en fournissant l’objet `UpdateItemRequest` que vous avez créé à l’étape précédente. 

L’exemple de code C\$1 suivant illustre les étapes précédentes. L’exemple de code met à jour un élément book (livre) dans la table `ProductCatalog`. Il ajoute un nouvel auteur à la collection `Authors` et supprime l’attribut `ISBN` existant. Il permet également de réduire le prix d’une unité.



```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#A", "Authors"},
        {"#P", "Price"},
        {"#NA", "NewAttribute"},
        {"#I", "ISBN"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":auth",new AttributeValue { SS = {"Author YY","Author ZZ"}}},
        {":p",new AttributeValue {N = "1"}},
        {":newattr",new AttributeValue {S = "someValue"}},
    },

    // This expression does the following:
    // 1) Adds two new authors to the list
    // 2) Reduces the price
    // 3) Adds a new attribute to the item
    // 4) Removes the ISBN attribute from the item
    UpdateExpression = "ADD #A :auth SET #P = #P - :p, #NA = :newattr REMOVE #I"
};
var response = client.UpdateItem(request);
```

### Spécification de paramètres facultatifs
<a name="UpdateItemLowLevelDotNETOptions"></a>

Vous pouvez également fournir des paramètres facultatifs à l’aide de l’objet `UpdateItemRequest`, comme illustré dans l’exemple C\$1 suivant. Il spécifie les deux paramètres facultatifs suivants :
+ `ExpressionAttributeValues` et `ConditionExpression` pour spécifier que le prix peut être mis à jour seulement s’il est de 20,00.
+ Paramètre `ReturnValues` pour demander l’élément mis à jour dans la réponse. 

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "202" } } },

    // Update price only if the current price is 20.00.
    ExpressionAttributeNames = new Dictionary<string,string>()
    {
        {"#P", "Price"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":newprice",new AttributeValue {N = "22"}},
        {":currprice",new AttributeValue {N = "20"}}
    },
    UpdateExpression = "SET #P = :newprice",
    ConditionExpression = "#P = :currprice",
    TableName = tableName,
    ReturnValues = "ALL_NEW" // Return all the attributes of the updated item.
};

var response = client.UpdateItem(request);
```

Pour de plus amples informations, veuillez consulter [UpdateItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html). 

## Compteurs atomiques
<a name="AtomicCounterLowLevelDotNet"></a>

`updateItem` vous permet d’implémenter un compteur atomique, où vous incrémentez ou décrémentez la valeur d’un attribut existant sans interférer avec d’autres demandes d’écriture. Mettez à jour un compteur atomique à l’aide de `updateItem` avec un attribut de type `Number` dans le paramètre `UpdateExpression`, et `ADD` pour `Action`.

L’extrait de code suivant illustre cette action, en incrémentant l’attribut `Quantity` d’une unité.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new UpdateItemRequest
{
    Key = new Dictionary<string, AttributeValue>() { { "Id", new AttributeValue { N = "121" } } },
    ExpressionAttributeNames = new Dictionary<string, string>()
    {
        {"#Q", "Quantity"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":incr",new AttributeValue {N = "1"}}
    },
    UpdateExpression = "SET #Q = #Q + :incr",
    TableName = tableName
};

var response = client.UpdateItem(request);
```

## Suppression d’un élément
<a name="DeleteMidLevelDotNet"></a>

La méthode `DeleteItem` supprime un élément d’une table. 

Pour supprimer un élément à l’aide de l’API SDK .NET de bas niveau, procédez comme suit : 

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

1. Fournissez les paramètres obligatoires en créant une instance de la classe `DeleteItemRequest`.

    Pour supprimer un élément, le nom de la table et la clé primaire de l’élément sont requis. 

1. Appelez la méthode `DeleteItem` en fournissant l’objet `DeleteItemRequest` que vous avez créé à l’étape précédente. 

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();
string tableName = "ProductCatalog";

var request = new DeleteItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } },
};

var response = client.DeleteItem(request);
```

### Spécification de paramètres facultatifs
<a name="DeleteItemLowLevelDotNETOptions"></a>

Vous pouvez également fournir des paramètres facultatifs à l’aide de l’objet `DeleteItemRequest`, comme illustré dans l’exemple de code C\$1 suivant. Il spécifie les deux paramètres facultatifs suivants :
+ `ExpressionAttributeValues`et `ConditionExpression` pour spécifier que l'élément du livre ne peut être supprimé que s'il n'est plus en cours de publication (la valeur de InPublication l'attribut est fausse). 
+ Paramètre `ReturnValues` pour demander l’élément supprimé dans la réponse.

**Example**  

```
var request = new DeleteItemRequest
{
    TableName = tableName,
    Key = new Dictionary<string,AttributeValue>() { { "Id", new AttributeValue { N = "201" } } },

    // Optional parameters.
    ReturnValues = "ALL_OLD",
    ExpressionAttributeNames = new Dictionary<string, string>()
    {
        {"#IP", "InPublication"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
    {
        {":inpub",new AttributeValue {BOOL = false}}
    },
    ConditionExpression = "#IP = :inpub"
};

var response = client.DeleteItem(request);
```

Pour de plus amples informations, veuillez consulter [DeleteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_DeleteItem.html).

## Écriture par lots : insertion et suppression de plusieurs éléments
<a name="BatchWriteLowLevelDotNet"></a>

L’*écriture par lots* désigne l’insertion et la suppression de plusieurs éléments dans un lot. La méthode `BatchWriteItem` vous permet d’insérer et de supprimer plusieurs éléments d’une ou de plusieurs tables en un seul appel. Pour extraire plusieurs éléments à l’aide de l’API SDK .NET de bas niveau, procédez comme suit :

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

1. Décrivez toutes les opérations d’insertion et de suppression en créant une instance de la classe `BatchWriteItemRequest`.

1. Appelez la méthode `BatchWriteItem` en fournissant l’objet `BatchWriteItemRequest` que vous avez créé à l’étape précédente.

1. Traitez la réponse. Vous devez vérifier si des éléments de requêtes non traités ont été renvoyés dans la réponse. Cela peut se produire si vous atteignez le quota de débit alloué ou en cas d’autre erreur temporaire. En outre, DynamoDB limite la taille de demande et le nombre d’opérations que vous pouvez spécifier dans une demande. Si vous dépassez ces limites, DynamoDB rejette la demande. Pour de plus amples informations, veuillez consulter [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html). 

L’exemple de code C\$1 suivant illustre les étapes précédentes. L’exemple crée un objet `BatchWriteItemRequest` pour effectuer les opérations d’écriture suivantes :
+ Insérer un élément dans la table `Forum`
+ Insérer et supprimer un élément dans la table `Thread`

Le code exécute `BatchWriteItem` pour effectuer une opération par lots.

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";
string table2Name = "Thread";

var request = new BatchWriteItemRequest
 {
   RequestItems = new Dictionary<string, List<WriteRequest>>
    {
      {
        table1Name, new List<WriteRequest>
        {
          new WriteRequest
          {
             PutRequest = new PutRequest
             {
                Item = new Dictionary<string,AttributeValue>
                {
                  { "Name", new AttributeValue { S = "Amazon S3 forum" } },
                  { "Threads", new AttributeValue { N = "0" }}
                }
             }
          }
        }
      } ,
      {
        table2Name, new List<WriteRequest>
        {
          new WriteRequest
          {
            PutRequest = new PutRequest
            {
               Item = new Dictionary<string,AttributeValue>
               {
                 { "ForumName", new AttributeValue { S = "Amazon S3 forum" } },
                 { "Subject", new AttributeValue { S = "My sample question" } },
                 { "Message", new AttributeValue { S = "Message Text." } },
                 { "KeywordTags", new AttributeValue { SS = new List<string> { "Amazon S3", "Bucket" }  } }
               }
            }
          },
          new WriteRequest
          {
             DeleteRequest = new DeleteRequest
             {
                Key = new Dictionary<string,AttributeValue>()
                {
                   { "ForumName", new AttributeValue { S = "Some forum name" } },
                   { "Subject", new AttributeValue { S = "Some subject" } }
                }
             }
          }
        }
      }
    }
 };
response = client.BatchWriteItem(request);
```

Pour obtenir un exemple pratique, consultez [Exemple : opérations par lots à l'aide de l'API de AWS SDK pour .NET bas niveau](batch-operation-lowlevel-dotnet.md). 

## Obtention par lots : obtention de plusieurs éléments
<a name="BatchGetLowLevelDotNet"></a>

La méthode `BatchGetItem` vous permet de récupérer plusieurs éléments d’une ou de plusieurs tables. 

**Note**  
Pour récupérer un seul élément, vous pouvez utiliser la méthode `GetItem`. 

Pour extraire plusieurs éléments à l’aide de l’API AWS SDK pour .NET de bas niveau, procédez comme suit :

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

1. Fournissez les paramètres obligatoires en créant une instance de la classe `BatchGetItemRequest`.

   Pour extraire plusieurs éléments, le nom de la table et une liste de valeurs de clé primaire sont requis. 

1. Appelez la méthode `BatchGetItem` en fournissant l’objet `BatchGetItemRequest` que vous avez créé à l’étape précédente.

1. Traitez la réponse. Vous devez vérifier s’il existe des clés non traitées, ce qui peut se produire si vous atteignez le quota de débit alloué ou en cas d’autre erreur temporaire.

L’exemple de code C\$1 suivant illustre les étapes précédentes. L’exemple extrait les éléments de deux tables : `Forum` et `Thread`. La demande spécifie deux éléments dans la table `Forum` et trois éléments dans la table `Thread`. La réponse inclut des éléments des deux tables. Le code montre comment vous pouvez traiter la réponse.



```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";
string table2Name = "Thread";

var request = new BatchGetItemRequest
{
  RequestItems = new Dictionary<string, KeysAndAttributes>()
  {
    { table1Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "DynamoDB" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "Amazon S3" } }
          }
        }
      }
    },
    {
      table2Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "DynamoDB" } },
            { "Subject", new AttributeValue { S = "DynamoDB Thread 1" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "DynamoDB" } },
            { "Subject", new AttributeValue { S = "DynamoDB Thread 2" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "ForumName", new AttributeValue { S = "Amazon S3" } },
            { "Subject", new AttributeValue { S = "Amazon S3 Thread 1" } }
          }
        }
      }
    }
  }
};

var response = client.BatchGetItem(request);

// Check the response.
var result = response.BatchGetItemResult;
var responses = result.Responses; // The attribute list in the response.

var table1Results = responses[table1Name];
Console.WriteLine("Items in table {0}" + table1Name);
foreach (var item1 in table1Results.Items)
{
  PrintItem(item1);
}

var table2Results = responses[table2Name];
Console.WriteLine("Items in table {1}" + table2Name);
foreach (var item2 in table2Results.Items)
{
  PrintItem(item2);
}
// Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error.
Dictionary<string, KeysAndAttributes> unprocessedKeys = result.UnprocessedKeys;
foreach (KeyValuePair<string, KeysAndAttributes> pair in unprocessedKeys)
{
    Console.WriteLine(pair.Key, pair.Value);
}
```



### Spécification de paramètres facultatifs
<a name="BatchGetItemLowLevelDotNETOptions"></a>

Vous pouvez également fournir des paramètres facultatifs à l’aide de l’objet `BatchGetItemRequest`, comme illustré dans l’exemple de code C\$1 suivant. L’exemple extrait deux éléments de la table `Forum`. Il spécifie le paramètre facultatif suivant :
+  Paramètre `ProjectionExpression` pour spécifier les attributs à extraire.

**Example**  

```
AmazonDynamoDBClient client = new AmazonDynamoDBClient();

string table1Name = "Forum";

var request = new BatchGetItemRequest
{
  RequestItems = new Dictionary<string, KeysAndAttributes>()
  {
    { table1Name,
      new KeysAndAttributes
      {
        Keys = new List<Dictionary<string, AttributeValue>>()
        {
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "DynamoDB" } }
          },
          new Dictionary<string, AttributeValue>()
          {
            { "Name", new AttributeValue { S = "Amazon S3" } }
          }
        }
      },
      // Optional - name of an attribute to retrieve.
      ProjectionExpression = "Title"
    }
  }
};

var response = client.BatchGetItem(request);
```

Pour de plus amples informations, veuillez consulter [BatchGetItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchGetItem.html). 

# Exemple : opérations CRUD à l'aide de l'API de AWS SDK pour .NET bas niveau
<a name="LowLevelDotNetItemsExample"></a>

L’exemple de code C\$1 suivant illustre des opérations CRUD sur un élément Amazon DynamoDB. L’exemple ajoute un élément à la table `ProductCatalog`, l’extrait, exécute diverses mises à jour et supprime finalement l’élément. Si vous n’avez pas créé cette table, vous pouvez également la créer par programmation. Pour de plus amples informations, veuillez consulter [Création de tableaux d'exemple et téléchargement de données à l'aide du AWS SDK pour .NET](AppendixSampleDataCodeDotNET.md).

Pour step-by-step obtenir des instructions sur le test de l'échantillon suivant, reportez-vous à[Exemples de code .NET](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;
using Amazon.SecurityToken;

namespace com.amazonaws.codesamples
{
    class LowLevelItemCRUDExample
    {
        private static string tableName = "ProductCatalog";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                CreateItem();
                RetrieveItem();

                // Perform various updates.
                UpdateMultipleAttributes();
                UpdateExistingAttributeConditionally();

                // Delete item.
                DeleteItem();
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
        }

        private static void CreateItem()
        {
            var request = new PutItemRequest
            {
                TableName = tableName,
                Item = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  }},
                { "Title", new AttributeValue {
                      S = "Book 201 Title"
                  }},
                { "ISBN", new AttributeValue {
                      S = "11-11-11-11"
                  }},
                { "Authors", new AttributeValue {
                      SS = new List<string>{"Author1", "Author2" }
                  }},
                { "Price", new AttributeValue {
                      N = "20.00"
                  }},
                { "Dimensions", new AttributeValue {
                      S = "8.5x11.0x.75"
                  }},
                { "InPublication", new AttributeValue {
                      BOOL = false
                  } }
            }
            };
            client.PutItem(request);
        }

        private static void RetrieveItem()
        {
            var request = new GetItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                ProjectionExpression = "Id, ISBN, Title, Authors",
                ConsistentRead = true
            };
            var response = client.GetItem(request);

            // Check the response.
            var attributeList = response.Item; // attribute list in the response.
            Console.WriteLine("\nPrinting item after retrieving it ............");
            PrintItem(attributeList);
        }

        private static void UpdateMultipleAttributes()
        {
            var request = new UpdateItemRequest
            {
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                // Perform the following updates:
                // 1) Add two new authors to the list
                // 1) Set a new attribute
                // 2) Remove the ISBN attribute
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#A","Authors"},
                {"#NA","NewAttribute"},
                {"#I","ISBN"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":auth",new AttributeValue {
                     SS = {"Author YY", "Author ZZ"}
                 }},
                {":new",new AttributeValue {
                     S = "New Value"
                 }}
            },

                UpdateExpression = "ADD #A :auth SET #NA = :new REMOVE #I",

                TableName = tableName,
                ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.
            };
            var response = client.UpdateItem(request);

            // Check the response.
            var attributeList = response.Attributes; // attribute list in the response.
                                                     // print attributeList.
            Console.WriteLine("\nPrinting item after multiple attribute update ............");
            PrintItem(attributeList);
        }

        private static void UpdateExistingAttributeConditionally()
        {
            var request = new UpdateItemRequest
            {
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#P", "Price"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":newprice",new AttributeValue {
                     N = "22.00"
                 }},
                {":currprice",new AttributeValue {
                     N = "20.00"
                 }}
            },
                // This updates price only if current price is 20.00.
                UpdateExpression = "SET #P = :newprice",
                ConditionExpression = "#P = :currprice",

                TableName = tableName,
                ReturnValues = "ALL_NEW" // Give me all attributes of the updated item.
            };
            var response = client.UpdateItem(request);

            // Check the response.
            var attributeList = response.Attributes; // attribute list in the response.
            Console.WriteLine("\nPrinting item after updating price value conditionally ............");
            PrintItem(attributeList);
        }

        private static void DeleteItem()
        {
            var request = new DeleteItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      N = "1000"
                  } }
            },

                // Return the entire item as it appeared before the update.
                ReturnValues = "ALL_OLD",
                ExpressionAttributeNames = new Dictionary<string, string>()
            {
                {"#IP", "InPublication"}
            },
                ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
            {
                {":inpub",new AttributeValue {
                     BOOL = false
                 }}
            },
                ConditionExpression = "#IP = :inpub"
            };

            var response = client.DeleteItem(request);

            // Check the response.
            var attributeList = response.Attributes; // Attribute list in the response.
                                                     // Print item.
            Console.WriteLine("\nPrinting item that was just deleted ............");
            PrintItem(attributeList);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }
    }
}
```

# Exemple : opérations par lots à l'aide de l'API de AWS SDK pour .NET bas niveau
<a name="batch-operation-lowlevel-dotnet"></a>

**Topics**
+ [Exemple : opération d'écriture par lots à l'aide de l'API de AWS SDK pour .NET bas niveau](#batch-write-low-level-dotnet)
+ [Exemple : opération Batch get à l'aide de l'API de AWS SDK pour .NET bas niveau](#LowLevelDotNetBatchGet)

Cette section fournit des exemples d’opérations par lots, *écriture par lots* et *obtention par lots*, qu’Amazon DynamoDB prend en charge.

## Exemple : opération d'écriture par lots à l'aide de l'API de AWS SDK pour .NET bas niveau
<a name="batch-write-low-level-dotnet"></a>

L’exemple de code C\$1 suivant exécute les opérations d’insertion et de suppression suivantes à l’aide de la méthode `BatchWriteItem` :
+ Insère un élément dans la table `Forum`.
+ Insère un élément et supprime un élément de la table `Thread`. 

Vous pouvez spécifier tout nombre de demandes put et delete sur une ou plusieurs tables lors de la création de votre demande d’écriture par lots. Cependant, DynamoDB `BatchWriteItem` limite la taille d’une demande d’écriture par lots et le nombre d’opérations d’insertion et de suppression dans une même opération d’écriture par lots. Pour de plus amples informations, veuillez consulter [BatchWriteItem](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_BatchWriteItem.html). Si votre demande dépasse ces limites, elle est rejetée. Si votre table n’a pas suffisamment de débit alloué pour traiter cette demande, les éléments non traités de la demande sont renvoyés dans la réponse. 

L’exemple suivant vérifie la réponse pour voir si elle comporte des éléments de demande non traités. Si tel est le cas, une boucle est parcourue et la demande `BatchWriteItem` est renvoyée avec les articles non traités de la demande. Vous pouvez également créer ces exemples de tables et charger des exemples de données par programmation. Pour de plus amples informations, veuillez consulter [Création de tableaux d'exemple et téléchargement de données à l'aide du AWS SDK pour .NET](AppendixSampleDataCodeDotNET.md).

Pour step-by-step obtenir des instructions sur le test de l'échantillon suivant, reportez-vous à[Exemples de code .NET](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelBatchWrite
    {
        private static string table1Name = "Forum";
        private static string table2Name = "Thread";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                TestBatchWrite();
            }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }

            Console.WriteLine("To continue, press Enter");
            Console.ReadLine();
        }

        private static void TestBatchWrite()
        {
            var request = new BatchWriteItemRequest
            {
                ReturnConsumedCapacity = "TOTAL",
                RequestItems = new Dictionary<string, List<WriteRequest>>
            {
                {
                    table1Name, new List<WriteRequest>
                    {
                        new WriteRequest
                        {
                            PutRequest = new PutRequest
                            {
                                Item = new Dictionary<string, AttributeValue>
                                {
                                    { "Name", new AttributeValue {
                                          S = "S3 forum"
                                      } },
                                    { "Threads", new AttributeValue {
                                          N = "0"
                                      }}
                                }
                            }
                        }
                    }
                },
                {
                    table2Name, new List<WriteRequest>
                    {
                        new WriteRequest
                        {
                            PutRequest = new PutRequest
                            {
                                Item = new Dictionary<string, AttributeValue>
                                {
                                    { "ForumName", new AttributeValue {
                                          S = "S3 forum"
                                      } },
                                    { "Subject", new AttributeValue {
                                          S = "My sample question"
                                      } },
                                    { "Message", new AttributeValue {
                                          S = "Message Text."
                                      } },
                                    { "KeywordTags", new AttributeValue {
                                          SS = new List<string> { "S3", "Bucket" }
                                      } }
                                }
                            }
                        },
                        new WriteRequest
                        {
                            // For the operation to delete an item, if you provide a primary key value
                            // that does not exist in the table, there is no error, it is just a no-op.
                            DeleteRequest = new DeleteRequest
                            {
                                Key = new Dictionary<string, AttributeValue>()
                                {
                                    { "ForumName",  new AttributeValue {
                                          S = "Some partition key value"
                                      } },
                                    { "Subject", new AttributeValue {
                                          S = "Some sort key value"
                                      } }
                                }
                            }
                        }
                    }
                }
            }
            };

            CallBatchWriteTillCompletion(request);
        }

        private static void CallBatchWriteTillCompletion(BatchWriteItemRequest request)
        {
            BatchWriteItemResponse response;

            int callCount = 0;
            do
            {
                Console.WriteLine("Making request");
                response = client.BatchWriteItem(request);
                callCount++;

                // Check the response.

                var tableConsumedCapacities = response.ConsumedCapacity;
                var unprocessed = response.UnprocessedItems;

                Console.WriteLine("Per-table consumed capacity");
                foreach (var tableConsumedCapacity in tableConsumedCapacities)
                {
                    Console.WriteLine("{0} - {1}", tableConsumedCapacity.TableName, tableConsumedCapacity.CapacityUnits);
                }

                Console.WriteLine("Unprocessed");
                foreach (var unp in unprocessed)
                {
                    Console.WriteLine("{0} - {1}", unp.Key, unp.Value.Count);
                }
                Console.WriteLine();

                // For the next iteration, the request will have unprocessed items.
                request.RequestItems = unprocessed;
            } while (response.UnprocessedItems.Count > 0);

            Console.WriteLine("Total # of batch write API calls made: {0}", callCount);
        }
    }
}
```

## Exemple : opération Batch get à l'aide de l'API de AWS SDK pour .NET bas niveau
<a name="LowLevelDotNetBatchGet"></a>

L’exemple de code C\$1 suivant extrait plusieurs éléments des tables `Forum` et `Thread` dans Amazon DynamoDB à l’aide de la méthode `BatchGetItem`. La demande `BatchGetItemRequest` spécifie les noms de table et une liste de clés primaires pour chaque table. L’exemple traite la réponse en imprimant les éléments récupérés. 

Pour step-by-step obtenir des instructions sur le test de l'échantillon suivant, reportez-vous à[Exemples de code .NET](CodeSamples.DotNet.md). 

**Example**  

```
using System;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelBatchGet
    {
        private static string table1Name = "Forum";
        private static string table2Name = "Thread";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            try
            {
                RetrieveMultipleItemsBatchGet();

                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }

        private static void RetrieveMultipleItemsBatchGet()
        {
            var request = new BatchGetItemRequest
            {
                RequestItems = new Dictionary<string, KeysAndAttributes>()
            {
                { table1Name,
                  new KeysAndAttributes
                  {
                      Keys = new List<Dictionary<string, AttributeValue> >()
                      {
                          new Dictionary<string, AttributeValue>()
                          {
                              { "Name", new AttributeValue {
                            S = "Amazon DynamoDB"
                        } }
                          },
                          new Dictionary<string, AttributeValue>()
                          {
                              { "Name", new AttributeValue {
                            S = "Amazon S3"
                        } }
                          }
                      }
                  }},
                {
                    table2Name,
                    new KeysAndAttributes
                    {
                        Keys = new List<Dictionary<string, AttributeValue> >()
                        {
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon DynamoDB"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "DynamoDB Thread 1"
                                  } }
                            },
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon DynamoDB"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "DynamoDB Thread 2"
                                  } }
                            },
                            new Dictionary<string, AttributeValue>()
                            {
                                { "ForumName", new AttributeValue {
                                      S = "Amazon S3"
                                  } },
                                { "Subject", new AttributeValue {
                                      S = "S3 Thread 1"
                                  } }
                            }
                        }
                    }
                }
            }
            };

            BatchGetItemResponse response;
            do
            {
                Console.WriteLine("Making request");
                response = client.BatchGetItem(request);

                // Check the response.
                var responses = response.Responses; // Attribute list in the response.

                foreach (var tableResponse in responses)
                {
                    var tableResults = tableResponse.Value;
                    Console.WriteLine("Items retrieved from table {0}", tableResponse.Key);
                    foreach (var item1 in tableResults)
                    {
                        PrintItem(item1);
                    }
                }

                // Any unprocessed keys? could happen if you exceed ProvisionedThroughput or some other error.
                Dictionary<string, KeysAndAttributes> unprocessedKeys = response.UnprocessedKeys;
                foreach (var unprocessedTableKeys in unprocessedKeys)
                {
                    // Print table name.
                    Console.WriteLine(unprocessedTableKeys.Key);
                    // Print unprocessed primary keys.
                    foreach (var key in unprocessedTableKeys.Value.Keys)
                    {
                        PrintItem(key);
                    }
                }

                request.RequestItems = unprocessedKeys;
            } while (response.UnprocessedKeys.Count > 0);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }
    }
}
```

# Exemple : gestion des attributs de type binaire à l'aide de l'API de AWS SDK pour .NET bas niveau
<a name="LowLevelDotNetBinaryTypeExample"></a>

L’exemple de code C\$1 suivant illustre la gestion des attributs de type binaire. L’exemple ajoute un élément à la table `Reply`. L’élément inclut un attribut de type binaire (`ExtendedMessage`) qui stocke les données compressées. Ensuite, l’exemple récupère l’élément et imprime toutes les valeurs d’attribut. A titre d’illustration, l’exemple compresse un exemple de flux et l’affecte à l’attribut `ExtendedMessage` à l’aide de la classe `GZipStream`, puis le décompresse lors de l’affichage de la valeur de l’attribut. 

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.IO;
using System.IO.Compression;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.Runtime;

namespace com.amazonaws.codesamples
{
    class LowLevelItemBinaryExample
    {
        private static string tableName = "Reply";
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();

        static void Main(string[] args)
        {
            // Reply table primary key.
            string replyIdPartitionKey = "Amazon DynamoDB#DynamoDB Thread 1";
            string replyDateTimeSortKey = Convert.ToString(DateTime.UtcNow);

            try
            {
                CreateItem(replyIdPartitionKey, replyDateTimeSortKey);
                RetrieveItem(replyIdPartitionKey, replyDateTimeSortKey);
                // Delete item.
                DeleteItem(replyIdPartitionKey, replyDateTimeSortKey);
                Console.WriteLine("To continue, press Enter");
                Console.ReadLine();
            }
            catch (AmazonDynamoDBException e) { Console.WriteLine(e.Message); }
            catch (AmazonServiceException e) { Console.WriteLine(e.Message); }
            catch (Exception e) { Console.WriteLine(e.Message); }
        }

        private static void CreateItem(string partitionKey, string sortKey)
        {
            MemoryStream compressedMessage = ToGzipMemoryStream("Some long extended message to compress.");
            var request = new PutItemRequest
            {
                TableName = tableName,
                Item = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  }},
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  }},
                { "Subject", new AttributeValue {
                      S = "Binary type "
                  }},
                { "Message", new AttributeValue {
                      S = "Some message about the binary type"
                  }},
                { "ExtendedMessage", new AttributeValue {
                      B = compressedMessage
                  }}
            }
            };
            client.PutItem(request);
        }

        private static void RetrieveItem(string partitionKey, string sortKey)
        {
            var request = new GetItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  } },
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  } }
            },
                ConsistentRead = true
            };
            var response = client.GetItem(request);

            // Check the response.
            var attributeList = response.Item; // attribute list in the response.
            Console.WriteLine("\nPrinting item after retrieving it ............");

            PrintItem(attributeList);
        }

        private static void DeleteItem(string partitionKey, string sortKey)
        {
            var request = new DeleteItemRequest
            {
                TableName = tableName,
                Key = new Dictionary<string, AttributeValue>()
            {
                { "Id", new AttributeValue {
                      S = partitionKey
                  } },
                { "ReplyDateTime", new AttributeValue {
                      S = sortKey
                  } }
            }
            };
            var response = client.DeleteItem(request);
        }

        private static void PrintItem(Dictionary<string, AttributeValue> attributeList)
        {
            foreach (KeyValuePair<string, AttributeValue> kvp in attributeList)
            {
                string attributeName = kvp.Key;
                AttributeValue value = kvp.Value;

                Console.WriteLine(
                    attributeName + " " +
                    (value.S == null ? "" : "S=[" + value.S + "]") +
                    (value.N == null ? "" : "N=[" + value.N + "]") +
                    (value.SS == null ? "" : "SS=[" + string.Join(",", value.SS.ToArray()) + "]") +
                    (value.NS == null ? "" : "NS=[" + string.Join(",", value.NS.ToArray()) + "]") +
                    (value.B == null ? "" : "B=[" + FromGzipMemoryStream(value.B) + "]")
                    );
            }
            Console.WriteLine("************************************************");
        }

        private static MemoryStream ToGzipMemoryStream(string value)
        {
            MemoryStream output = new MemoryStream();
            using (GZipStream zipStream = new GZipStream(output, CompressionMode.Compress, true))
            using (StreamWriter writer = new StreamWriter(zipStream))
            {
                writer.Write(value);
            }
            return output;
        }

        private static string FromGzipMemoryStream(MemoryStream stream)
        {
            using (GZipStream zipStream = new GZipStream(stream, CompressionMode.Decompress))
            using (StreamReader reader = new StreamReader(zipStream))
            {
                return reader.ReadToEnd();
            }
        }
    }
}
```

# Amélioration de l’accès aux données avec les index secondaires dans DynamoDB
<a name="SecondaryIndexes"></a>

Amazon DynamoDB fournit un accès rapide aux éléments d’une table en spécifiant des valeurs de clé principale. Cependant, il serait utile pour de nombreuses applications de disposer d’une ou de plusieurs clés secondaires (ou alternatives) permettant un accès efficace aux données présentant d’autres attributs que la clé primaire. Pour ce faire, vous pouvez créer un ou plusieurs index secondaires pour une table, et émettre des demandes `Query` ou `Scan` sur ces index.

Un *index secondaire* est une structure de données qui contient un sous-ensemble d’attributs d’une table, ainsi qu’une autre clé pour prendre en charge des opérations `Query`. Vous pouvez récupérer les données de l’index à l’aide d’un `Query`, globalement de la même manière que vous utilisez `Query` avec une table. Une table peut avoir plusieurs index secondaires, ce qui permet à vos applications d’accéder à de nombreux modèles de requête différents.

**Note**  
Vous pouvez également `Scan` un index, globalement de la même manière que vous le feriez pour `Scan` une table.   
L’accès intercompte pour les opérations d’analyse d’index secondaires n’est actuellement pas pris en charge par les [politiques basées sur les ressources](access-control-resource-based.md).

Chaque index secondaire est associé à une table dont il extrait ses données. Il s’agit de la *table de base* de l’index. Lorsque vous créez un index, vous définissez une autre clé pour cet index (clé de partition et clé de tri). Vous définissez également les attributs qui doivent être *projetés*, ou copiés de la table de base vers l’index. DynamoDB copie ces attributs dans l’index, ainsi que les attributs de clé primaire de la table de base. Vous pouvez ensuite interroger ou analyser l’index de la même manière que vous procéderiez avec une table. 

DynamoDB grère automatiquement chaque index secondaire . Lorsque vous ajoutez, modifiez ou supprimez des éléments dans la table de base, tous les index de cette table sont également mis à jour pour refléter ces modifications.

DynamoDB prend en charge deux types d’index secondaires :
+ **[Index secondaire global](GSI.html) – **Index avec une clé de partition et une clé de tri pouvant différer de celles de la table de base. Un index secondaire global est considéré comme « global », car les requêtes sur l’index peuvent couvrir toutes les données de la table de base, sur toutes les partitions. Un index secondaire global est stocké dans son propre espace de partition à l’écart de la table de base, et est mis à l’échelle séparément de celle-ci.
+ **[Index secondaire local](LSI.html) – **Index avec la même clé de partition que la table de base, mais une clé de tri différente. Un index secondaire est « local » dans la mesure où la portée de chacune de ses partitions correspond à une partition de la table de base ayant la même valeur de clé de partition.

Pour une comparaison des index secondaires globaux et des index secondaires locaux, regardez cette vidéo.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/BkEu7zBWge8/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/BkEu7zBWge8)


**Topics**
+ [Utilisation d’index secondaires globaux dans DynamoDB](GSI.md)
+ [Index locaux secondaires](LSI.md)

Vous devez tenir compte des exigences de votre application lorsque vous déterminez le type d’index à utiliser. Le tableau suivant montre les principales différences entre un index secondaire global et un index secondaire local.


****  

| Caractéristiques | GSI | Index secondaire local | 
| --- | --- | --- | 
| Schéma de clé | La clé primaire d’un index secondaire global peut être simple (clé de partition) ou composite (clé de partition et clé de tri). | La clé primaire d’un index secondaire local doit être composite (clé de partition et clé de tri). | 
| Attributs de clé | La clé de partition d’index et la clé de tri (le cas échéant) peuvent être n’importe quels attributs de table de base de type chaîne, nombre ou binaire. | La clé de partition de l’index est le même attribut que la clé de partition de la table de base. La clé de tri peut être n’importe quel attribut de la table de base, de type chaîne, nombre ou binaire. | 
| Restrictions de taille par valeur de clé de partition | Les index secondaires globaux ne font l’objet d’aucune restriction de taille . | Pour chaque valeur de clé de partition, la taille totale de tous les éléments indexés doit être inférieure ou égale à 10 Go. | 
| Opérations d’index en ligne | Vous pouvez créer des index secondaires globaux au moment où vous créez une table. Vous pouvez ajouter un index secondaire global à une table ou en supprimer un. Pour de plus amples informations, veuillez consulter [Gestion des index secondaires globaux dans DynamoDB](GSI.OnlineOps.md).  | Vous créez des index secondaires locaux au moment où vous créez une table. Vous ne pouvez ni ajouter un index secondaire local à une table, ni en supprimer un. | 
| Requêtes et partitions | Un index secondaire global vous permet d’interroger une table entière, toutes partitions incluses.  | Un index secondaire local vous permet d’interroger une seule partition en spécifiant la valeur de clé de partition dans la requête. | 
| Cohérence en lecture | Les requêtes sur les index secondaires globaux ne prennent en charge que la cohérence éventuelle. | Lorsque vous interrogez un index secondaire local, vous avez le choix entre la cohérence éventuelle ou la cohérence forte. | 
| Consommation de débit alloué | Chaque index secondaire global a ses propres paramètres de débit approvisionné pour les activités de lecture et d’écriture. Les requêtes ou analyses sur un index secondaire global consomment des unités de capacité de l’index, pas de la table de base. Il en va de même pour des mises à jour d’index secondaire global résultant d’écritures dans la table. Un index secondaire global associé à des tables globales consomme des unités de capacité d’écriture.  | Les requêtes ou analyses sur un index secondaire local consomment des unités de capacité de lecture de la table de base. Lorsque vous écrivez des données dans une table, ses index secondaires locaux sont mis à jour, ce qui entraîne une consommation des unités de capacité d’écriture à partir de la table de base. Un index secondaire local associé à des tables globales consomme des unités de capacité d’écriture répliquées. | 
| Attributs projetés | Les requêtes ou analyses d’index secondaire global ne vous permettent d’interroger que les attributs projetés dans l’index. DynamoDB n’extrait aucun attribut de la table. | Si vous interrogez ou analysez un index secondaire local, vous pouvez demander des attributs qui ne sont pas projetés dans l’index. DynamoDB extrait automatiquement ces attributs de la table. | 

Si vous souhaitez créer plus d’une table avec des index secondaires, vous devez le faire de manière séquentielle. Par exemple, vous créez la première table et attendez qu’elle devienne `ACTIVE`, vous créez la table suivante et attendez qu’elle devienne `ACTIVE`, et ainsi de suite. Si vous essayez de créer simultanément plus d’une table avec un index secondaire, DynamoDB renvoie une `LimitExceededException`.

Chaque index secondaire utilise la même [classe de table](HowItWorks.TableClasses.html) et le même [mode de capacité](capacity-mode.md) que la table de base à laquelle il est associé. Pour chaque index secondaire, vous devez spécifier les informations suivantes :
+ Type d’index à créer : index secondaire global ou un index secondaire local.
+ Un nom pour l’index. Les règles de dénomination pour les index sont identiques à celles pour les tables, comme indiqué dans [Quotas dans Amazon DynamoDB](ServiceQuotas.md). Le nom doit être unique pour la table de base à laquelle il est associé, mais vous pouvez utiliser le même nom pour des index qui sont associés à d’autres tables de base.
+ Le schéma de clés pour l’index. Chaque attribut du schéma de clé d’index doit être un attribut de niveau supérieur de type `String`, `Number` ou `Binary`. D’autres types de données, y compris les documents et les jeux, ne sont pas autorisés. Les autres exigences pour le schéma de clé dépendent du type d’index : 
  + Pour un index secondaire global, la clé de partition peut être n’importe quel attribut scalaire de la table de base. Une clé de tri est facultative et peut également être n’importe quel attribut scalaire de la table de base.
  + Pour un index secondaire local, la clé de partition doit être la même que celle de la table de base, et la clé de tri doit être un attribut de la table de base autre qu’une clé.
+ Attributs supplémentaires, le cas échéant, à projeter de la table de base vers l’index. Ces attributs sont en plus des attributs clés de la table, qui sont automatiquement projetés dans chaque index. Vous pouvez projeter des attributs de n’importe quel type de données, y compris scalaires, documents et jeux.
+ Les paramètres de débit alloué pour l’index, si nécessaire :
  + Pour un index secondaire global, vous devez spécifier des paramètres d’unité de capacité de lecture et d’écriture. Ces paramètres de débit alloué sont indépendants des paramètres de la table de base.
  + Pour un index secondaire local, vous n’avez pas besoin de spécifier des paramètres d’unité de capacité de lecture et d’écriture. Toute opération de lecture et d’écriture sur un index secondaire local tire les paramètres de débit approvisionné de sa table de base.

Pour bénéficier d’une flexibilité de requête maximum, vous pouvez créer jusqu’à 20 index secondaires globaux (quota par défaut) et 5 index secondaires locaux par table.

Pour obtenir la liste détaillée des index secondaires sur une table, utilisez l’opération `DescribeTable`. L’opération `DescribeTable` renvoie le nom, la taille de stockage et le nombre d’éléments pour chaque index secondaire sur la table. Ces valeurs ne sont pas mises à jour en temps réel, mais elles sont actualisées environ toutes les six heures.

Vous pouvez accéder aux données dans un index secondaire à l’aide de l’opération `Query` ou `Scan`. Vous devez spécifier le nom de la table de base et le nom de l’index que vous souhaitez utiliser, les attributs à renvoyer dans les résultats, ainsi que tous les filtres ou expressions de condition que vous souhaitez appliquer. DynamoDB peut renvoyer les résultats dans l’ordre croissant ou décroissant.

Lorsque vous supprimez une table, tous les index associés à cette table sont également supprimés.

Pour connaître les bonnes pratiques, consultez [Bonnes pratiques d’utilisation d’index secondaires dans DynamoDB](bp-indexes.md).

# Utilisation d’index secondaires globaux dans DynamoDB
<a name="GSI"></a>

Certaines applications peuvent avoir besoin d’exécuter de nombreux types de requêtes, à l’aide de divers attributs comme critères de requête. Pour prendre en charge ces exigences, vous pouvez créer un ou plusieurs *index secondaires globaux* et émettre des demandes `Query` sur ces index dans Amazon DynamoDB.

**Topics**
+ [Étape 6 : Utiliser un index secondaire global](#GSI.scenario)
+ [Projections d’attribut](#GSI.Projections)
+ [Schéma de clé à attributs multiples](#GSI.MultiAttributeKeys)
+ [Lecture de données à partir d’un index secondaire global](#GSI.Reading)
+ [Synchronisation des données entre les tables et les index secondaires globaux](#GSI.Writes)
+ [Classes de tables avec index secondaire global](#GSI.tableclasses)
+ [Considérations sur le débit alloué pour les index secondaires globaux](#GSI.ThroughputConsiderations)
+ [Considérations relatives au stockage pour les index secondaires globaux](#GSI.StorageConsiderations)
+ [Motifs de design](GSI.DesignPatterns.md)
+ [Gestion des index secondaires globaux dans DynamoDB](GSI.OnlineOps.md)
+ [Détection et correction des violations de clé d’index dans DynamoDB](GSI.OnlineOps.ViolationDetection.md)
+ [Utilisation d'index secondaires globaux : Java](GSIJavaDocumentAPI.md)
+ [Utilisation d'index secondaires globaux : .NET](GSILowLevelDotNet.md)
+ [Gestion des index secondaires globaux dans DynamoDB à l’aide de l’AWS CLI](GCICli.md)

## Étape 6 : Utiliser un index secondaire global
<a name="GSI.scenario"></a>

À des fins d’illustration, considérons une table nommée `GameScores` qui assure le suivi des utilisateurs et enregistre les scores d’une application de jeux pour appareils mobiles. Chaque élément dans `GameScores` est identifié par une clé de partition (`UserId`) et une clé de tri (`GameTitle`). 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.)

![\[GameScores table contenant une liste de l'identifiant utilisateur, du titre, du score, de la date et des victoires/défaites.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_01.png)


Supposons maintenant que vous vouliez écrire une application de classement pour afficher les meilleurs scores de chaque partie. Une requête ayant spécifié les attributs clé (`UserId` et `GameTitle`) serait très efficace. Cependant, si l’application a besoin d’extraire les données depuis `GameScores` en fonction de `GameTitle` uniquement, elle nécessiterait l’utilisation d’une opération `Scan`. Lorsque plusieurs éléments sont ajoutés à la table, les analyses de toutes les données deviennent lentes et inefficaces. Cela rend difficile la réponse aux questions suivantes :
+ Quel est le meilleur score jamais enregistré pour le jeu Meteor Blasters ?
+ Quel utilisateur a le score le plus élevé pour Galaxy Invaders ?
+ Quel est le taux plus élevé du nombre de victoires par rapport au nombre de pertes ?

Afin d’accélérer les requêtes sur des attributs autres que de clé, vous pouvez créer un index secondaire global. Un index secondaire global contient une sélection d’attributs de la table de base, mais ils sont organisés selon une clé primaire différente de celle de la table. La clé d’index n’a pas besoin d’avoir l’un des attributs de clé de la table. Elle n’a même pas besoin d’avoir le même schéma de clé qu’une table.

Par exemple, vous pouvez créer un index secondaire global nommé `GameTitleIndex`, avec une clé de partition `GameTitle` et une clé de tri `TopScore`. Comme les attributs de la clé primaire de la table de base sont toujours projetés sur un index, l’attribut `UserId` est également présent. Le schéma suivant illustre ce à quoi l’index `GameTitleIndex` doit ressembler.

![\[GameTitleIndex tableau contenant une liste de titres, de scores et d'identifiants d'utilisateur.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_02.png)


Maintenant, vous pouvez interroger `GameTitleIndex` et obtenir facilement les scores de Meteor Blasters. Les résultats sont triés sur les valeurs de la clé de tri, `TopScore`. Si vous définissez le paramètre `ScanIndexForward` sur la valeur false, les résultats sont retournés par ordre décroissant, de telle sorte que le meilleur score est retourné en premier.

Chaque index secondaire global doit avoir une clé de partition et peut avoir une clé de tri facultative. Le schéma de la clé d’index peut être différent de celui de la table de base. Vous pouvez disposer d’une table avec une clé primaire simple (clé de partition), et créer un index secondaire global avec une clé primaire composite (clé de partition et clé de tri), ou inversement. Les attributs de clé d’index peuvent se composer de n’importe lequel des attributs `String`, `Number` ou `Binary` de niveau supérieur de la table de base. Les autres types scalaires, types de document et types d’ensemble ne sont pas autorisés.

Vous pouvez projeter d’autres attributs de table de base sur l’index si vous le souhaitez. Lorsque vous interrogez l’index, DynamoDB peut extraire ces attributs projetés de façon efficace. Cependant, les interrogations d’index secondaire global ne peuvent pas extraire d’attributs de la table de base. Par exemple, si vous interrogez `GameTitleIndex` comme illustré dans le diagramme précédent, la requête ne peut pas accéder aux attributs non-clé autres que `TopScore` (même si les attributs de clé `GameTitle` et `UserId` sont automatiquement projetés).

Dans une table DynamoDB, chaque valeur de clé doit être unique. En revanche, les valeurs de clé dans un index secondaire global n’ont pas besoin d’être uniques. À des fins d’illustration, supposons qu’un jeu nommé Comet Quest soit particulièrement difficile, avec de nombreux utilisateurs qui tentent en vain d’obtenir un score supérieur à zéro. Les quelques données suivantes représentent ce comportement.


****  

| UserId | GameTitle | TopScore | 
| --- | --- | --- | 
| 123 | Comet Quest | 0 | 
| 201 | Comet Quest | 0 | 
| 301 | Comet Quest | 0 | 

Lorsque de l’ajout de ces données à la table `GameScores`, DynamoDB les propage vers `GameTitleIndex`. Si nous interrogeons alors l’index à l’aide de Comet Quest pour `GameTitle` et de 0 pour `TopScore`, les données suivantes sont renvoyées.

![\[Table contenant la liste des titres, scores et ID utilisateur.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_05.png)


Seuls les éléments avec les valeurs de clé spécifiée apparaissent dans la réponse. Au sein de cet ensemble de données, les éléments ne figurent dans aucun ordre particulier. 

Un index secondaire global ne suit que les éléments de données où ses attributs clés existent réellement. Par exemple, supposons que vous ayez ajouté un nouvel élément à la table `GameScores`, mais que vous n’ayez fourni que les attributs de clé primaires requis.


****  

| UserId | GameTitle | 
| --- | --- | 
| 400 | Comet Quest | 

Étant donné que vous n’avez pas spécifié l’attribut `TopScore`, DynamoDB ne propage pas cet élément vers `GameTitleIndex`. Par conséquent, si vous interrogiez `GameScores` pour tous les éléments Comet Quest, vous obtiendriez les quatre éléments suivants.

![\[Table contenant la liste de 4 titres, des meilleurs scores et des ID utilisateur.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_04.png)


Une requête similaire sur `GameTitleIndex` renvoie toujours trois éléments, plutôt que quatre. Cela est dû au fait que l’élément avec `TopScore` non existant n’est pas propagé sur l’index.

![\[Table contenant la liste de 3 titres, des meilleurs scores et des ID utilisateur.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_05.png)


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

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 précédent diagramme, `GameTitleIndex` n’a qu’un seul attribut projeté : `UserId`. Par conséquent, si une application peut déterminer efficacement le `UserId` des joueurs avec les scores les plus élevés pour chaque jeu à l’aide de `GameTitle` et de `TopScore` dans des requêtes, elle peut déterminer efficacement le taux le plus élevé de victoires par rapport au nombre de défaites pour ces joueurs. Pour ce faire, l'application devra effectuer une requête supplémentaire sur la table de base pour récupérer les victoires et les défaites de chacun des meilleurs buteurs. Une façon plus efficace de prendre en charge les requêtes sur ces données serait de projeter ces attributs de la table de base vers l’index secondaire global, comme illustré dans ce diagramme. 

![\[Représentation de la projection d’attributs non clés dans un GSI pour permettre une interrogation efficace.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/GSI_06.png)


Comme les attributs non clés `Wins` et`Losses` sont projetés dans l’index, une application peut déterminer le rapport entre le nombre de victoires et le nombre de défaites de n’importe quel jeu, ou pour toute combinaison d’ID d’utilisateur et de jeu.

Lorsque vous choisissez les attributs à projeter sur un index secondaire global, 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 global. Plus l’index est petit, moins les coûts d’écriture et de stockage sont élevés.
+ Si votre application accède fréquemment à des attributs autres que de clé, vous devez envisager de projeter ceux-ci dans un index secondaire global. Les coûts de stockage supplémentaires de l’index secondaire global 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 global. Cela vous offre une flexibilité maximale. Cependant, vos coûts de stockage augmenteront, voire doubleront.
+ Si votre application doit interroger peu fréquemment une table, mais doit exécuter un grand nombre d’écritures ou de mises à jour des données de la table, pensez à projeter `KEYS_ONLY`. L’index secondaire global sera d’une taille minimale, mais continuera d’être disponible chaque fois que ce sera nécessaire pour une activité de requête. 

## Schéma de clé à attributs multiples
<a name="GSI.MultiAttributeKeys"></a>

Les index secondaires globaux prennent en charge les clés à attributs multiples, ce qui vous permet de composer des clés de partition et de trier les clés à partir de plusieurs attributs. Avec les clés à attributs multiples, vous pouvez créer une clé de partition à partir de quatre attributs au maximum et une clé de tri à partir de quatre attributs, pour un total de huit attributs par schéma de clé.

Les clés à attributs multiples simplifient votre modèle de données en éliminant le besoin de concaténer manuellement les attributs dans des clés synthétiques. Au lieu de créer des chaînes composites`TOURNAMENT#WINTER2024#REGION#NA-EAST`, vous pouvez utiliser directement les attributs naturels de votre modèle de domaine. DynamoDB gère automatiquement la logique des clés composites, en hachant plusieurs attributs de clé de partition pour la distribution des données et en maintenant un ordre de tri hiérarchique entre plusieurs attributs de clé de tri.

Par exemple, imaginez un système de tournois de jeu dans lequel vous souhaitez organiser les matchs par tournoi et par région. Avec les clés à attributs multiples, vous pouvez définir votre clé de partition sous la forme de deux attributs distincts : `tournamentId` et`region`. De même, vous pouvez définir votre clé de tri à l'aide de plusieurs attributs tels que `round``bracket`, et `matchId` pour créer une hiérarchie naturelle. Cette approche permet de saisir vos données et de garder votre code propre, sans manipulation de chaînes ni analyse syntaxique.

Lorsque vous interrogez un index secondaire global avec des clés à attributs multiples, vous devez spécifier tous les attributs de clé de partition en utilisant des conditions d'égalité. Pour trier les attributs clés, vous pouvez les interroger left-to-right dans l'ordre dans lequel ils sont définis dans le schéma de clé. Cela signifie que vous pouvez interroger le premier attribut clé de tri seul, les deux premiers attributs ensemble ou tous les attributs ensemble, mais vous ne pouvez pas ignorer les attributs situés au milieu. Les conditions d'inégalité telles que `>` `<``BETWEEN`,, ou `begins_with()` doivent être la dernière condition de votre requête.

Les clés à attributs multiples fonctionnent particulièrement bien lors de la création d'index secondaires globaux sur des tables existantes. Vous pouvez utiliser des attributs qui existent déjà dans votre table sans avoir à ajouter des clés synthétiques à vos données. Cela permet d'ajouter facilement de nouveaux modèles de requête à votre application en créant des index qui réorganisent vos données à l'aide de différentes combinaisons d'attributs.

Chaque attribut d'une clé à attributs multiples peut avoir son propre type de données : `String` (S), `Number` (N) ou `Binary` (B). Lorsque vous choisissez des types de données, considérez que `Number` les attributs sont triés numériquement sans nécessiter de remplissage nul, tandis que les `String` attributs sont triés de manière lexicographique. Par exemple, si vous utilisez un `Number` type pour un attribut de score, les valeurs 5, 50, 500 et 1000 sont triées par ordre numérique naturel. Les mêmes valeurs que le `String` type seront triées comme « 1000 », « 5 », « 50 », « 500 », sauf si vous les complétez avec des zéros en tête.

Lorsque vous concevez des clés à attributs multiples, classez vos attributs du plus général au plus spécifique. Pour les clés de partition, combinez les attributs qui sont toujours interrogés ensemble et qui assurent une bonne distribution des données. Pour les clés de tri, placez les attributs fréquemment demandés en premier dans la hiérarchie afin d'optimiser la flexibilité des requêtes. Cet ordre vous permet d'effectuer des requêtes à n'importe quel niveau de granularité correspondant à vos habitudes d'accès.

Consultez le [Clés à attributs multiples](GSI.DesignPattern.MultiAttributeKeys.md) pour des exemples de mise en œuvre.

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

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

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

Vous pouvez utiliser l’opération `Query` pour accéder à un ou plusieurs éléments dans un index secondaire global. La requête doit spécifier le nom de la table de base et le nom de l’index que vous souhaitez utiliser, les attributs à renvoyer dans les résultats de la requête, ainsi que toutes les conditions de requête que vous souhaitez appliquer. DynamoDB peut renvoyer les résultats dans l’ordre croissant ou décroissant.

Prenez en compte les données suivantes retournées à partir d’une opération `Query` qui demande les données de jeu pour une application de classement.

```
{
    "TableName": "GameScores",
    "IndexName": "GameTitleIndex",
    "KeyConditionExpression": "GameTitle = :v_title",
    "ExpressionAttributeValues": {
        ":v_title": {"S": "Meteor Blasters"}
    },
    "ProjectionExpression": "UserId, TopScore",
    "ScanIndexForward": false
}
```

Dans cette requête :
+ DynamoDB y *GameTitleIndex*accède à l'aide de la clé de partition pour localiser *GameTitle*les éléments d'index des Meteor Blasters. 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 jeu, DynamoDB utilise l'index pour accéder à tous les IDs utilisateurs et aux meilleurs scores de ce jeu.
+ Les résultats sont retournés, triés par ordre décroissant, car le paramètre `ScanIndexForward` a la valeur false.

### Interrogation d’un index secondaire global
<a name="GSI.Scanning"></a>

Vous pouvez utiliser l’opération `Scan` pour extraire toutes les données d’un index secondaire global. 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’opération `Scan`. Pour de plus amples informations, veuillez consulter [Filtrer les expressions à des fins d’analyse](Scan.md#Scan.FilterExpression).

## Synchronisation des données entre les tables et les index secondaires globaux
<a name="GSI.Writes"></a>

DynamoDB synchronise automatiquement chaque index secondaire global avec sa table de base. Quand une application écrit ou supprime des éléments dans une table, tout index secondaire global sur cette table est mis à jour de manière asynchrone, à l’aide d’un modèle éventuellement cohérent. 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.

 Les index secondaires globaux héritent du mode read/write capacité de la table de base. Pour de plus amples informations, veuillez consulter [Considérations relatives au changement de mode de capacité dans DynamoDB](bp-switching-capacity-modes.md). 

Lorsque vous créez un index secondaire global, vous spécifiez un ou plusieurs attributs de clé d’index et leurs types de données. Cela signifie que chaque fois que vous écrivez un élément sur la table de base, les types de données de ces attributs doivent correspondre aux types de données du schéma de la clé d’index. Dans le cas de `GameTitleIndex`, la clé de partition `GameTitle` de l’index est définie comme type de données `String`. La clé de tri `TopScore` de l’index est de type `Number`. Si vous essayez d’ajouter un élément à la table `GameScores` et spécifiez un type de données différent pour `GameTitle` ou pour `TopScore`, DynamoDB renvoie une `ValidationException` en raison de la discordance des types de données.

Lorsque vous insérez ou supprimez des éléments dans une table, les index secondaires globaux sont mis à jour selon une façon éventuellement cohérente. Les modifications apportées aux données de la table sont propagées sur les index secondaires globaux en une fraction de seconde, dans des conditions normales. Cependant, dans certains scénarios de défaillance peu probables, les retards de propagation peuvent être plus longs. Pour cette raison, vos applications ont besoin d’anticiper et de gérer les situations où une requête sur un index secondaire global renvoie des résultats qui ne sont pas à jour.

Si vous écrivez un élément dans une table, vous n’avez pas à spécifier les attributs pour une clé de tri d’index secondaire global. Si vous utilisez `GameTitleIndex` comme exemple, vous n’avez pas besoin de spécifier une valeur pour l’attribut `TopScore` pour pouvoir écrire un nouvel élément sur la table `GameScores`. Dans ce cas, DynamoDB n’écrit aucune donnée dans l’index pour cet élément particulier.

Une table avec de nombreux index secondaires globaux 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 sur le débit alloué pour les index secondaires globaux](#GSI.ThroughputConsiderations).

## Classes de tables avec index secondaire global
<a name="GSI.tableclasses"></a>

Un index secondaire global utilisera toujours la même classe de tables que sa table de base. Chaque fois qu’un nouvel index secondaire global est ajouté à une table, le nouvel index utilise la même classe de tables que sa table de base. Lorsque la classe de tables d’une table est mise à jour, tous les index secondaires globaux associés sont également mis à jour.

## Considérations sur le débit alloué pour les index secondaires globaux
<a name="GSI.ThroughputConsiderations"></a>

Lorsque vous créez un index secondaire global sur une table en mode approvisionné, vous devez spécifier des unités de capacité de lecture et d’écriture pour la charge de travail prévue sur cet index. Les paramètres de débit approvisionné d’un index secondaire global sont distincts de ceux de sa table de base. Une opération `Query` sur un index secondaire global consomme les unités de capacité de lecture de l’index, pas de la table de base. Lorsque vous insérez ou supprimez des éléments dans une table, les index secondaires globaux sont également mis à jour. Ces mises à jour d’index consomment des unités de capacité d’écriture à partir de l’index, et non à partir de la table de base.

Par exemple, si vous exécutez une opération `Query` sur un index secondaire global et dépassez sa capacité de lecture approvisionnée, votre demande est limitée. Si vous exécutez une activité d’écriture massive sur la table, alors qu’un index secondaire global sur celle-ci a une capacité d’écriture insuffisante, l’activité d’écriture sur la table est limitée.

**Important**  
 Pour éviter les limitations potentielles, la capacité d’écriture allouée pour un index secondaire global doit être supérieure ou égale à la capacité d’écriture de la table de base, car les nouvelles mises à jour écrivent dans la table de base et l’index secondaire global. 

Afin de modifier les paramètres de débit approvisionné pour un index secondaire global, utilisez l’opération `DescribeTable`. Des informations détaillées sur tous les index secondaires globaux de la table sont retournées.

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

Les index secondaires globaux prennent en charge les lectures éventuellement cohérentes ; chacune d’elles utilise la moitié d’une unité de capacité en lecture. Cela signifie qu’une interrogation d’index secondaire global peut extraire jusqu’à 2 x 4 Ko = 8 Ko par unité de capacité de lecture.

Pour les interrogations d’index secondaire global, DynamoDB calcule l’activité de lecture approvisionnée de la même façon que pour les interrogations de 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é en 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).

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.

Par exemple, considérons un index secondaire global où chaque élément contient 2 000 octets de données. Supposons à présent que vous effectuez une opération `Query` sur cet index et que la `KeyConditionExpression` de la requête renvoie huit éléments. La taille totale des éléments correspondants est de 2 000 octets x 8 éléments = 16 000 octets. Ce résultat est ensuite arrondi à la limite de 4 Ko la plus proche. Les interrogations d’index secondaire global étant éventuellement cohérentes, le coût total est de 0,5 x (16 Ko / 4 Ko), soit 2 unités de capacité de lecture.

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

Lors de l’ajout, de la mise à jour ou de la suppression d’un élément dans une table, si l’opération affecte un index secondaire global, celui-ci consomme les unités de capacité d’écriture approvisionnée à cette fin. Le coût total du débit alloué pour une écriture se compose de la somme des unités de capacité en écriture utilisées par l’écriture sur la table de base et de celles utilisées par la mise à jour des index secondaires globaux. Notez que, si une écriture dans une table ne requiert de mise à jour d’index secondaire global, aucune capacité d’écriture n’est consommée à partir de l’index.

Pour qu’une écriture de table réussisse, les paramètres de débit provisionnés de la table et de tous ses index secondaires globaux doivent avoir une capacité d’écriture suffisante pour accueillir l’écriture. Sinon, l’écriture dans la table est limitée. 

**Important**  
Lors de la création d’un index secondaire global (GSI), les opérations d’écriture dans la table de base peuvent être limitées si l’activité GSI résultant des écritures dans la table de base dépasse la capacité d’écriture allouée au GSI. Cette limitation affecte toutes les opérations d’écriture, du processus d’indexation à la perturbation potentielle de vos charges de travail de production. Pour plus d’informations, consultez [Résolution des problèmes de limitation dans Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TroubleshootingThrottling.html).

Le coût d’écriture d’un élément dans un index secondaire global 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ée (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 nouveau é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.
+ Si la mise à jour de la table ne modifie que la valeur des attributs projetés du schéma de clé d’index, mais ne change pas la valeur d’un quelconque attribut de clé indexé, une écriture est nécessaire pour mettre à jour les valeurs des attributs projetés sur 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 retourner et en projetant uniquement ces attributs dans l’index.

## Considérations relatives au stockage pour les index secondaires globaux
<a name="GSI.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 globaux 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 globaux 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

Afin d’estimer les exigences de stockage pour un index secondaire global, vous pouvez évaluer la taille moyenne d’un élément de l’index, puis la multiplier par le nombre d’éléments de la table de base ayant les attributs de clé d’index secondaire global.

Si une table contient un élément dont aucun attribut particulier n'est défini, mais que cet attribut est défini comme clé de partition d'index ou clé de tri, DynamoDB n'écrit aucune donnée pour cet élément dans l'index.

# Motifs de design
<a name="GSI.DesignPatterns"></a>

Les modèles de conception fournissent des solutions éprouvées aux défis courants liés à l'utilisation d'index secondaires globaux. Ces modèles vous aident à créer des applications efficaces et évolutives en vous montrant comment structurer vos index pour des cas d'utilisation spécifiques.

Chaque modèle inclut un guide d'implémentation complet avec des exemples de code, les meilleures pratiques et des cas d'utilisation réels pour vous aider à appliquer le modèle à vos propres applications.

**Topics**
+ [Clés à attributs multiples](GSI.DesignPattern.MultiAttributeKeys.md)

# Modèle de clés à attributs multiples
<a name="GSI.DesignPattern.MultiAttributeKeys"></a>

## Aperçu
<a name="GSI.DesignPattern.MultiAttributeKeys.Overview"></a>

Les clés à attributs multiples vous permettent de créer une partition d'index secondaire global (GSI) et de trier les clés composées d'un maximum de quatre attributs chacune. Cela réduit le code côté client et facilite la modélisation initiale des données et l'ajout de nouveaux modèles d'accès ultérieurement.

Imaginons un scénario courant : pour créer un GSI qui interroge des éléments selon plusieurs attributs hiérarchiques, vous devez traditionnellement créer des clés synthétiques en concaténant des valeurs. Par exemple, dans une application de jeu, pour interroger les matchs d'un tournoi par tournoi, région et manche, vous pouvez créer une clé de partition GSI synthétique telle que TOURNAMENT\$1 WINTER2 024 \$1REGION \$1NA -EAST et une clé de tri synthétique telle que ROUND \$1SEMIFINALS \$1BRACKET \$1UPPER. Cette approche fonctionne, mais nécessite la concaténation de chaînes lors de l'écriture de données, l'analyse lors de la lecture et le remplissage de clés synthétiques sur tous les éléments existants si vous ajoutez le GSI à une table existante. Cela rend le code plus encombré et il est difficile de maintenir la sécurité des types sur les composants clés individuels.

Les clés à attributs multiples résolvent ce problème pour GSIs. Vous définissez votre clé de partition GSI à l'aide de plusieurs attributs existants tels que TournamentID et region. DynamoDB gère automatiquement la logique des clés composites, en les hachant ensemble pour la distribution des données. Vous écrivez des éléments en utilisant les attributs naturels de votre modèle de domaine, et le GSI les indexe automatiquement. Pas de concaténation, pas d'analyse syntaxique, pas de remblayage. Votre code reste propre, vos données restent saisies et vos requêtes restent simples. Cette approche est particulièrement utile lorsque vous disposez de données hiérarchiques avec des groupements d'attributs naturels (par exemple tournoi → région → manche, ou organisation → département → équipe).

## Exemple d'application
<a name="GSI.DesignPattern.MultiAttributeKeys.ApplicationExample"></a>

Ce guide explique comment créer un système de suivi des matchs de tournoi pour une plateforme d'e-sport. La plateforme doit interroger efficacement les matchs selon plusieurs critères : par tournoi et par région pour la gestion des brackets, par joueur pour l'historique des matchs et par date pour la programmation.

## Modèle de données
<a name="GSI.DesignPattern.MultiAttributeKeys.DataModel"></a>

Dans cette présentation, le système de suivi des matchs de tournoi prend en charge trois modèles d'accès principaux, chacun nécessitant une structure de clé différente :

**Modèle d'accès 1 :** recherchez une correspondance spécifique à l'aide de son identifiant unique
+ **Solution :** table de base avec `matchId` comme clé de partition

**Modèle d'accès 2 :** recherchez tous les matchs pour un tournoi et une région spécifiques, en filtrant éventuellement par tour, bracket ou match
+ **Solution :** index secondaire global avec clé de partition multi-attributs (`tournamentId`\$1`region`) et clé de tri multi-attributs (`round`\$1 \$1`bracket`) `matchId`
+ **Exemples de requêtes :** « Tous les WINTER2 024 matchs dans la région NA-EAST » ou « Tous les matchs des DEMI-FINALES dans la tranche SUPÉRIEURE pour 024/NA-EAST » WINTER2

**Modèle d'accès 3 : recherchez** l'historique des matchs d'un joueur, en filtrant éventuellement par plage de dates ou par tour de tournoi
+ **Solution :** index secondaire global avec clé de partition unique (`player1Id`) et clé de tri multi-attributs (`matchDate`\$1`round`)
+ **Exemples de requêtes :** « Tous les matchs du joueur 101 » ou « Les matchs du joueur 101 en janvier 2024 »

La principale différence entre les approches traditionnelles et les approches à attributs multiples apparaît clairement lorsque l'on examine la structure des articles :

**Approche traditionnelle de l'index secondaire global (clés concaténées) :**

```
// Manual concatenation required for GSI keys
const item = {
    matchId: 'match-001',                                          // Base table PK
    tournamentId: 'WINTER2024',
    region: 'NA-EAST',
    round: 'SEMIFINALS',
    bracket: 'UPPER',
    player1Id: '101',
    // Synthetic keys needed for GSI
    GSI_PK: `TOURNAMENT#${tournamentId}#REGION#${region}`,       // Must concatenate
    GSI_SK: `${round}#${bracket}#${matchId}`,                    // Must concatenate
    // ... other attributes
};
```

**Approche de l'index secondaire global à attributs multiples (clés natives) :**

```
// Use existing attributes directly - no concatenation needed
const item = {
    matchId: 'match-001',                                          // Base table PK
    tournamentId: 'WINTER2024',
    region: 'NA-EAST',
    round: 'SEMIFINALS',
    bracket: 'UPPER',
    player1Id: '101',
    matchDate: '2024-01-18',
    // No synthetic keys needed - GSI uses existing attributes directly
    // ... other attributes
};
```

Avec les clés à attributs multiples, vous pouvez écrire des éléments une seule fois avec des attributs de domaine naturels. DynamoDB les indexe automatiquement sur GSIs plusieurs sans nécessiter de clés concaténées synthétiques.

**Schéma de table de base :**
+ Clé de partition : `matchId` (1 attribut)

**Schéma d'index secondaire global (TournamentRegionIndex avec clés à attributs multiples) :**
+ Clé de partition :`tournamentId`, `region` (2 attributs)
+ Clé de tri : `round``bracket`,, `matchId` (3 attributs)

**Schéma d'index secondaire global (PlayerMatchHistoryIndex avec clés à attributs multiples) :**
+ Clé de partition : `player1Id` (1 attribut)
+ Clé de tri :`matchDate`, `round` (2 attributs)

### Table de base : TournamentMatches
<a name="GSI.DesignPattern.MultiAttributeKeys.BaseTable"></a>


| MatchID (PK) | ID du tournoi | region | round | crochet | ID du joueur 1 | ID du joueur 2 | Date du match | vainqueur | score | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| match-001 | WINTER2024 | NA-EAST | FINALES | CHAMPIONNAT | 101 | 103 | 20-01-2024 | 101 | 3-1 | 
| match-002 | WINTER2024 | NA-EAST | DEMI-FINALES | UPPER | 101 | 105 | 18-01-2024 | 101 | 3-2 | 
| match-003 | WINTER2024 | NA-EAST | DEMI-FINALES | UPPER | 103 | 107 | 18-01-2024 | 103 | 3-0 | 
| match-004 | WINTER2024 | NA-EAST | QUARTS DE FINALE | UPPER | 101 | 109 | 15-01-2024 | 101 | 3-1 | 
| match-005 | WINTER2024 | NA-WEST | FINALES | CHAMPIONNAT | 102 | 104 | 20-01-2024 | 102 | 3-2 | 
| match-006 | WINTER2024 | NA-WEST | DEMI-FINALES | UPPER | 102 | 106 | 18-01-2024 | 102 | 3-1 | 
| match-007 | SPRING2024 | NA-EAST | QUARTS DE FINALE | UPPER | 101 | 108 | 15/03/2024 | 101 | 3-0 | 
| match-008 | SPRING2024 | NA-EAST | QUARTS DE FINALE | LOWER | 103 | 110 | 15/03/2024 | 103 | 3-2 | 

### GSI : TournamentRegionIndex (clés à attributs multiples)
<a name="GSI.DesignPattern.MultiAttributeKeys.TournamentRegionIndexTable"></a>


| ID du tournoi (PK) | région (PK) | rond (SK) | support (SK) | MatchID (SK) | ID du joueur 1 | ID du joueur 2 | Date du match | vainqueur | score | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| WINTER2024 | NA-EAST | FINALES | CHAMPIONNAT | match-001 | 101 | 103 | 20-01-2024 | 101 | 3-1 | 
| WINTER2024 | NA-EAST | QUARTS DE FINALE | UPPER | match-004 | 101 | 109 | 15-01-2024 | 101 | 3-1 | 
| WINTER2024 | NA-EAST | DEMI-FINALES | UPPER | match-002 | 101 | 105 | 18-01-2024 | 101 | 3-2 | 
| WINTER2024 | NA-EAST | DEMI-FINALES | UPPER | match-003 | 103 | 107 | 18-01-2024 | 103 | 3-0 | 
| WINTER2024 | NA-WEST | FINALES | CHAMPIONNAT | match-005 | 102 | 104 | 20-01-2024 | 102 | 3-2 | 
| WINTER2024 | NA-WEST | DEMI-FINALES | UPPER | match-006 | 102 | 106 | 18-01-2024 | 102 | 3-1 | 
| SPRING2024 | NA-EAST | QUARTS DE FINALE | LOWER | match-008 | 103 | 110 | 15/03/2024 | 103 | 3-2 | 
| SPRING2024 | NA-EAST | QUARTS DE FINALE | UPPER | match-007 | 101 | 108 | 15/03/2024 | 101 | 3-0 | 

### GSI : PlayerMatchHistoryIndex (clés à attributs multiples)
<a name="GSI.DesignPattern.MultiAttributeKeys.PlayerMatchHistoryIndexTable"></a>


| ID du joueur 1 (PK) | MatchDate (SK) | rond (SK) | ID du tournoi | region | crochet | Identifiant du match | ID du joueur 2 | vainqueur | score | 
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 
| 101 | 15-01-2024 | QUARTS DE FINALE | WINTER2024 | NA-EAST | UPPER | match-004 | 109 | 101 | 3-1 | 
| 101 | 18-01-2024 | DEMI-FINALES | WINTER2024 | NA-EAST | UPPER | match-002 | 105 | 101 | 3-2 | 
| 101 | 20-01-2024 | FINALES | WINTER2024 | NA-EAST | CHAMPIONNAT | match-001 | 103 | 101 | 3-1 | 
| 101 | 15/03/2024 | QUARTS DE FINALE | SPRING2024 | NA-EAST | UPPER | match-007 | 108 | 101 | 3-0 | 
| 102 | 18-01-2024 | DEMI-FINALES | WINTER2024 | NA-WEST | UPPER | match-006 | 106 | 102 | 3-1 | 
| 102 | 20-01-2024 | FINALES | WINTER2024 | NA-WEST | CHAMPIONNAT | match-005 | 104 | 102 | 3-2 | 
| 103 | 18-01-2024 | DEMI-FINALES | WINTER2024 | NA-EAST | UPPER | match-003 | 107 | 103 | 3-0 | 
| 103 | 15/03/2024 | QUARTS DE FINALE | SPRING2024 | NA-EAST | LOWER | match-008 | 110 | 103 | 3-2 | 

## Prérequis
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites"></a>

Avant de commencer, assurez-vous de disposer des éléments suivants :

### Compte et autorisations
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.AWSAccount"></a>
+ Un AWS compte actif ([créez-en un ici](https://aws.amazon.com/free/) si nécessaire)
+ Autorisations IAM pour les opérations DynamoDB :
  + `dynamodb:CreateTable`
  + `dynamodb:DeleteTable`
  + `dynamodb:DescribeTable`
  + `dynamodb:PutItem`
  + `dynamodb:Query`
  + `dynamodb:BatchWriteItem`

**Note**  
**Note de sécurité :** Pour une utilisation en production, créez une politique IAM personnalisée avec uniquement les autorisations dont vous avez besoin. Pour ce didacticiel, vous pouvez utiliser la politique AWS gérée`AmazonDynamoDBFullAccessV2`.

### Environnement de développement
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.DevEnvironment"></a>
+ Node.js installé sur votre machine
+ AWS informations d'identification configurées à l'aide de l'une des méthodes suivantes :

**Option 1 : AWS CLI**

```
aws configure
```

**Option 2 : variables d’environnement**

```
export AWS_ACCESS_KEY_ID=your_access_key_here
export AWS_SECRET_ACCESS_KEY=your_secret_key_here
export AWS_DEFAULT_REGION=us-east-1
```

### Installation des packages obligatoires
<a name="GSI.DesignPattern.MultiAttributeKeys.Prerequisites.InstallPackages"></a>

```
npm install @aws-sdk/client-dynamodb @aws-sdk/lib-dynamodb
```

## Mise en œuvre
<a name="GSI.DesignPattern.MultiAttributeKeys.Implementation"></a>

### Étape 1 : Création d'une table à GSIs l'aide de clés à attributs multiples
<a name="GSI.DesignPattern.MultiAttributeKeys.CreateTable"></a>

Créez une table avec une structure de clés de base simple et utilisant GSIs des clés à attributs multiples.

#### Exemple de code
<a name="w2aac19c13c45c23b9c11b3b5b1"></a>

```
import { DynamoDBClient, CreateTableCommand } from "@aws-sdk/client-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });

const response = await client.send(new CreateTableCommand({
    TableName: 'TournamentMatches',
    
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'matchId', KeyType: 'HASH' }              // Simple PK
    ],
    
    AttributeDefinitions: [
        { AttributeName: 'matchId', AttributeType: 'S' },
        { AttributeName: 'tournamentId', AttributeType: 'S' },
        { AttributeName: 'region', AttributeType: 'S' },
        { AttributeName: 'round', AttributeType: 'S' },
        { AttributeName: 'bracket', AttributeType: 'S' },
        { AttributeName: 'player1Id', AttributeType: 'S' },
        { AttributeName: 'matchDate', AttributeType: 'S' }
    ],
    
    // GSIs with multi-attribute keys
    GlobalSecondaryIndexes: [
        {
            IndexName: 'TournamentRegionIndex',
            KeySchema: [
                { AttributeName: 'tournamentId', KeyType: 'HASH' },    // GSI PK attribute 1
                { AttributeName: 'region', KeyType: 'HASH' },          // GSI PK attribute 2
                { AttributeName: 'round', KeyType: 'RANGE' },          // GSI SK attribute 1
                { AttributeName: 'bracket', KeyType: 'RANGE' },        // GSI SK attribute 2
                { AttributeName: 'matchId', KeyType: 'RANGE' }         // GSI SK attribute 3
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'PlayerMatchHistoryIndex',
            KeySchema: [
                { AttributeName: 'player1Id', KeyType: 'HASH' },       // GSI PK
                { AttributeName: 'matchDate', KeyType: 'RANGE' },      // GSI SK attribute 1
                { AttributeName: 'round', KeyType: 'RANGE' }           // GSI SK attribute 2
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    
    BillingMode: 'PAY_PER_REQUEST'
}));

console.log("Table with multi-attribute GSI keys created successfully");
```

**Principales décisions de conception :**

**Table de base :** La table de base utilise une clé de `matchId` partition simple pour les recherches par correspondance directe, ce qui permet de maintenir la structure de la table de base simple tout en GSIs fournissant des modèles de requête complexes.

**TournamentRegionIndex Index secondaire global : L'index** secondaire `TournamentRegionIndex` mondial utilise `tournamentId` \$1 `region` comme clé de partition à attributs multiples, ce qui crée une isolation entre les régions de tournois, les données étant distribuées par le hachage des deux attributs combinés, ce qui permet d'effectuer des requêtes efficaces dans un contexte de région de tournoi spécifique. La clé de tri à attributs multiples (`round`\$1 `bracket` \$1`matchId`) permet un tri hiérarchique qui prend en charge les requêtes à tous les niveaux de la hiérarchie avec un ordre naturel, du général (rond) au spécifique (identifiant de correspondance).

**PlayerMatchHistoryIndex Index secondaire mondial : L'index** secondaire `PlayerMatchHistoryIndex` mondial réorganise les données par joueur en les utilisant `player1Id` comme clé de partition, ce qui permet d'effectuer des requêtes entre tournois pour un joueur spécifique. La clé de tri à attributs multiples (`matchDate`\$1`round`) fournit un ordre chronologique avec la possibilité de filtrer par plages de dates ou par tours de tournoi spécifiques.

### Étape 2 : Insérer des données avec des attributs natifs
<a name="GSI.DesignPattern.MultiAttributeKeys.InsertData"></a>

Ajoutez les données des matchs du tournoi à l'aide d'attributs naturels. Le GSI indexera automatiquement ces attributs sans nécessiter de clés synthétiques.

#### Exemple de code
<a name="w2aac19c13c45c23b9c11b5b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, PutCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Tournament match data - no synthetic keys needed for GSIs
const matches = [
    // Winter 2024 Tournament, NA-EAST region
    {
        matchId: 'match-001',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'FINALS',
        bracket: 'CHAMPIONSHIP',
        player1Id: '101',
        player2Id: '103',
        matchDate: '2024-01-20',
        winner: '101',
        score: '3-1'
    },
    {
        matchId: 'match-002',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '105',
        matchDate: '2024-01-18',
        winner: '101',
        score: '3-2'
    },
    {
        matchId: 'match-003',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '103',
        player2Id: '107',
        matchDate: '2024-01-18',
        winner: '103',
        score: '3-0'
    },
    {
        matchId: 'match-004',
        tournamentId: 'WINTER2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '109',
        matchDate: '2024-01-15',
        winner: '101',
        score: '3-1'
    },
    
    // Winter 2024 Tournament, NA-WEST region
    {
        matchId: 'match-005',
        tournamentId: 'WINTER2024',
        region: 'NA-WEST',
        round: 'FINALS',
        bracket: 'CHAMPIONSHIP',
        player1Id: '102',
        player2Id: '104',
        matchDate: '2024-01-20',
        winner: '102',
        score: '3-2'
    },
    {
        matchId: 'match-006',
        tournamentId: 'WINTER2024',
        region: 'NA-WEST',
        round: 'SEMIFINALS',
        bracket: 'UPPER',
        player1Id: '102',
        player2Id: '106',
        matchDate: '2024-01-18',
        winner: '102',
        score: '3-1'
    },
    
    // Spring 2024 Tournament, NA-EAST region
    {
        matchId: 'match-007',
        tournamentId: 'SPRING2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'UPPER',
        player1Id: '101',
        player2Id: '108',
        matchDate: '2024-03-15',
        winner: '101',
        score: '3-0'
    },
    {
        matchId: 'match-008',
        tournamentId: 'SPRING2024',
        region: 'NA-EAST',
        round: 'QUARTERFINALS',
        bracket: 'LOWER',
        player1Id: '103',
        player2Id: '110',
        matchDate: '2024-03-15',
        winner: '103',
        score: '3-2'
    }
];

// Insert all matches
for (const match of matches) {
    await docClient.send(new PutCommand({
        TableName: 'TournamentMatches',
        Item: match
    }));
    
    console.log(`Added: ${match.matchId} - ${match.tournamentId}/${match.region} - ${match.round} ${match.bracket}`);
}

console.log(`\nInserted ${matches.length} tournament matches`);
console.log("No synthetic keys created - GSIs use native attributes automatically");
```

**Structure des données expliquée :**

**Utilisation naturelle des attributs :** chaque attribut représente un véritable concept de tournoi sans aucune concaténation ou analyse de chaînes requise, fournissant ainsi un mappage direct avec le modèle de domaine.

Indexation **automatique de l'index secondaire global : Indexation** GSIs automatique des éléments à l'aide des attributs existants (`tournamentId``region`,`round`,`bracket`, `matchId` pour TournamentRegionIndex et `player1Id``matchDate`, `round` pour PlayerMatchHistoryIndex) sans nécessiter de clés concaténées synthétiques.

**Aucun remplissage supplémentaire n'est nécessaire :** lorsque vous ajoutez un nouvel index secondaire global avec des clés à attributs multiples à une table existante, DynamoDB indexe automatiquement tous les éléments existants à l'aide de leurs attributs naturels. Il n'est pas nécessaire de mettre à jour les éléments à l'aide de clés synthétiques.

### Étape 3 : Interrogez TournamentRegionIndex l'index secondaire global avec tous les attributs de clé de partition
<a name="GSI.DesignPattern.MultiAttributeKeys.QueryAllPartitionKeys"></a>

Cet exemple interroge l'index secondaire TournamentRegionIndex global qui possède une clé de partition à attributs multiples (`tournamentId`\$1`region`). Tous les attributs de clé de partition doivent être spécifiés avec des conditions d'égalité dans les requêtes. Vous ne pouvez pas effectuer de requête `tournamentId` uniquement ou utiliser des opérateurs d'inégalité sur les attributs de clé de partition.

#### Exemple de code
<a name="w2aac19c13c45c23b9c11b7b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query GSI: All matches for WINTER2024 tournament in NA-EAST region
const response = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region',
    ExpressionAttributeNames: {
        '#region': 'region',  // 'region' is a reserved keyword
        '#tournament': 'tournament'
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST'
    }
}));

console.log(`Found ${response.Items.length} matches for WINTER2024/NA-EAST:\n`);
response.Items.forEach(match => {
    console.log(`  ${match.round} | ${match.bracket} | ${match.matchId}`);
    console.log(`    Players: ${match.player1Id} vs ${match.player2Id}`);
    console.log(`    Winner: ${match.winner}, Score: ${match.score}\n`);
});
```

**Résultat attendu :**

```
Found 4 matches for WINTER2024/NA-EAST:

  FINALS | CHAMPIONSHIP | match-001
    Players: 101 vs 103
    Winner: 101, Score: 3-1

  QUARTERFINALS | UPPER | match-004
    Players: 101 vs 109
    Winner: 101, Score: 3-1

  SEMIFINALS | UPPER | match-002
    Players: 101 vs 105
    Winner: 101, Score: 3-2

  SEMIFINALS | UPPER | match-003
    Players: 103 vs 107
    Winner: 103, Score: 3-0
```

**Requêtes non valides :**

```
// Missing region attribute
KeyConditionExpression: 'tournamentId = :tournament'

// Using inequality on partition key attribute
KeyConditionExpression: 'tournamentId = :tournament AND #region > :region'
```

**Performances :** les clés de partition à attributs multiples sont hachées ensemble, offrant les mêmes performances de recherche O (1) que les clés à attribut unique.

### Étape 4 : demander les clés de tri de l'index secondaire global left-to-right
<a name="GSI.DesignPattern.MultiAttributeKeys.QuerySortKeysLeftToRight"></a>

Les attributs clés de tri doivent être interrogés left-to-right dans l'ordre dans lequel ils sont définis dans l'index secondaire global. Cet exemple montre comment interroger les différents TournamentRegionIndex niveaux hiérarchiques : filtrage par simple`round`, par `round` \$1 `bracket` ou par les trois attributs clés de tri. Vous ne pouvez pas ignorer les attributs au milieu. Par exemple, vous ne pouvez pas effectuer d'interrogation par `round` et `matchId` pendant les sauts. `bracket`

#### Exemple de code
<a name="w2aac19c13c45c23b9c11b9b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: Filter by first sort key attribute (round)
console.log("Query 1: All SEMIFINALS matches");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS'
    }
}));
console.log(`  Found ${query1.Items.length} matches\n`);

// Query 2: Filter by first two sort key attributes (round + bracket)
console.log("Query 2: SEMIFINALS UPPER bracket matches");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND bracket = :bracket',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':bracket': 'UPPER'
    }
}));
console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Filter by all three sort key attributes (round + bracket + matchId)
console.log("Query 3: Specific match in SEMIFINALS UPPER bracket");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND bracket = :bracket AND matchId = :matchId',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':bracket': 'UPPER',
        ':matchId': 'match-002'
    }
}));
console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: INVALID - skipping round
console.log("Query 4: Attempting to skip first sort key attribute (WILL FAIL)");
try {
    const query4 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND bracket = :bracket',
        ExpressionAttributeNames: {
            '#region': 'region'  // 'region' is a reserved keyword
        },
        ExpressionAttributeValues: {
            ':tournament': 'WINTER2024',
            ':region': 'NA-EAST',
            ':bracket': 'UPPER'
        }
    }));
} catch (error) {
    console.log(`  Error: ${error.message}`);
    console.log(`  Cannot skip sort key attributes - must query left-to-right\n`);
}
```

**Résultat attendu :**

```
Query 1: All SEMIFINALS matches
  Found 2 matches

Query 2: SEMIFINALS UPPER bracket matches
  Found 2 matches

Query 3: Specific match in SEMIFINALS UPPER bracket
  Found 1 matches

Query 4: Attempting to skip first sort key attribute (WILL FAIL)
  Error: Query key condition not supported
  Cannot skip sort key attributes - must query left-to-right
```

**Left-to-right règles de requête :** vous devez interroger les attributs dans l'ordre de gauche à droite, sans en sauter aucun.

**Modèles valides :**
+ Premier attribut uniquement : `round = 'SEMIFINALS'`
+ Les deux premiers attributs : `round = 'SEMIFINALS' AND bracket = 'UPPER'`
+ Les trois attributs : `round = 'SEMIFINALS' AND bracket = 'UPPER' AND matchId = 'match-002'`

**Modèles non valides :**
+ Ignorer le premier attribut : `bracket = 'UPPER'` (saute le tour)
+ Interrogation hors ordre : `matchId = 'match-002' AND round = 'SEMIFINALS'`
+ Laisser des espaces : `round = 'SEMIFINALS' AND matchId = 'match-002'` (ne tient pas compte du crochet)

**Note**  
**Conseil de conception :** Triez les attributs clés du plus général au plus spécifique afin d'optimiser la flexibilité des requêtes.

### Étape 5 : Utiliser les conditions d'inégalité sur les clés de tri de l'indice secondaire global
<a name="GSI.DesignPattern.MultiAttributeKeys.InequalityConditions"></a>

Les conditions d'inégalité doivent être la dernière condition de votre requête. Cet exemple montre comment utiliser les opérateurs de comparaison (`>=`,`BETWEEN`) et la correspondance de préfixes (`begins_with()`) sur les attributs clés de tri. Une fois que vous avez utilisé un opérateur d'inégalité, vous ne pouvez pas ajouter de conditions clés de tri supplémentaires après celui-ci. L'inégalité doit être la condition finale de votre expression de condition clé.

#### Exemple de code
<a name="w2aac19c13c45c23b9c11c11b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: Round comparison (inequality on first sort key attribute)
console.log("Query 1: Matches from QUARTERFINALS onwards");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round >= :round',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'QUARTERFINALS'
    }
}));
console.log(`  Found ${query1.Items.length} matches\n`);

// Query 2: Round range with BETWEEN
console.log("Query 2: Matches between QUARTERFINALS and SEMIFINALS");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round BETWEEN :start AND :end',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':start': 'QUARTERFINALS',
        ':end': 'SEMIFINALS'
    }
}));
console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Prefix matching with begins_with (treated as inequality)
console.log("Query 3: Matches in brackets starting with 'U'");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'TournamentRegionIndex',
    KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round = :round AND begins_with(bracket, :prefix)',
    ExpressionAttributeNames: {
        '#region': 'region'  // 'region' is a reserved keyword
    },
    ExpressionAttributeValues: {
        ':tournament': 'WINTER2024',
        ':region': 'NA-EAST',
        ':round': 'SEMIFINALS',
        ':prefix': 'U'
    }
}));
console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: INVALID - condition after inequality
console.log("Query 4: Attempting condition after inequality (WILL FAIL)");
try {
    const query4 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region AND round > :round AND bracket = :bracket',
        ExpressionAttributeNames: {
            '#region': 'region'  // 'region' is a reserved keyword
        },
        ExpressionAttributeValues: {
            ':tournament': 'WINTER2024',
            ':region': 'NA-EAST',
            ':round': 'QUARTERFINALS',
            ':bracket': 'UPPER'
        }
    }));
} catch (error) {
    console.log(`  Error: ${error.message}`);
    console.log(`  Cannot add conditions after inequality - it must be last\n`);
}
```

**Règles relatives aux opérateurs d'inégalité :** vous pouvez utiliser des opérateurs de comparaison (`>``>=`,`<`,,`<=`) `BETWEEN` pour les requêtes de plage et `begins_with()` pour la correspondance de préfixes. L'inégalité doit être la dernière condition de votre requête.

**Modèles valides :**
+ Conditions d'égalité suivies d'inégalités : `round = 'SEMIFINALS' AND bracket = 'UPPER' AND matchId > 'match-001'`
+ Inégalité sur le premier attribut : `round BETWEEN 'QUARTERFINALS' AND 'SEMIFINALS'`
+ Correspondance du préfixe comme condition finale : `round = 'SEMIFINALS' AND begins_with(bracket, 'U')`

**Modèles non valides :**
+ Ajouter des conditions après une inégalité : `round > 'QUARTERFINALS' AND bracket = 'UPPER'`
+ En utilisant de multiples inégalités : `round > 'QUARTERFINALS' AND bracket > 'L'`

**Important**  
`begins_with()`est traitée comme une condition d'inégalité, de sorte qu'aucune condition clé de tri supplémentaire ne peut la suivre.

### Étape 6 : Interroger l'index secondaire PlayerMatchHistoryIndex global avec une clé de tri à attributs multiples
<a name="GSI.DesignPattern.MultiAttributeKeys.QueryPlayerHistory"></a>

Cet exemple interroge celui PlayerMatchHistoryIndex qui possède une clé de partition unique (`player1Id`) et une clé de tri multi-attributs (`matchDate`\$1`round`). Cela permet d'effectuer une analyse entre tournois en interrogeant tous les matchs pour un joueur spécifique sans connaître le tournoi, IDs alors que le tableau de base nécessiterait des requêtes distinctes par combinaison tournien-région.

#### Exemple de code
<a name="w2aac19c13c45c23b9c11c13b5b1"></a>

```
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, QueryCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

// Query 1: All matches for Player 101 across all tournaments
console.log("Query 1: All matches for Player 101");
const query1 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player',
    ExpressionAttributeValues: {
        ':player': '101'
    }
}));

console.log(`  Found ${query1.Items.length} matches for Player 101:`);
query1.Items.forEach(match => {
    console.log(`    ${match.tournamentId}/${match.region} - ${match.matchDate} - ${match.round}`);
});
console.log();

// Query 2: Player 101 matches on specific date
console.log("Query 2: Player 101 matches on 2024-01-18");
const query2 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate = :date',
    ExpressionAttributeValues: {
        ':player': '101',
        ':date': '2024-01-18'
    }
}));

console.log(`  Found ${query2.Items.length} matches\n`);

// Query 3: Player 101 SEMIFINALS matches on specific date
console.log("Query 3: Player 101 SEMIFINALS matches on 2024-01-18");
const query3 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate = :date AND round = :round',
    ExpressionAttributeValues: {
        ':player': '101',
        ':date': '2024-01-18',
        ':round': 'SEMIFINALS'
    }
}));

console.log(`  Found ${query3.Items.length} matches\n`);

// Query 4: Player 101 matches in date range
console.log("Query 4: Player 101 matches in January 2024");
const query4 = await docClient.send(new QueryCommand({
    TableName: 'TournamentMatches',
    IndexName: 'PlayerMatchHistoryIndex',
    KeyConditionExpression: 'player1Id = :player AND matchDate BETWEEN :start AND :end',
    ExpressionAttributeValues: {
        ':player': '101',
        ':start': '2024-01-01',
        ':end': '2024-01-31'
    }
}));

console.log(`  Found ${query4.Items.length} matches\n`);
```

## Variations de motifs
<a name="GSI.DesignPattern.MultiAttributeKeys.PatternVariations"></a>

### Données chronologiques avec clés à attributs multiples
<a name="GSI.DesignPattern.MultiAttributeKeys.TimeSeries"></a>

Optimisation pour les requêtes de séries chronologiques avec des attributs temporels hiérarchiques

#### Exemple de code
<a name="w2aac19c13c45c23b9c13b3b5b1"></a>

```
{
    TableName: 'IoTReadings',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'readingId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'readingId', AttributeType: 'S' },
        { AttributeName: 'deviceId', AttributeType: 'S' },
        { AttributeName: 'locationId', AttributeType: 'S' },
        { AttributeName: 'year', AttributeType: 'S' },
        { AttributeName: 'month', AttributeType: 'S' },
        { AttributeName: 'day', AttributeType: 'S' },
        { AttributeName: 'timestamp', AttributeType: 'S' }
    ],
    // GSI with multi-attribute keys for time-series queries
    GlobalSecondaryIndexes: [{
        IndexName: 'DeviceLocationTimeIndex',
        KeySchema: [
            { AttributeName: 'deviceId', KeyType: 'HASH' },
            { AttributeName: 'locationId', KeyType: 'HASH' },
            { AttributeName: 'year', KeyType: 'RANGE' },
            { AttributeName: 'month', KeyType: 'RANGE' },
            { AttributeName: 'day', KeyType: 'RANGE' },
            { AttributeName: 'timestamp', KeyType: 'RANGE' }
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query patterns enabled via GSI:
// - All readings for device in location
// - Readings for specific year
// - Readings for specific month in year
// - Readings for specific day
// - Readings in time range
```

**Avantages :** La hiérarchie temporelle naturelle (année → mois → jour → horodatage) permet des requêtes efficaces à tout moment avec une granularité sans analyse ou manipulation de dates. L'index secondaire global indexe automatiquement toutes les lectures en utilisant leurs attributs temporels naturels.

### Commandes de commerce électronique avec clés à attributs multiples
<a name="GSI.DesignPattern.MultiAttributeKeys.ECommerce"></a>

Suivez les commandes avec plusieurs dimensions

#### Exemple de code
<a name="w2aac19c13c45c23b9c13b5b5b1"></a>

```
{
    TableName: 'Orders',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'orderId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'orderId', AttributeType: 'S' },
        { AttributeName: 'sellerId', AttributeType: 'S' },
        { AttributeName: 'region', AttributeType: 'S' },
        { AttributeName: 'orderDate', AttributeType: 'S' },
        { AttributeName: 'category', AttributeType: 'S' },
        { AttributeName: 'customerId', AttributeType: 'S' },
        { AttributeName: 'orderStatus', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'SellerRegionIndex',
            KeySchema: [
                { AttributeName: 'sellerId', KeyType: 'HASH' },
                { AttributeName: 'region', KeyType: 'HASH' },
                { AttributeName: 'orderDate', KeyType: 'RANGE' },
                { AttributeName: 'category', KeyType: 'RANGE' },
                { AttributeName: 'orderId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'CustomerOrdersIndex',
            KeySchema: [
                { AttributeName: 'customerId', KeyType: 'HASH' },
                { AttributeName: 'orderDate', KeyType: 'RANGE' },
                { AttributeName: 'orderStatus', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// SellerRegionIndex GSI queries:
// - Orders by seller and region
// - Orders by seller, region, and date
// - Orders by seller, region, date, and category

// CustomerOrdersIndex GSI queries:
// - Customer's orders
// - Customer's orders by date
// - Customer's orders by date and status
```

### Données d'organisation hiérarchiques
<a name="GSI.DesignPattern.MultiAttributeKeys.Hierarchical"></a>

Hiérarchies organisationnelles modélisées

#### Exemple de code
<a name="w2aac19c13c45c23b9c13b7b5b1"></a>

```
{
    TableName: 'Employees',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'employeeId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'employeeId', AttributeType: 'S' },
        { AttributeName: 'companyId', AttributeType: 'S' },
        { AttributeName: 'divisionId', AttributeType: 'S' },
        { AttributeName: 'departmentId', AttributeType: 'S' },
        { AttributeName: 'teamId', AttributeType: 'S' },
        { AttributeName: 'skillCategory', AttributeType: 'S' },
        { AttributeName: 'skillLevel', AttributeType: 'S' },
        { AttributeName: 'yearsExperience', AttributeType: 'N' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'OrganizationIndex',
            KeySchema: [
                { AttributeName: 'companyId', KeyType: 'HASH' },
                { AttributeName: 'divisionId', KeyType: 'HASH' },
                { AttributeName: 'departmentId', KeyType: 'RANGE' },
                { AttributeName: 'teamId', KeyType: 'RANGE' },
                { AttributeName: 'employeeId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'SkillsIndex',
            KeySchema: [
                { AttributeName: 'skillCategory', KeyType: 'HASH' },
                { AttributeName: 'skillLevel', KeyType: 'RANGE' },
                { AttributeName: 'yearsExperience', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'INCLUDE', NonKeyAttributes: ['employeeId', 'name'] }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// OrganizationIndex GSI query patterns:
// - All employees in company/division
// - Employees in specific department
// - Employees in specific team

// SkillsIndex GSI query patterns:
// - Employees by skill and experience level
```

### Clés à attributs multiples éparses
<a name="GSI.DesignPattern.MultiAttributeKeys.Sparse"></a>

Combinez des clés à attributs multiples pour créer un GSI clairsemé

#### Exemple de code
<a name="w2aac19c13c45c23b9c13b9b5b1"></a>

```
{
    TableName: 'Products',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'productId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'productId', AttributeType: 'S' },
        { AttributeName: 'categoryId', AttributeType: 'S' },
        { AttributeName: 'subcategoryId', AttributeType: 'S' },
        { AttributeName: 'averageRating', AttributeType: 'N' },
        { AttributeName: 'reviewCount', AttributeType: 'N' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'CategoryIndex',
            KeySchema: [
                { AttributeName: 'categoryId', KeyType: 'HASH' },
                { AttributeName: 'subcategoryId', KeyType: 'HASH' },
                { AttributeName: 'productId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'ReviewedProductsIndex',
            KeySchema: [
                { AttributeName: 'categoryId', KeyType: 'HASH' },
                { AttributeName: 'averageRating', KeyType: 'RANGE' },  // Optional attribute
                { AttributeName: 'reviewCount', KeyType: 'RANGE' }     // Optional attribute
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// Only products with reviews appear in ReviewedProductsIndex GSI
// Automatic filtering without application logic
// Multi-attribute sort key enables rating and count queries
```

### SaaS multi-tenant
<a name="GSI.DesignPattern.MultiAttributeKeys.SaaS"></a>

Plateforme SaaS multi-locataires avec isolation du client

#### Exemple de code
<a name="w2aac19c13c45c23b9c13c11b5b1"></a>

```
// Table design
{
    TableName: 'SaasData',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'resourceId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'resourceId', AttributeType: 'S' },
        { AttributeName: 'tenantId', AttributeType: 'S' },
        { AttributeName: 'customerId', AttributeType: 'S' },
        { AttributeName: 'resourceType', AttributeType: 'S' }
    ],
    // GSI with multi-attribute keys for tenant-customer isolation
    GlobalSecondaryIndexes: [{
        IndexName: 'TenantCustomerIndex',
        KeySchema: [
            { AttributeName: 'tenantId', KeyType: 'HASH' },
            { AttributeName: 'customerId', KeyType: 'HASH' },
            { AttributeName: 'resourceType', KeyType: 'RANGE' },
            { AttributeName: 'resourceId', KeyType: 'RANGE' }
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query GSI: All resources for tenant T001, customer C001
const resources = await docClient.send(new QueryCommand({
    TableName: 'SaasData',
    IndexName: 'TenantCustomerIndex',
    KeyConditionExpression: 'tenantId = :tenant AND customerId = :customer',
    ExpressionAttributeValues: {
        ':tenant': 'T001',
        ':customer': 'C001'
    }
}));

// Query GSI: Specific resource type for tenant/customer
const documents = await docClient.send(new QueryCommand({
    TableName: 'SaasData',
    IndexName: 'TenantCustomerIndex',
    KeyConditionExpression: 'tenantId = :tenant AND customerId = :customer AND resourceType = :type',
    ExpressionAttributeValues: {
        ':tenant': 'T001',
        ':customer': 'C001',
        ':type': 'document'
    }
}));
```

**Avantages :** requêtes efficaces dans le contexte locataire-client et organisation naturelle des données.

### Transactions financières
<a name="GSI.DesignPattern.MultiAttributeKeys.Financial"></a>

Le système bancaire suit les transactions du compte en utilisant GSIs

#### Exemple de code
<a name="w2aac19c13c45c23b9c13c13b5b1"></a>

```
// Table design
{
    TableName: 'BankTransactions',
    // Base table: Simple partition key
    KeySchema: [
        { AttributeName: 'transactionId', KeyType: 'HASH' }
    ],
    AttributeDefinitions: [
        { AttributeName: 'transactionId', AttributeType: 'S' },
        { AttributeName: 'accountId', AttributeType: 'S' },
        { AttributeName: 'year', AttributeType: 'S' },
        { AttributeName: 'month', AttributeType: 'S' },
        { AttributeName: 'day', AttributeType: 'S' },
        { AttributeName: 'transactionType', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [
        {
            IndexName: 'AccountTimeIndex',
            KeySchema: [
                { AttributeName: 'accountId', KeyType: 'HASH' },
                { AttributeName: 'year', KeyType: 'RANGE' },
                { AttributeName: 'month', KeyType: 'RANGE' },
                { AttributeName: 'day', KeyType: 'RANGE' },
                { AttributeName: 'transactionId', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        },
        {
            IndexName: 'TransactionTypeIndex',
            KeySchema: [
                { AttributeName: 'accountId', KeyType: 'HASH' },
                { AttributeName: 'transactionType', KeyType: 'RANGE' },
                { AttributeName: 'year', KeyType: 'RANGE' },
                { AttributeName: 'month', KeyType: 'RANGE' }
            ],
            Projection: { ProjectionType: 'ALL' }
        }
    ],
    BillingMode: 'PAY_PER_REQUEST'
}

// Query AccountTimeIndex GSI: All transactions for account in 2023
const yearTransactions = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'AccountTimeIndex',
    KeyConditionExpression: 'accountId = :account AND #year = :year',
    ExpressionAttributeNames: { '#year': 'year' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':year': '2023'
    }
}));

// Query AccountTimeIndex GSI: Transactions in specific month
const monthTransactions = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'AccountTimeIndex',
    KeyConditionExpression: 'accountId = :account AND #year = :year AND #month = :month',
    ExpressionAttributeNames: { '#year': 'year', '#month': 'month' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':year': '2023',
        ':month': '11'
    }
}));

// Query TransactionTypeIndex GSI: Deposits in 2023
const deposits = await docClient.send(new QueryCommand({
    TableName: 'BankTransactions',
    IndexName: 'TransactionTypeIndex',
    KeyConditionExpression: 'accountId = :account AND transactionType = :type AND #year = :year',
    ExpressionAttributeNames: { '#year': 'year' },
    ExpressionAttributeValues: {
        ':account': 'ACC-12345',
        ':type': 'deposit',
        ':year': '2023'
    }
}));
```

## Exemple complet
<a name="GSI.DesignPattern.MultiAttributeKeys.CompleteExample"></a>

L'exemple suivant illustre les clés à attributs multiples, de la configuration au nettoyage :

### Exemple de code
<a name="w2aac19c13c45c23b9c15b5b1"></a>

```
import { 
    DynamoDBClient, 
    CreateTableCommand, 
    DeleteTableCommand, 
    waitUntilTableExists 
} from "@aws-sdk/client-dynamodb";
import { 
    DynamoDBDocumentClient, 
    PutCommand, 
    QueryCommand 
} from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: 'us-west-2' });
const docClient = DynamoDBDocumentClient.from(client);

async function multiAttributeKeysDemo() {
    console.log("Starting Multi-Attribute GSI Keys Demo\n");
    
    // Step 1: Create table with GSIs using multi-attribute keys
    console.log("1. Creating table with multi-attribute GSI keys...");
    await client.send(new CreateTableCommand({
        TableName: 'TournamentMatches',
        KeySchema: [
            { AttributeName: 'matchId', KeyType: 'HASH' }
        ],
        AttributeDefinitions: [
            { AttributeName: 'matchId', AttributeType: 'S' },
            { AttributeName: 'tournamentId', AttributeType: 'S' },
            { AttributeName: 'region', AttributeType: 'S' },
            { AttributeName: 'round', AttributeType: 'S' },
            { AttributeName: 'bracket', AttributeType: 'S' },
            { AttributeName: 'player1Id', AttributeType: 'S' },
            { AttributeName: 'matchDate', AttributeType: 'S' }
        ],
        GlobalSecondaryIndexes: [
            {
                IndexName: 'TournamentRegionIndex',
                KeySchema: [
                    { AttributeName: 'tournamentId', KeyType: 'HASH' },
                    { AttributeName: 'region', KeyType: 'HASH' },
                    { AttributeName: 'round', KeyType: 'RANGE' },
                    { AttributeName: 'bracket', KeyType: 'RANGE' },
                    { AttributeName: 'matchId', KeyType: 'RANGE' }
                ],
                Projection: { ProjectionType: 'ALL' }
            },
            {
                IndexName: 'PlayerMatchHistoryIndex',
                KeySchema: [
                    { AttributeName: 'player1Id', KeyType: 'HASH' },
                    { AttributeName: 'matchDate', KeyType: 'RANGE' },
                    { AttributeName: 'round', KeyType: 'RANGE' }
                ],
                Projection: { ProjectionType: 'ALL' }
            }
        ],
        BillingMode: 'PAY_PER_REQUEST'
    }));
    
    await waitUntilTableExists({ client, maxWaitTime: 120 }, { TableName: 'TournamentMatches' });
    console.log("Table created\n");
    
    // Step 2: Insert tournament matches
    console.log("2. Inserting tournament matches...");
    const matches = [
        { matchId: 'match-001', tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'FINALS', bracket: 'CHAMPIONSHIP', player1Id: '101', player2Id: '103', matchDate: '2024-01-20', winner: '101', score: '3-1' },
        { matchId: 'match-002', tournamentId: 'WINTER2024', region: 'NA-EAST', round: 'SEMIFINALS', bracket: 'UPPER', player1Id: '101', player2Id: '105', matchDate: '2024-01-18', winner: '101', score: '3-2' },
        { matchId: 'match-003', tournamentId: 'WINTER2024', region: 'NA-WEST', round: 'FINALS', bracket: 'CHAMPIONSHIP', player1Id: '102', player2Id: '104', matchDate: '2024-01-20', winner: '102', score: '3-2' },
        { matchId: 'match-004', tournamentId: 'SPRING2024', region: 'NA-EAST', round: 'QUARTERFINALS', bracket: 'UPPER', player1Id: '101', player2Id: '108', matchDate: '2024-03-15', winner: '101', score: '3-0' }
    ];
    
    for (const match of matches) {
        await docClient.send(new PutCommand({ TableName: 'TournamentMatches', Item: match }));
    }
    console.log(`Inserted ${matches.length} tournament matches\n`);
    
    // Step 3: Query GSI with multi-attribute partition key
    console.log("3. Query TournamentRegionIndex GSI: WINTER2024/NA-EAST matches");
    const gsiQuery1 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'TournamentRegionIndex',
        KeyConditionExpression: 'tournamentId = :tournament AND #region = :region',
        ExpressionAttributeNames: { '#region': 'region' },
        ExpressionAttributeValues: { ':tournament': 'WINTER2024', ':region': 'NA-EAST' }
    }));
    
    console.log(`  Found ${gsiQuery1.Items.length} matches:`);
    gsiQuery1.Items.forEach(match => {
        console.log(`    ${match.round} - ${match.bracket} - ${match.winner} won`);
    });
    
    // Step 4: Query GSI with multi-attribute sort key
    console.log("\n4. Query PlayerMatchHistoryIndex GSI: All matches for Player 101");
    const gsiQuery2 = await docClient.send(new QueryCommand({
        TableName: 'TournamentMatches',
        IndexName: 'PlayerMatchHistoryIndex',
        KeyConditionExpression: 'player1Id = :player',
        ExpressionAttributeValues: { ':player': '101' }
    }));
    
    console.log(`  Found ${gsiQuery2.Items.length} matches for Player 101:`);
    gsiQuery2.Items.forEach(match => {
        console.log(`    ${match.tournamentId}/${match.region} - ${match.matchDate} - ${match.round}`);
    });
    
    console.log("\nDemo complete");
    console.log("No synthetic keys needed - GSIs use native attributes automatically");
}

async function cleanup() {
    console.log("Deleting table...");
    await client.send(new DeleteTableCommand({ TableName: 'TournamentMatches' }));
    console.log("Table deleted");
}

// Run demo
multiAttributeKeysDemo().catch(console.error);

// Uncomment to cleanup:
// cleanup().catch(console.error);
```

**Échafaudage de code minimal**

### Exemple de code
<a name="w2aac19c13c45c23b9c15b9b1"></a>

```
// 1. Create table with GSI using multi-attribute keys
await client.send(new CreateTableCommand({
    TableName: 'MyTable',
    KeySchema: [
        { AttributeName: 'id', KeyType: 'HASH' }        // Simple base table PK
    ],
    AttributeDefinitions: [
        { AttributeName: 'id', AttributeType: 'S' },
        { AttributeName: 'attr1', AttributeType: 'S' },
        { AttributeName: 'attr2', AttributeType: 'S' },
        { AttributeName: 'attr3', AttributeType: 'S' },
        { AttributeName: 'attr4', AttributeType: 'S' }
    ],
    GlobalSecondaryIndexes: [{
        IndexName: 'MyGSI',
        KeySchema: [
            { AttributeName: 'attr1', KeyType: 'HASH' },    // GSI PK attribute 1
            { AttributeName: 'attr2', KeyType: 'HASH' },    // GSI PK attribute 2
            { AttributeName: 'attr3', KeyType: 'RANGE' },   // GSI SK attribute 1
            { AttributeName: 'attr4', KeyType: 'RANGE' }    // GSI SK attribute 2
        ],
        Projection: { ProjectionType: 'ALL' }
    }],
    BillingMode: 'PAY_PER_REQUEST'
}));

// 2. Insert items with native attributes (no concatenation needed for GSI)
await docClient.send(new PutCommand({
    TableName: 'MyTable',
    Item: {
        id: 'item-001',
        attr1: 'value1',
        attr2: 'value2',
        attr3: 'value3',
        attr4: 'value4',
        // ... other attributes
    }
}));

// 3. Query GSI with all partition key attributes
await docClient.send(new QueryCommand({
    TableName: 'MyTable',
    IndexName: 'MyGSI',
    KeyConditionExpression: 'attr1 = :v1 AND attr2 = :v2',
    ExpressionAttributeValues: {
        ':v1': 'value1',
        ':v2': 'value2'
    }
}));

// 4. Query GSI with sort key attributes (left-to-right)
await docClient.send(new QueryCommand({
    TableName: 'MyTable',
    IndexName: 'MyGSI',
    KeyConditionExpression: 'attr1 = :v1 AND attr2 = :v2 AND attr3 = :v3',
    ExpressionAttributeValues: {
        ':v1': 'value1',
        ':v2': 'value2',
        ':v3': 'value3'
    }
}));

// Note: If any attribute name is a DynamoDB reserved keyword, use ExpressionAttributeNames:
// KeyConditionExpression: 'attr1 = :v1 AND #attr2 = :v2'
// ExpressionAttributeNames: { '#attr2': 'attr2' }
```

## Ressources supplémentaires
<a name="GSI.DesignPattern.MultiAttributeKeys.AdditionalResources"></a>
+ [Meilleures pratiques DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/best-practices.html)
+ [Utilisation de tables et de données](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithTables.html)
+ [Index secondaires globaux](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html)
+ [Opérations de requête et de numérisation](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html)

# Gestion des index secondaires globaux dans DynamoDB
<a name="GSI.OnlineOps"></a>

Cette section décrit comment créer, modifier et supprimer des index secondaires globaux dans Amazon DynamoDB.

**Topics**
+ [Création d’une table avec des index secondaires globaux](#GSI.Creating)
+ [Description des index secondaires globaux sur une table](#GSI.Describing)
+ [Ajout d’un index secondaire global à une table existante](#GSI.OnlineOps.Creating)
+ [Suppression d’un index secondaire global](#GSI.OnlineOps.Deleting)
+ [Modification d’un index secondaire global pendant la création](#GSI.OnlineOps.Creating.Modify)

## Création d’une table avec des index secondaires globaux
<a name="GSI.Creating"></a>

Pour créer une table avec un ou plusieurs index secondaires globaux, utilisez l’opération `CreateTable` avec le paramètre `GlobalSecondaryIndexes`. Pour bénéficier d’une flexibilité de requête maximum, vous pouvez créer jusqu’à 20 index secondaires globaux (quota par défaut) par table. 

Vous devez spécifier un attribut faisant office de clé de partition d’index. Vous pouvez éventuellement spécifier un autre attribut pour la clé de tri d’index. Il n’est pas nécessaire que l’un de ces attributs de clé soit identique à un attribut de clé dans la table. Par exemple, dans le *GameScores*tableau (voir[Utilisation d’index secondaires globaux dans DynamoDB](GSI.md)), il n'`TopScoreDateTime`y a `TopScore` pas non plus d'attributs clés. Vous pouvez créer un index secondaire global avec une clé de partition `TopScore` et une clé de tri `TopScoreDateTime`. Vous pouvez utiliser un tel index pour déterminer s’il existe une corrélation entre les scores d’une partie et l’heure de la journée à laquelle celle-ci est jouée.

Chaque attribut de clé d’index doit être un scalaire de type `String`, `Number` ou `Binary` (il ne peut pas être de type document ou ensemble). Vous pouvez projeter des attributs de tout type de données dans un index secondaire global. 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).

Si vous utilisez le mode approvisionné, vous devez fournir les paramètres `ProvisionedThroughput` pour l’index, à savoir `ReadCapacityUnits` et `WriteCapacityUnits`. Ces paramètres de débit approvisionné sont distincts de ceux de la table, mais se comportent de la même manière. Pour de plus amples informations, veuillez consulter [Considérations sur le débit alloué pour les index secondaires globaux](GSI.md#GSI.ThroughputConsiderations).

 Les index secondaires globaux héritent du mode read/write capacité de la table de base. Pour de plus amples informations, veuillez consulter [Considérations relatives au changement de mode de capacité dans DynamoDB](bp-switching-capacity-modes.md). 

**Note**  
 Lors de la création d’un nouvel index secondaire global, il peut être important de vérifier si la clé de partition de votre choix produit une distribution inégale ou réduite des données ou du trafic entre les valeurs des clés de partition du nouvel index. Si cela se produit, vous pourriez voir des opérations de remplissage et d’écriture se produire en même temps et limiter les écritures dans la table de base. Le service prend des mesures pour minimiser l’éventualité de ce scénario, mais il n’a aucune idée de la forme des données client par rapport à la clé de partition d’index, à la projection choisie ou à la rareté de la clé primaire d’index.  
Si vous pensez que votre nouvel index secondaire global peut présenter des données ou une distribution de trafic étroites ou asymétriques entre les valeurs des clés de partition, tenez compte des points suivants avant d’ajouter de nouveaux index à des tables importantes sur le plan opérationnel.  
Il peut être plus sûr d’ajouter l’index au moment où votre application génère le moins de trafic.
Envisagez d'activer CloudWatch Contributor Insights sur votre table de base et vos index. Cela vous procurera des informations précieuses sur la distribution de votre trafic.
 Surveillez `WriteThrottleEvents` et `ThrottledRequests` mesurez `OnlineIndexPercentageProgress` CloudWatch tout au long du processus. Ajustez la capacité d'écriture allouée selon les besoins pour terminer le remblayage dans un délai raisonnable sans aucun effet de limitation significatif sur vos opérations en cours. `OnlineIndexConsumedWriteCapacity`et `OnlineThrottleEvents` devraient afficher 0 lors du remblayage de l'indice.
Préparez-vous à annuler la création de l'index si vous subissez un impact opérationnel dû à la limitation des écritures.

## Description des index secondaires globaux sur une table
<a name="GSI.Describing"></a>

Pour afficher l’état de tous les index secondaires globaux sur une table, utilisez l’opération `DescribeTable`. La portion `GlobalSecondaryIndexes` de la réponse affiche tous les index sur la table, ainsi que l’état actuel de chacun d’eux (`IndexStatus`).

L’état `IndexStatus` d’un index secondaire global peut être l’un des suivants :
+ `CREATING` – L’index est en cours de création et n’est pas encore disponible pour utilisation.
+ `ACTIVE` – L’index est prêt pour utilisation et les applications peuvent effectuer des opérations `Query` dessus.
+ `UPDATING` – Les paramètres de débit approvisionné de l’index sont en cours de modification.
+ `DELETING` – L’index est actuellement en cours de suppression et ne peut plus être utilisé.

Quand DynamoDB a fini de générer un index secondaire global, l’état de celui-ci passe de `CREATING` à `ACTIVE`.

## Ajout d’un index secondaire global à une table existante
<a name="GSI.OnlineOps.Creating"></a>

Pour ajouter un index secondaire global à une table existante, utilisez l’opération `UpdateTable` avec le paramètre `GlobalSecondaryIndexUpdates`. Vous devez fournir les informations suivantes :
+ Un nom d’index. Le nom doit être unique parmi tous les index sur cette table.
+ Le schéma de clé de l’index. Vous devez spécifier un attribut pour la clé de partition d’index. Vous pouvez éventuellement spécifier un autre attribut pour la clé de tri d’index. Il n’est pas nécessaire que l’un de ces attributs de clé soit identique à un attribut de clé dans la table. Les types de données pour chaque attribut de schéma doivent être scalaires : `String`, `Number` ou `Binary`.
+ Attributs à projeter à partir de la table dans l’index :
  + `KEYS_ONLY` – 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. 
  + `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 inclut tous les attributs de la table source.
+ Les paramètres de débit approvisionné pour l’index, à savoir `ReadCapacityUnits` et `WriteCapacityUnits`. Ces paramètres de débit approvisionné sont distincts de ceux de la table.

Vous ne pouvez créer qu'un seul index secondaire global par opération `UpdateTable`.

### Phases de création d'index
<a name="GSI.OnlineOps.Creating.Phases"></a>

Lorsque vous ajoutez un nouvel index secondaire global à une table existante, la table reste disponible pendant la création de l’index. Toutefois, le nouvel index n’est pas disponible pour les opérations Query tant que son état n’est pas passé de `CREATING` à `ACTIVE`.

**Note**  
La création d’un index secondaire global n’utilise pas la scalabilité automatique des applications. L’augmentation de la capacité de scalabilité automatique des applications `MIN` ne réduit pas le temps de création de l’index secondaire global.

En coulisses, DynamoDB génère l’index en deux phases :

**Allocation de ressources**  
DynamoDB alloue les ressources de calcul et de stockage nécessaires à la génération de l’index.  
Au cours de la phase d’allocation des ressources, l’attribut `IndexStatus` est `CREATING`, et l’attribut `Backfilling` a la valeur false. Utilisez l’opération `DescribeTable` pour récupérer l’état d’une table et de tous ses index secondaires.  
Pendant que l’index est en phase d’allocation de ressources, vous ne pouvez pas supprimer l’index ou sa table parent. Vous ne pouvez pas non plus modifier le débit approvisionné de l’index ou de la table. Vous ne pouvez pas ajouter ou supprimer d’autres index sur la table. En revanche, vous pouvez modifier le débit approvisionné de ces autres index.

**Remplissage**  
Pour chaque élément de la table, DynamoDB détermine l’ensemble d’attributs à écrire dans l’index en fonction de sa projection (`KEYS_ONLY`, `INCLUDE` ou `ALL`). Il écrit ensuite ces attributs dans l’index. Durant la phase de remplissage, DynamoDB suit les éléments ajoutés, supprimés ou mis à jour dans la table. Les attributs de ces éléments sont également ajoutés, supprimés ou mis à jour dans l’index, selon le cas.  
Au cours de la phase de remplissage, l’attribut `IndexStatus` est défini sur `CREATING`, et l’attribut `Backfilling` a la valeur true. Utilisez l’opération `DescribeTable` pour récupérer l’état d’une table et de tous ses index secondaires.  
Pendant le remplissage de l’index, vous ne pouvez pas supprimer sa table parent. Vous pouvez cependant toujours supprimer l’index ou modifier le débit approvisionné de la table et de n’importe lequel de ses index secondaires globaux.  
Pendant la phase de remplissage, certaines écritures d’éléments violant le schéma de clé peuvent aboutir tandis que d’autres sont rejetées. Après le remplissage, toutes les écritures dans les éléments, qui violent le schéma de clé du nouvel index sont rejetées. Nous vous recommandons d’exécuter l’outil de détection des violations une fois la phase de remplissage terminée afin de détecter et résoudre d’éventuelles violations de clé. Pour de plus amples informations, veuillez consulter [Détection et correction des violations de clé d’index dans DynamoDB](GSI.OnlineOps.ViolationDetection.md).

Pendant les phases d’allocation de ressources et de remplissage, l’index est dans l’état `CREATING`. Pendant ce temps, DynamoDB effectue des opérations de lecture sur la table. Vous n’êtes pas facturé pour les opérations de lecture de la table de base destinées au remplissage de l’index secondaire global.

Une fois la génération de l’index terminée, l’état passe à `ACTIVE`. Vous ne pouvez pas effectuer d’opération `Query` ou `Scan` sur l’index tant que l’état de celui-ci n’est pas `ACTIVE`.

**Note**  
Dans certains cas, DynamoDB ne peut pas écrire des données de la table dans l’index en raison de violations de clé d’index. Cela peut se produire si :  
Le type de données d’une valeur d’attribut ne correspond pas au type de données d’un type de données de schéma de clé d’index.
La taille d’un attribut dépasse la longueur maximale définie pour un attribut de clé d’index.
Un attribut de clé d’index a une valeur de String ou de Binary attribute vide.
Les violations de clé d’index n’interfèrent pas avec la création d’index secondaire global. Cependant, quand l’index passe à l’état `ACTIVE`, il ne contient plus de clé violant le schéma de clé.  
DynamoDB fournit un outil autonome pour détecter et résoudre ces problèmes. Pour de plus amples informations, veuillez consulter [Détection et correction des violations de clé d’index dans DynamoDB](GSI.OnlineOps.ViolationDetection.md).

### Ajout d’un index secondaire global à une table volumineuse
<a name="GSI.OnlineOps.Creating.LargeTable"></a>

Le temps nécessaire à la génération d’un index secondaire global dépend de plusieurs facteurs, tels que les suivants :
+ La taille de la table
+ Le nombre d’éléments dans la table pouvant être inclus dans l’index
+ Le nombre d’attributs projetés dans l’index
+ L’activité d’écriture sur la table principale pendant les générations d’index

Si vous ajoutez un index secondaire global à une table très volumineuse, le processus de création peut prendre beaucoup de temps. Pour suivre la progression et déterminer si la capacité d'écriture de l'index est suffisante, consultez les CloudWatch statistiques Amazon suivantes :
+ `OnlineIndexPercentageProgress`

Pour plus d'informations sur CloudWatch les métriques associées à DynamoDB, consultez. [Métriques DynamoDB](metrics-dimensions.md#dynamodb-metrics)

**Important**  
Vous devrez peut-être autoriser la mise en liste d’autorisation de très grandes tables avant de créer ou de mettre à jour un index secondaire global. Contactez le AWS Support pour autoriser la mise en liste de vos tables.

Pendant le remplissage d’un index, DynamoDB utilise la capacité système interne pour lire la table. Cela permet de minimiser l’impact de la création d’index et de s’assurer que la table ne manque pas de capacité de lecture.

## Suppression d’un index secondaire global
<a name="GSI.OnlineOps.Deleting"></a>

Si vous n’avez plus besoin d’un index secondaire global, vous pouvez le supprimer à l’aide de l’opération `UpdateTable`.

Vous ne pouvez supprimer qu’un seul index secondaire global par opération `UpdateTable`.

Le processus de suppression de l’index secondaire global n’a aucune incidence sur les activités de lecture ou d’écriture dans la table parent. Pendant la suppression, vous pouvez toujours modifier le débit approvisionné sur d’autres index.

**Note**  
Lorsque vous supprimez une table à l’aide de l’action `DeleteTable`, tous les index secondaires globaux sur cette table sont également supprimés.
Votre compte ne sera pas facturé pour l’opération de suppression de l’index secondaire global.

## Modification d’un index secondaire global pendant la création
<a name="GSI.OnlineOps.Creating.Modify"></a>

Pendant la génération d’un index, vous pouvez utiliser l’opération `DescribeTable` pour déterminer la phase en cours. La description de l’index inclut un attribut booléen, `Backfilling`, indiquant si DynamoDB est en train de charger l’index avec les éléments de la table. Si la valeur de `Backfilling` est true, la phase d’allocation de ressources est terminée et le remplissage de l’index est en cours. 

Pendant la phase de remplissage, vous pouvez supprimer l’index en cours de création. Au cours de cette phase, vous ne pouvez pas ajouter ou supprimer d’autres index sur la table.

**Note**  
Pour les index créés dans le cadre d’une opération `CreateTable`, l’attribut `Backfilling` n’apparaît pas dans la sortie `DescribeTable`. Pour de plus amples informations, veuillez consulter [Phases de création d'index](#GSI.OnlineOps.Creating.Phases).

# Détection et correction des violations de clé d’index dans DynamoDB
<a name="GSI.OnlineOps.ViolationDetection"></a>

Durant la phase de remplissage du processus de création d’index secondaire global, Amazon DynamoDB examine chaque élément de la table pour déterminer s’il peut être inclus dans l’index. Il se peut que certains éléments ne soient pas être éligibles parce qu’ils provoqueraient des violations de clé d’index. Dans ce cas, ces éléments restent dans la table, mais l’index ne contient pas d’entrée correspondante.

Une *violation de clé d’index* se produit dans les situations suivantes :
+ Il existe une discordance de type de données entre une valeur d’attribut et le type de données du schéma de clé d’index. Par exemple, supposons que l’un des éléments de la table `GameScores` a une valeur `TopScore` de type `String`. Si vous ajoutiez un index secondaire global avec une clé de partition `TopScore` de type `Number`, l’élément de la table violerait la clé d’index.
+ Une valeur d’attribut de la table dépasse la longueur maximum pour un attribut de clé d’index. La longueur maximum d’une clé de partition est de 2 048 octets, et la longueur maximum d’une clé de tri est de 1 024 octets. Si l’une des valeurs d’attribut correspondantes dans la table dépasse ces limites, l’élément de la table viole la clé d’index.

**Note**  
Si une valeur de String ou de Binary attribute est définie pour un attribut utilisé comme clé d’index, la valeur d’attribut doit avoir une longueur supérieure à zéro ; sinon, l’élément de la table viole la clé d’index.  
Cet outil ne signale pas cette violation de clé d’index, pour le moment.

Si une violation de clé d’index se produit, la phase de remplissage se poursuit sans interruption. Toutefois, les éléments violant le schéma de clé ne sont pas inclus dans l’index. Une fois la phase de remplissage terminée, toutes les écritures dans des éléments, qui violent le schéma de clé du nouvel index sont rejetées.

Pour identifier et corriger les valeurs d’attribut dans une table, qui violent une clé d’index, utilisez l’outil de détection des violations. Pour exécuter l’outil de détection des violations, vous créez un fichier de configuration qui spécifie le nom d’une table à analyser, les noms et les types de données des clés de partition et de tri d’index secondaire global, ainsi que les actions à entreprendre en cas détection de violations de clé d’index. L’outil de détection des violations peut opérer dans l’un des deux modes suivants :
+ **Mode détection** – Détecter les violations de clé d’index. Utilisez le mode de détection pour signaler les éléments de la table qui provoqueraient des violations de clé dans un index secondaire global (vous pouvez éventuellement demander que ces éléments de table violant le schéma de clé soient supprimés immédiatement quand ils sont détectés). La sortie du mode détection est écrite dans un fichier que vous pouvez utiliser pour une analyse plus approfondie.
+ **Mode correction** – Corriger les violations de clé d’index. En mode correction, l’outil de détection des violations lit un fichier d’entrée du même format que le fichier de sortie du mode détection. Le mode correction lit les enregistrements du fichier d’entrée et, pour chacun d’eux, supprime ou met à jour les éléments correspondants dans la table (notez que, si vous choisissez de mettre à jour les éléments, vous devez modifier le fichier d’entrée et définir des valeurs appropriées pour ces mises à jour).

## Téléchargement et exécution de l’outil de détection des violations
<a name="GSI.OnlineOps.ViolationDetection.Running"></a>

L’outil de détection des violations est disponible en tant qu’archive Java exécutable (fichier `.jar`), et s’exécute sur les ordinateurs Windows, macOS ou Linux. L’outil de détection des violations requiert Java 1.7 (ou version ultérieure) et Apache Maven.
+ [Téléchargez le détecteur de violations depuis GitHub](https://github.com/awslabs/dynamodb-online-index-violation-detector)

Suivez les instructions figurant dans le fichier `README.md` pour télécharger et installer l’outil de détection des violations à l’aide de Maven.

Pour démarrer l’outil de détection des violations, accédez au répertoire dans lequel vous avez généré le fichier `ViolationDetector.java`, puis entrez la commande suivante.

```
java -jar ViolationDetector.jar [options]
```

La ligne de commande de l’outil de détection des violations accepte les options suivantes :
+ `-h | --help` – Affiche un résumé et des options d’utilisation pour l’outil de détection des violations.
+ `-p | --configFilePath` `value` – Nom complet d’un fichier de configuration de l’outil de détection des violations. Pour de plus amples informations, veuillez consulter [Fichier de configuration de l’outil de détection des violations](#GSI.OnlineOps.ViolationDetection.ConfigFile).
+ `-t | --detect` `value` – Détecte les violations de clé d’index dans la table, et les écris dans le fichier de sortie de l’outil de détection des violations. Si la valeur de ce paramètre est définie sur `keep`, les éléments comportant des violations de clé ne sont pas modifiés. Si la valeur est définie sur `delete`, les éléments comportant des violations de clé sont supprimés de la table.
+ `-c | --correct` `value` – Lit les violations de clé d’index à partir d’un fichier d’entrée, et prend des mesures correctives sur les éléments de la table. Si la valeur de ce paramètre est définie sur `update`, les éléments comportant des violations de clé sont mis à jour avec de nouvelles valeurs ne violant pas le schéma de clé. Si la valeur est définie sur `delete`, les éléments comportant des violations de clé sont supprimés de la table.

## Fichier de configuration de l’outil de détection des violations
<a name="GSI.OnlineOps.ViolationDetection.ConfigFile"></a>

Lors de l’exécution, l’outil de détection des violations nécessite un fichier de configuration. Les paramètres de ce fichier déterminent les ressources DynamoDB auxquelles l’outil de détection des violations peut accéder, ainsi que le débit approvisionné qu’il peut consommer. Le tableau suivant décrit ces paramètres.


****  

| Nom du paramètre | Description | Obligatoire ? | 
| --- | --- | --- | 
|  `awsCredentialsFile`  |  Le nom complet d’un fichier contenant vos informations d’identification AWS . Le format du fichier contenant les informations d’identification doit être le suivant : <pre>accessKey = access_key_id_goes_here<br />secretKey = secret_key_goes_here </pre>  |  Oui  | 
|  `dynamoDBRegion`  |   AWS Région dans laquelle se trouve la table. Par exemple : `us-west-2`.  |  Oui  | 
|  `tableName`  | Le nom de la table DynamoDB à analyser. |  Oui  | 
|  `gsiHashKeyName`  |  Le nom de la clé de partition d’index.  |  Oui  | 
|  `gsiHashKeyType`  |  Le type de données de la clé de partition d’index, à savoir `String`, `Number` ou `Binary` : `S \| N \| B`  |  Oui  | 
|  `gsiRangeKeyName`  |  Le nom de la clé de tri d’index. Ne spécifiez pas ce paramètre si l’index n’a qu’une clé primaire simple (clé de partition).  |  Non  | 
|  `gsiRangeKeyType`  |  Le type de données de la clé de tri d’index, à savoir `String`, `Number` ou `Binary` : `S \| N \| B`  Ne spécifiez pas ce paramètre si l’index n’a qu’une clé primaire simple (clé de partition).  |  Non  | 
|  `recordDetails`  |  Indication relative à l’écriture des détails des violations de clé d’index dans le fichier de sortie. Si la valeur est définie sur `true` (par défaut), les informations complètes sur les éléments violant le schéma de clé sont rapportées. Si la valeur est définie sur `false`, seul le nombre de violations est rapporté.  |  Non  | 
|  `recordGsiValueInViolationRecord`  |  Indication relative à l’écriture des valeurs des violations de clé d’index dans le fichier de sortie. Si la valeur est définie sur `true` (par défaut), les valeurs de clés sont rapportées. Si la valeur est définie sur `false`, les valeurs de clés sont rapportées.  |  Non  | 
|  `detectionOutputPath`  |  Le chemin d’accès complet du fichier de sortie de l’outil de détection des violations. Ce paramètre prend en charge l’écriture dans un répertoire local ou sur Amazon Simple Storage Service (Amazon S3). Voici quelques exemples : `detectionOutputPath = ``//local/path/filename.csv` `detectionOutputPath = ``s3://bucket/filename.csv` Les informations figurant dans le fichier de sortie s’affichent au format CSV (valeurs séparées par des virgules). Si vous ne définissez pas `detectionOutputPath`, le fichier de sortie est nommé `violation_detection.csv` et écrit dans votre répertoire de travail actuel.  |  Non  | 
|  `numOfSegments`  | Le nombre de segments d’analyse parallèle à utiliser quand l’outil de détection des violations analyse la table. La valeur par défaut est 1, ce qui signifie que la table est analysée de manière séquentielle. Si la valeur est égale ou supérieure à 2, l’outil de détection des violations divise la table en plusieurs segments logiques et un nombre égal d’unités d’exécution d’analyse. La valeur maximum de `numOfSegments` est 4 096.Pour les tables plus volumineuses, une analyse parallèle est généralement plus rapide qu’une analyse séquentielle. En outre, si la table est suffisamment grande pour couvrir plusieurs partitions, une analyse parallèle répartit uniformément son activité de lecture sur plusieurs partitions.Pour plus d’informations sur les analyses parallèles dans DynamoDB, consultez [Analyse parallèle](Scan.md#Scan.ParallelScan). |  Non  | 
|  `numOfViolations`  |  La limite supérieure des violations de clé d’index à écrire dans le fichier de sortie. Si la valeur est définie sur `-1` (par défaut), la table entière est analysée. Si la valeur est définie sur un nombre entier positif, l’outil de détection des violations s’arrête après avoir rencontré ce nombre de violations.  |  Non  | 
|  `numOfRecords`  |  Le nombre d’éléments de la table à analyser. Si la valeur est définie sur (par défaut), la table entière est analysée. Si la valeur est définie sur un nombre entier positif, l’outil de détection des violations s’arrête après avoir analysé ce nombre d’éléments de la table.  |  Non  | 
|  `readWriteIOPSPercent`  |  Régule le pourcentage d’unités de capacité de lecture approvisionnée qui sont consommées pendant l’analyse de la table. La plage des valeurs valides s’étend de `1` à `100`. La valeur par défaut (`25`) signifie que l’outil de détection des violations ne consommera pas plus de 25 % du débit de lecture approvisionné de la table.  |  Non  | 
|  `correctionInputPath`  |  Chemin d’accès complet du fichier d’entrée de correction de l’outil de détection des violations. Si vous exécutez l’outil de détection des violations en mode correction, le contenu de ce fichier est utilisé pour modifier ou supprimer les éléments de données dans la table, qui violent l’index secondaire global. Le format du fichier `correctionInputPath` est identique à celui du fichier `detectionOutputPath`. Cela vous permet de traiter la sortie du mode détection comme entrée en mode correction.  |  Non  | 
|  `correctionOutputPath`  |  Chemin d’accès complet du fichier de sortie de correction de l’outil de détection des violations. Ce fichier n’est créé que s’il y a des erreurs de mise à jour. Ce paramètre prend en charge l’écriture dans un répertoire local ou sur Amazon S3. Voici quelques exemples : `correctionOutputPath = ``//local/path/filename.csv` `correctionOutputPath = ``s3://bucket/filename.csv` Les informations figurant dans le fichier de sortie s’affichent au format CSV. Si vous ne définissez pas `correctionOutputPath`, le fichier de sortie est nommé `violation_update_errors.csv` et écrit dans votre répertoire de travail actuel.  |  Non  | 

## Détection
<a name="GSI.OnlineOps.ViolationDetection.Detection"></a>

Pour détecter les violations de clé d’index, utilisez l’outil de détection des violations avec l’option de ligne de commande `--detect`. Pour voir le fonctionnement de cette option, considérez le tableau `ProductCatalog`. Voici la liste des éléments de la table. Seule la clé primaire (`Id`) et l’attribut `Price` sont affichés.


****  

| Id (clé primaire) | Price | 
| --- | --- | 
| 101 |  5  | 
| 102 |  20  | 
| 103 | 200  | 
| 201 |  100  | 
| 202 |  200  | 
| 203 |  300  | 
| 204 |  400  | 
| 205 |  500  | 

Toutes les valeurs pour `Price` sont de type `Number`. Cependant, DynamoDB étant sans schéma, il est possible d’ajouter un élément avec une valeur `Price` non numérique. Par exemple, supposons que vous ajoutez un autre élément à la table `ProductCatalog`.


****  

| Id (clé primaire) | Price | 
| --- | --- | 
| 999 | "Hello" | 

La table totalise maintenant neuf éléments.

Vous ajoutez à présent un nouvel index secondaire global à la table : `PriceIndex`. La clé primaire pour cet index est une clé de partition, `Price`, de type `Number`. Une fois l’index généré, il contient huit éléments, tandis que la table `ProductCatalog` en contient neuf. La raison de cette différence est que la valeur `"Hello"` est de type `String`, alors que `PriceIndex` a une clé primaire de type `Number`. La valeur `String` violant la clé d’index secondaire globale, elle n’est pas présente dans l’index.

Pour utiliser l’outil de détection des violations dans ce scénario, vous devez d’abord créer un fichier de configuration tel que le suivant.

```
# Properties file for violation detection tool configuration.
# Parameters that are not specified will use default values.

awsCredentialsFile = /home/alice/credentials.txt
dynamoDBRegion = us-west-2
tableName = ProductCatalog
gsiHashKeyName = Price
gsiHashKeyType = N
recordDetails = true
recordGsiValueInViolationRecord = true
detectionOutputPath = ./gsi_violation_check.csv
correctionInputPath = ./gsi_violation_check.csv
numOfSegments = 1
readWriteIOPSPercent = 40
```

Ensuite, vous exécutez l’outil de détection des violations comme dans l’exemple suivant.

```
$  java -jar ViolationDetector.jar --configFilePath config.txt --detect keep

Violation detection started: sequential scan, Table name: ProductCatalog, GSI name: PriceIndex
Progress: Items scanned in total: 9,    Items scanned by this thread: 9,    Violations found by this thread: 1, Violations deleted by this thread: 0
Violation detection finished: Records scanned: 9, Violations found: 1, Violations deleted: 0, see results at: ./gsi_violation_check.csv
```

Si le paramètre de configuration `recordDetails` est défini sur `true`, l’outil de détection des violations écrit les détails de chaque violation dans le fichier de sortie, comme dans l’exemple suivant.

```
Table Hash Key,GSI Hash Key Value,GSI Hash Key Violation Type,GSI Hash Key Violation Description,GSI Hash Key Update Value(FOR USER),Delete Blank Attributes When Updating?(Y/N) 

999,"{""S"":""Hello""}",Type Violation,Expected: N Found: S,,
```

Le fichier de sortie est au format CSV. La première ligne du fichier est un en-tête. Elle est suivie d’un registre par élément qui viole la clé d’index. Les champs de ces registres de violation sont les suivants :
+ **Table hash key** (Clé de hachage de table) – Valeur de clé de partition de l’élément dans la table.
+ **Table range key** (Clé de plage de table) – Valeur de clé de tri de l’élément dans la table.
+ **GSI hash key value** (Valeur de clé de hachage GSI) – Valeur de clé de partition de l’index secondaire global.
+ **GSI hash key violation type** (Type de violation de clé de hachage GSI) – `Type Violation` ou `Size Violation`.
+ **GSI hash key violation description** (Description de violation de clé de hachage GSI) – Cause de la violation.
+ **GSI hash key update value (FOR USER)** (Valeur de mise à jour de clé de hachage GSI (POUR UTILISATEUR)) – En mode correction, nouvelle valeur fournie par l’utilisateur pour l’attribut.
+ **GSI range key value** (Valeur de clé de plage GSI) – Valeur de clé de tri de l’index secondaire global.
+ **GSI range key violation type** (Type de violation de clé de plage GSI) – `Type Violation` ou `Size Violation`.
+ **GSI range key violation description** (Description de violation de clé de plage GSI) – Cause de la violation.
+ **GSI range key update value (FOR USER)** (Valeur de mise à jour de clé de plage GSI (POUR UTILISATEUR)) – En mode correction, nouvelle valeur fournie par l’utilisateur pour l’attribut.
+ **Delete blank attribute when updating (Y/N)** (Supprimer un attribut vide lors de la mise à jour (O/N)) – En mode correction, détermine s’il faut supprimer (Y) ou conserver (N) l’élément violant le schéma de clé dans la table, mais uniquement si l’un des champs suivants est vide :
  + `GSI Hash Key Update Value(FOR USER)`
  + `GSI Range Key Update Value(FOR USER)`

  Si l’un de ces champs n’est pas vide, `Delete Blank Attribute When Updating(Y/N)` n’a aucun effet.

**Note**  
Le format de sortie peut varier en fonction du fichier de configuration et des options de ligne de commande. Par exemple, si la table possède une clé primaire simple (sans clé de tri), aucun champ de clé de tri ne figure dans la sortie.  
Il se peut que les registres de violation dans le fichier ne soient pas dans un ordre trié.

## Correction
<a name="GSI.OnlineOps.ViolationDetection.Correction"></a>

Pour corriger les violations de clé d’indexation, utilisez l’outil de détection des violations avec l’option de ligne de commande `--correct`. En mode correction, l’outil de détection des violations lit le fichier d’entrée spécifié par le paramètre `correctionInputPath`. Le format de ce fichier étant le même que celui du fichier `detectionOutputPath`, vous pouvez utiliser la sortie de la détection comme entrée pour la correction.

L’outil de détection des violations offre deux options pour corriger les violations de clé d’index :
+ **Delete violations (Supprimer les violations)** – Supprimer les éléments de table qui ont des valeurs d’attribut violant le schéma de clé.
+ **Update violations (Mettre à jour les violations)** – Mettre à jour les éléments de table en remplaçant les attributs violant le schéma de clé par des valeurs ne les violant pas.

Dans les deux cas, vous pouvez utiliser le fichier de sortie du mode détection comme entrée pour le mode correction.

En poursuivant avec l’exemple `ProductCatalog`, supposons que vous voulez supprimer de la table l’élément violant le schéma de clé. Pour ce faire, vous utilisez la ligne de commande suivante.

```
$  java -jar ViolationDetector.jar --configFilePath config.txt --correct delete
```

À ce stade, vous êtes invité à confirmer si vous souhaitez supprimer les éléments violant le schéma de clé.

```
Are you sure to delete all violations on the table?y/n
y
Confirmed, will delete violations on the table...
Violation correction from file started: Reading records from file: ./gsi_violation_check.csv, will delete these records from table.
Violation correction from file finished: Violations delete: 1, Violations Update: 0
```

A présent, `ProductCatalog` et `PriceIndex` ont le même nombre d’éléments.

# Utilisation d'index secondaires globaux : Java
<a name="GSIJavaDocumentAPI"></a>

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

Voici les étapes courantes pour les opérations de table. 

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 global](#GSIJavaDocumentAPI.CreateTableWithIndex)
+ [Décrire une table avec un index secondaire global](#GSIJavaDocumentAPI.DescribeTableWithIndex)
+ [Interroger un index secondaire global](#GSIJavaDocumentAPI.QueryAnIndex)
+ [Exemple : index secondaires globaux utilisant l'API du AWS SDK pour Java document](GSIJavaDocumentAPI.Example.md)

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

Vous pouvez créer des index secondaires globaux au moment où vous créez une table. Pour ce faire, utilisez `CreateTable` et fournissez vos spécifications pour un ou plusieurs index secondaires globaux. L'exemple de code Java suivant crée une table destinée à accueillir des données météorologiques. La clé de partition est `Location`, et la clé de tri `Date`. Un index secondaire global nommé `PrecipIndex` permet un accès rapide aux données de précipitations pour différents endroits.

Voici les étapes à suivre pour créer une table avec un index secondaire global à 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 global, vous devez fournir le nom de l'index, ses paramètres de débit approvisionné, les définitions d'attribut 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 (`WeatherData`) avec un index secondaire global (`PrecipIndex`). La clé de partition d'index est `Date`, et la clé de tri `Precipitation`. Tous les attributs de table sont projetés sur l'index. Les utilisateurs peuvent interroger cet index afin d'obtenir des données météorologiques pour une date particulière, en triant éventuellement les données par quantité de précipitations. 

`Precipitation` n'étant pas un attribut de clé pour la table, il n'est pas obligatoire. Toutefois, les éléments `WeatherData` sans `Precipitation` n'apparaissent pas dans `PrecipIndex`.

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

// Attribute definitions
ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Location")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Date")
    .withAttributeType("S"));
attributeDefinitions.add(new AttributeDefinition()
    .withAttributeName("Precipitation")
    .withAttributeType("N"));

// Table key schema
ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Location")
    .withKeyType(KeyType.HASH));  //Partition key
tableKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.RANGE));  //Sort key

// PrecipIndex
GlobalSecondaryIndex precipIndex = new GlobalSecondaryIndex()
    .withIndexName("PrecipIndex")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 10)
        .withWriteCapacityUnits((long) 1))
        .withProjection(new Projection().withProjectionType(ProjectionType.ALL));

ArrayList<KeySchemaElement> indexKeySchema = new ArrayList<KeySchemaElement>();

indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Date")
    .withKeyType(KeyType.HASH));  //Partition key
indexKeySchema.add(new KeySchemaElement()
    .withAttributeName("Precipitation")
    .withKeyType(KeyType.RANGE));  //Sort key

precipIndex.setKeySchema(indexKeySchema);

CreateTableRequest createTableRequest = new CreateTableRequest()
    .withTableName("WeatherData")
    .withProvisionedThroughput(new ProvisionedThroughput()
        .withReadCapacityUnits((long) 5)
        .withWriteCapacityUnits((long) 1))
    .withAttributeDefinitions(attributeDefinitions)
    .withKeySchema(tableKeySchema)
    .withGlobalSecondaryIndexes(precipIndex);

Table table = dynamoDB.createTable(createTableRequest);
System.out.println(table.getDescription());
```

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 global
<a name="GSIJavaDocumentAPI.DescribeTableWithIndex"></a>

Pour obtenir des informations concernant les index secondaires globaux sur une table, utilisez l'opération `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 global sur une table. 

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

1. Créez une instance de la classe `Table` pour représenter l'index que vous souhaitez utiliser.

1. Appelez la méthode `describe` 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);

Table table = dynamoDB.getTable("WeatherData");
TableDescription tableDesc = table.describe();
    

Iterator<GlobalSecondaryIndexDescription> gsiIter = tableDesc.getGlobalSecondaryIndexes().iterator();
while (gsiIter.hasNext()) {
    GlobalSecondaryIndexDescription gsiDesc = gsiIter.next();
    System.out.println("Info for index "
         + gsiDesc.getIndexName() + ":");

    Iterator<KeySchemaElement> kseIter = gsiDesc.getKeySchema().iterator();
    while (kseIter.hasNext()) {
        KeySchemaElement kse = kseIter.next();
        System.out.printf("\t%s: %s\n", kse.getAttributeName(), kse.getKeyType());
    }
    Projection projection = gsiDesc.getProjection();
    System.out.println("\tThe projection type is: "
        + projection.getProjectionType());
    if (projection.getProjectionType().toString().equals("INCLUDE")) {
        System.out.println("\t\tThe non-key projected attributes are: "
            + projection.getNonKeyAttributes());
    }
}
```

## Interroger un index secondaire global
<a name="GSIJavaDocumentAPI.QueryAnIndex"></a>

Vous pouvez utiliser l'opération `Query` sur un index secondaire global de la même manière que vous utilisez l'opération `Query` sur une table. Vous devez spécifier le nom de l'index, les critères de requête pour la clé de partition d'index et la clé de tri (le cas échéant), ainsi que les attributs que vous souhaitez renvoyer. Dans cet exemple, l'index est `PrecipIndex`. Il a une clé de partition `Date` et une clé de tri `Precipitation`. L'interrogation de l'index renvoie toutes les données météorologiques pour une date particulière, où les précipitations sont supérieures à zéro.

Voici les étapes à suivre pour interroger un index secondaire global à 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` pour représenter l'index que vous souhaitez utiliser.

1. Créez une instance de la classe `Index` pour l'index que vous souhaitez interroger.

1. Appelez la méthode `query` sur l'objet `Index`.

Nom d'attribut `Date` est un mot réservé DynamoDB. Par conséquent, vous devez utiliser un nom d'attribut d'expression comme espace réservé dans la `KeyConditionExpression`.

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

**Example**  

```
AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
DynamoDB dynamoDB = new DynamoDB(client);

Table table = dynamoDB.getTable("WeatherData");
Index index = table.getIndex("PrecipIndex");

QuerySpec spec = new QuerySpec()
    .withKeyConditionExpression("#d = :v_date and Precipitation = :v_precip")
    .withNameMap(new NameMap()
        .with("#d", "Date"))
    .withValueMap(new ValueMap()
        .withString(":v_date","2013-08-10")
        .withNumber(":v_precip",0));

ItemCollection<QueryOutcome> items = index.query(spec);
Iterator<Item> iter = items.iterator(); 
while (iter.hasNext()) {
    System.out.println(iter.next().toJSONPretty());
}
```

# Exemple : index secondaires globaux utilisant l'API du AWS SDK pour Java document
<a name="GSIJavaDocumentAPI.Example"></a>

L'exemple de code Java suivant montre comment utiliser les index secondaires globaux. L'exemple crée une table nommée `Issues`, utilisable dans un système simple de suivi de bogues pour le développement de logiciels. La clé de partition est `IssueId`, et la clé de tri `Title`. Il y a trois index secondaires globaux sur cette table :
+ `CreateDateIndex` – La clé de partition est `CreateDate`, et la clé de tri `IssueId`. En plus des clés de table, les attributs `Description` et `Status` sont projetés dans l'index.
+ `TitleIndex` – La clé de partition est `Title`, et la clé de tri `IssueId`. Aucun attribut autre que les clés de table n'est projeté dans l'index.
+ `DueDateIndex` – La clé de partition est `DueDate` et il n'y a pas de clé de tri. Tous les attributs de table sont projetés sur l'index.

Une fois la table `Issues` créée, le programme charge la table avec des données représentant des rapports de bogues logiciels. Il interroge ensuite les données à l'aide d'index secondaires globaux. Enfin, le programme supprime la table `Issues`.

Pour step-by-step obtenir des instructions sur le test de l'exemple suivant, reportez-vous à[Exemples de code Java](CodeSamples.Java.md).

**Example**  

```
package com.amazonaws.codesamples.document;

import java.util.ArrayList;
import java.util.Iterator;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Index;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.QueryOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.QuerySpec;
import com.amazonaws.services.dynamodbv2.document.utils.ValueMap;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.GlobalSecondaryIndex;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.Projection;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;

public class DocumentAPIGlobalSecondaryIndexExample {

    static AmazonDynamoDB client = AmazonDynamoDBClientBuilder.standard().build();
    static DynamoDB dynamoDB = new DynamoDB(client);

    public static String tableName = "Issues";

    public static void main(String[] args) throws Exception {

        createTable();
        loadData();

        queryIndex("CreateDateIndex");
        queryIndex("TitleIndex");
        queryIndex("DueDateIndex");

        deleteTable(tableName);

    }

    public static void createTable() {

        // Attribute definitions
        ArrayList<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();

        attributeDefinitions.add(new AttributeDefinition().withAttributeName("IssueId").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("Title").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("CreateDate").withAttributeType("S"));
        attributeDefinitions.add(new AttributeDefinition().withAttributeName("DueDate").withAttributeType("S"));

        // Key schema for table
        ArrayList<KeySchemaElement> tableKeySchema = new ArrayList<KeySchemaElement>();
        tableKeySchema.add(new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.HASH)); // Partition
                                                                                                           // key
        tableKeySchema.add(new KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.RANGE)); // Sort
                                                                                                          // key

        // Initial provisioned throughput settings for the indexes
        ProvisionedThroughput ptIndex = new ProvisionedThroughput().withReadCapacityUnits(1L)
                .withWriteCapacityUnits(1L);

        // CreateDateIndex
        GlobalSecondaryIndex createDateIndex = new GlobalSecondaryIndex().withIndexName("CreateDateIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("CreateDate").withKeyType(KeyType.HASH), // Partition
                                                                                                                 // key
                        new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort
                                                                                                        // key
                .withProjection(
                        new Projection().withProjectionType("INCLUDE").withNonKeyAttributes("Description", "Status"));

        // TitleIndex
        GlobalSecondaryIndex titleIndex = new GlobalSecondaryIndex().withIndexName("TitleIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("Title").withKeyType(KeyType.HASH), // Partition
                                                                                                            // key
                        new KeySchemaElement().withAttributeName("IssueId").withKeyType(KeyType.RANGE)) // Sort
                                                                                                        // key
                .withProjection(new Projection().withProjectionType("KEYS_ONLY"));

        // DueDateIndex
        GlobalSecondaryIndex dueDateIndex = new GlobalSecondaryIndex().withIndexName("DueDateIndex")
                .withProvisionedThroughput(ptIndex)
                .withKeySchema(new KeySchemaElement().withAttributeName("DueDate").withKeyType(KeyType.HASH)) // Partition
                                                                                                              // key
                .withProjection(new Projection().withProjectionType("ALL"));

        CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName)
                .withProvisionedThroughput(
                        new ProvisionedThroughput().withReadCapacityUnits((long) 1).withWriteCapacityUnits((long) 1))
                .withAttributeDefinitions(attributeDefinitions).withKeySchema(tableKeySchema)
                .withGlobalSecondaryIndexes(createDateIndex, titleIndex, dueDateIndex);

        System.out.println("Creating table " + tableName + "...");
        dynamoDB.createTable(createTableRequest);

        // Wait for table to become active
        System.out.println("Waiting for " + tableName + " to become ACTIVE...");
        try {
            Table table = dynamoDB.getTable(tableName);
            table.waitForActive();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void queryIndex(String indexName) {

        Table table = dynamoDB.getTable(tableName);

        System.out.println("\n***********************************************************\n");
        System.out.print("Querying index " + indexName + "...");

        Index index = table.getIndex(indexName);

        ItemCollection<QueryOutcome> items = null;

        QuerySpec querySpec = new QuerySpec();

        if (indexName == "CreateDateIndex") {
            System.out.println("Issues filed on 2013-11-01");
            querySpec.withKeyConditionExpression("CreateDate = :v_date and begins_with(IssueId, :v_issue)")
                    .withValueMap(new ValueMap().withString(":v_date", "2013-11-01").withString(":v_issue", "A-"));
            items = index.query(querySpec);
        } else if (indexName == "TitleIndex") {
            System.out.println("Compilation errors");
            querySpec.withKeyConditionExpression("Title = :v_title and begins_with(IssueId, :v_issue)")
                    .withValueMap(
                            new ValueMap().withString(":v_title", "Compilation error").withString(":v_issue", "A-"));
            items = index.query(querySpec);
        } else if (indexName == "DueDateIndex") {
            System.out.println("Items that are due on 2013-11-30");
            querySpec.withKeyConditionExpression("DueDate = :v_date")
                    .withValueMap(new ValueMap().withString(":v_date", "2013-11-30"));
            items = index.query(querySpec);
        } else {
            System.out.println("\nNo valid index name provided");
            return;
        }

        Iterator<Item> iterator = items.iterator();

        System.out.println("Query: printing results...");

        while (iterator.hasNext()) {
            System.out.println(iterator.next().toJSONPretty());
        }

    }

    public static void deleteTable(String tableName) {

        System.out.println("Deleting table " + tableName + "...");

        Table table = dynamoDB.getTable(tableName);
        table.delete();

        // Wait for table to be deleted
        System.out.println("Waiting for " + tableName + " to be deleted...");
        try {
            table.waitForDelete();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void loadData() {

        System.out.println("Loading data into table " + tableName + "...");

        // IssueId, Title,
        // Description,
        // CreateDate, LastUpdateDate, DueDate,
        // Priority, Status

        putItem("A-101", "Compilation error", "Can't compile Project X - bad version number. What does this mean?",
                "2013-11-01", "2013-11-02", "2013-11-10", 1, "Assigned");

        putItem("A-102", "Can't read data file", "The main data file is missing, or the permissions are incorrect",
                "2013-11-01", "2013-11-04", "2013-11-30", 2, "In progress");

        putItem("A-103", "Test failure", "Functional test of Project X produces errors", "2013-11-01", "2013-11-02",
                "2013-11-10", 1, "In progress");

        putItem("A-104", "Compilation error", "Variable 'messageCount' was not initialized.", "2013-11-15",
                "2013-11-16", "2013-11-30", 3, "Assigned");

        putItem("A-105", "Network issue", "Can't ping IP address 127.0.0.1. Please fix this.", "2013-11-15",
                "2013-11-16", "2013-11-19", 5, "Assigned");

    }

    public static void putItem(

            String issueId, String title, String description, String createDate, String lastUpdateDate, String dueDate,
            Integer priority, String status) {

        Table table = dynamoDB.getTable(tableName);

        Item item = new Item().withPrimaryKey("IssueId", issueId).withString("Title", title)
                .withString("Description", description).withString("CreateDate", createDate)
                .withString("LastUpdateDate", lastUpdateDate).withString("DueDate", dueDate)
                .withNumber("Priority", priority).withString("Status", status);

        table.putItem(item);
    }

}
```

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

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 globaux, décrire les index de la table et effectuer des requêtes à l'aide des index. Ces opérations mappent aux opérations DynamoDB correspondantes. Pour plus d'informations, consultez la [Référence d'API Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/). 

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. 

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

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

Vous pouvez créer des index secondaires globaux au moment où vous créez une table. Pour ce faire, utilisez `CreateTable` et fournissez vos spécifications pour un ou plusieurs index secondaires globaux. L'exemple de code C\$1 suivant crée une table destinée à accueillir des données météorologiques. La clé de partition est `Location`, et la clé de tri `Date`. Un index secondaire global nommé `PrecipIndex` permet un accès rapide aux données de précipitations pour différents endroits.

Voici les étapes à suivre pour créer une table avec un index secondaire global à 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 global, vous devez fournir le nom de l'index, ses paramètres de débit approvisionné, les définitions d'attribut pour 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 (`WeatherData`) avec un index secondaire global (`PrecipIndex`). La clé de partition d'index est `Date`, et la clé de tri `Precipitation`. Tous les attributs de table sont projetés sur l'index. Les utilisateurs peuvent interroger cet index afin d'obtenir des données météorologiques pour une date particulière, en triant éventuellement les données par quantité de précipitations. 

`Precipitation` n'étant pas un attribut de clé pour la table, il n'est pas obligatoire. Toutefois, les éléments `WeatherData` sans `Precipitation` n'apparaissent pas dans `PrecipIndex`.

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

// Attribute definitions
var attributeDefinitions = new List<AttributeDefinition>()
{
    {new AttributeDefinition{
        AttributeName = "Location",
        AttributeType = "S"}},
    {new AttributeDefinition{
        AttributeName = "Date",
        AttributeType = "S"}},
    {new AttributeDefinition(){
        AttributeName = "Precipitation",
        AttributeType = "N"}
    }
};

// Table key schema
var tableKeySchema = new List<KeySchemaElement>()
{
    {new KeySchemaElement {
        AttributeName = "Location",
        KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement {
        AttributeName = "Date",
        KeyType = "RANGE"}  //Sort key
    }
};

// PrecipIndex
var precipIndex = new GlobalSecondaryIndex
{
    IndexName = "PrecipIndex",
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)10,
        WriteCapacityUnits = (long)1
    },
    Projection = new Projection { ProjectionType = "ALL" }
};

var indexKeySchema = new List<KeySchemaElement> {
    {new KeySchemaElement { AttributeName = "Date", KeyType = "HASH"}},  //Partition key
    {new KeySchemaElement{AttributeName = "Precipitation",KeyType = "RANGE"}}  //Sort key
};

precipIndex.KeySchema = indexKeySchema;

CreateTableRequest createTableRequest = new CreateTableRequest
{
    TableName = tableName,
    ProvisionedThroughput = new ProvisionedThroughput
    {
        ReadCapacityUnits = (long)5,
        WriteCapacityUnits = (long)1
    },
    AttributeDefinitions = attributeDefinitions,
    KeySchema = tableKeySchema,
    GlobalSecondaryIndexes = { precipIndex }
};

CreateTableResponse response = client.CreateTable(createTableRequest);
Console.WriteLine(response.CreateTableResult.TableDescription.TableName);
Console.WriteLine(response.CreateTableResult.TableDescription.TableStatus);
```

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 global
<a name="GSILowLevelDotNet.DescribeTableWithIndex"></a>

Pour obtenir des informations concernant les index secondaires globaux sur une table, utilisez l'opération `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 global pour une table à l'aide de l'API de bas niveau .NET. 

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

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

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

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

**Example**  

```
client = new AmazonDynamoDBClient();
string tableName = "WeatherData";

DescribeTableResponse response = client.DescribeTable(new DescribeTableRequest { TableName = tableName});

List<GlobalSecondaryIndexDescription> globalSecondaryIndexes =
response.DescribeTableResult.Table.GlobalSecondaryIndexes;

// This code snippet will work for multiple indexes, even though
// there is only one index in this example.

foreach (GlobalSecondaryIndexDescription gsiDescription in globalSecondaryIndexes) {
     Console.WriteLine("Info for index " + gsiDescription.IndexName + ":");

     foreach (KeySchemaElement kse in gsiDescription.KeySchema) {
          Console.WriteLine("\t" + kse.AttributeName + ": key type is " + kse.KeyType);
     }

      Projection projection = gsiDescription.Projection;
      Console.WriteLine("\tThe projection type is: " + projection.ProjectionType);

      if (projection.ProjectionType.ToString().Equals("INCLUDE")) {
           Console.WriteLine("\t\tThe non-key projected attributes are: "
                + projection.NonKeyAttributes);
      }
}
```

## Interroger un index secondaire global
<a name="GSILowLevelDotNet.QueryAnIndex"></a>

Vous pouvez utiliser l'opération `Query` sur un index secondaire global de la même manière que vous utilisez l'opération `Query` sur une table. Vous devez spécifier le nom de l'index, les critères de requête pour la clé de partition d'index et la clé de tri (le cas échéant), ainsi que les attributs que vous souhaitez renvoyer. Dans cet exemple, l'index est `PrecipIndex`. Il a une clé de partition `Date` et une clé de tri `Precipitation`. L'interrogation de l'index renvoie toutes les données météorologiques pour une date particulière, où les précipitations sont supérieures à zéro.

Voici les étapes à suivre pour interroger un index secondaire global à 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.

Nom d'attribut `Date` est un mot réservé DynamoDB. Par conséquent, vous devez utiliser un nom d'attribut d'expression comme espace réservé dans la `KeyConditionExpression`.

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

**Example**  

```
client = new AmazonDynamoDBClient();

QueryRequest queryRequest = new QueryRequest
{
    TableName = "WeatherData",
    IndexName = "PrecipIndex",
    KeyConditionExpression = "#dt = :v_date and Precipitation > :v_precip",
    ExpressionAttributeNames = new Dictionary<String, String> {
        {"#dt", "Date"}
    },
    ExpressionAttributeValues = new Dictionary<string, AttributeValue> {
        {":v_date", new AttributeValue { S =  "2013-08-01" }},
        {":v_precip", new AttributeValue { N =  "0" }}
    },
    ScanIndexForward = true
};

var result = client.Query(queryRequest);

var items = result.Items;
foreach (var currentItem in items)
{
    foreach (string attr in currentItem.Keys)
    {
        Console.Write(attr + "---> ");
        if (attr == "Precipitation")
        {
            Console.WriteLine(currentItem[attr].N);
    }
    else
    {
        Console.WriteLine(currentItem[attr].S);
    }

         }
     Console.WriteLine();
}
```

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

L'exemple de code C\$1 suivant montre comment utiliser des index secondaires globaux. L'exemple crée une table nommée `Issues`, utilisable dans un système simple de suivi de bogues pour le développement de logiciels. La clé de partition est `IssueId`, et la clé de tri `Title`. Il y a trois index secondaires globaux sur cette table :
+ `CreateDateIndex` – La clé de partition est `CreateDate`, et la clé de tri `IssueId`. En plus des clés de table, les attributs `Description` et `Status` sont projetés dans l'index.
+ `TitleIndex` – La clé de partition est `Title`, et la clé de tri `IssueId`. Aucun attribut autre que les clés de table n'est projeté dans l'index.
+ `DueDateIndex` – La clé de partition est `DueDate` et il n'y a pas de clé de tri. Tous les attributs de table sont projetés sur l'index.

Une fois la table `Issues` créée, le programme charge la table avec des données représentant des rapports de bogues logiciels. Il interroge ensuite les données à l'aide d'index secondaires globaux. Enfin, le programme supprime la table `Issues`.

Pour step-by-step obtenir des instructions sur le test de l'échantillon 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 LowLevelGlobalSecondaryIndexExample
    {
        private static AmazonDynamoDBClient client = new AmazonDynamoDBClient();
        public static String tableName = "Issues";

        public static void Main(string[] args)
        {
            CreateTable();
            LoadData();

            QueryIndex("CreateDateIndex");
            QueryIndex("TitleIndex");
            QueryIndex("DueDateIndex");

            DeleteTable(tableName);

            Console.WriteLine("To continue, press enter");
            Console.Read();
        }

        private static void CreateTable()
        {
            // Attribute definitions
            var attributeDefinitions = new List<AttributeDefinition>()
        {
            {new AttributeDefinition {
                 AttributeName = "IssueId", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "Title", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "CreateDate", AttributeType = "S"
             }},
            {new AttributeDefinition {
                 AttributeName = "DueDate", AttributeType = "S"
             }}
        };

            // Key schema for table
            var tableKeySchema = new List<KeySchemaElement>() {
            {
                new KeySchemaElement {
                    AttributeName= "IssueId",
                    KeyType = "HASH" //Partition key
                }
            },
            {
                new KeySchemaElement {
                    AttributeName = "Title",
                    KeyType = "RANGE" //Sort key
                }
            }
        };

            // Initial provisioned throughput settings for the indexes
            var ptIndex = new ProvisionedThroughput
            {
                ReadCapacityUnits = 1L,
                WriteCapacityUnits = 1L
            };

            // CreateDateIndex
            var createDateIndex = new GlobalSecondaryIndex()
            {
                IndexName = "CreateDateIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "CreateDate", KeyType = "HASH" //Partition key
                },
                new KeySchemaElement {
                    AttributeName = "IssueId", KeyType = "RANGE" //Sort key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "INCLUDE",
                    NonKeyAttributes = {
                    "Description", "Status"
                }
                }
            };

            // TitleIndex
            var titleIndex = new GlobalSecondaryIndex()
            {
                IndexName = "TitleIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "Title", KeyType = "HASH" //Partition key
                },
                new KeySchemaElement {
                    AttributeName = "IssueId", KeyType = "RANGE" //Sort key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "KEYS_ONLY"
                }
            };

            // DueDateIndex
            var dueDateIndex = new GlobalSecondaryIndex()
            {
                IndexName = "DueDateIndex",
                ProvisionedThroughput = ptIndex,
                KeySchema = {
                new KeySchemaElement {
                    AttributeName = "DueDate",
                    KeyType = "HASH" //Partition key
                }
            },
                Projection = new Projection
                {
                    ProjectionType = "ALL"
                }
            };



            var createTableRequest = new CreateTableRequest
            {
                TableName = tableName,
                ProvisionedThroughput = new ProvisionedThroughput
                {
                    ReadCapacityUnits = (long)1,
                    WriteCapacityUnits = (long)1
                },
                AttributeDefinitions = attributeDefinitions,
                KeySchema = tableKeySchema,
                GlobalSecondaryIndexes = {
                createDateIndex, titleIndex, dueDateIndex
            }
            };

            Console.WriteLine("Creating table " + tableName + "...");
            client.CreateTable(createTableRequest);

            WaitUntilTableReady(tableName);
        }

        private static void LoadData()
        {
            Console.WriteLine("Loading data into table " + tableName + "...");

            // IssueId, Title,
            // Description,
            // CreateDate, LastUpdateDate, DueDate,
            // Priority, Status

            putItem("A-101", "Compilation error",
                "Can't compile Project X - bad version number. What does this mean?",
                "2013-11-01", "2013-11-02", "2013-11-10",
                1, "Assigned");

            putItem("A-102", "Can't read data file",
                "The main data file is missing, or the permissions are incorrect",
                "2013-11-01", "2013-11-04", "2013-11-30",
                2, "In progress");

            putItem("A-103", "Test failure",
                "Functional test of Project X produces errors",
                "2013-11-01", "2013-11-02", "2013-11-10",
                1, "In progress");

            putItem("A-104", "Compilation error",
                "Variable 'messageCount' was not initialized.",
                "2013-11-15", "2013-11-16", "2013-11-30",
                3, "Assigned");

            putItem("A-105", "Network issue",
                "Can't ping IP address 127.0.0.1. Please fix this.",
                "2013-11-15", "2013-11-16", "2013-11-19",
                5, "Assigned");
        }

        private static void putItem(
            String issueId, String title,
            String description,
            String createDate, String lastUpdateDate, String dueDate,
            Int32 priority, String status)
        {
            Dictionary<String, AttributeValue> item = new Dictionary<string, AttributeValue>();

            item.Add("IssueId", new AttributeValue
            {
                S = issueId
            });
            item.Add("Title", new AttributeValue
            {
                S = title
            });
            item.Add("Description", new AttributeValue
            {
                S = description
            });
            item.Add("CreateDate", new AttributeValue
            {
                S = createDate
            });
            item.Add("LastUpdateDate", new AttributeValue
            {
                S = lastUpdateDate
            });
            item.Add("DueDate", new AttributeValue
            {
                S = dueDate
            });
            item.Add("Priority", new AttributeValue
            {
                N = priority.ToString()
            });
            item.Add("Status", new AttributeValue
            {
                S = status
            });

            try
            {
                client.PutItem(new PutItemRequest
                {
                    TableName = tableName,
                    Item = item
                });
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
        }

        private static void QueryIndex(string indexName)
        {
            Console.WriteLine
                ("\n***********************************************************\n");
            Console.WriteLine("Querying index " + indexName + "...");

            QueryRequest queryRequest = new QueryRequest
            {
                TableName = tableName,
                IndexName = indexName,
                ScanIndexForward = true
            };


            String keyConditionExpression;
            Dictionary<string, AttributeValue> expressionAttributeValues = new Dictionary<string, AttributeValue>();

            if (indexName == "CreateDateIndex")
            {
                Console.WriteLine("Issues filed on 2013-11-01\n");

                keyConditionExpression = "CreateDate = :v_date and begins_with(IssueId, :v_issue)";
                expressionAttributeValues.Add(":v_date", new AttributeValue
                {
                    S = "2013-11-01"
                });
                expressionAttributeValues.Add(":v_issue", new AttributeValue
                {
                    S = "A-"
                });
            }
            else if (indexName == "TitleIndex")
            {
                Console.WriteLine("Compilation errors\n");

                keyConditionExpression = "Title = :v_title and begins_with(IssueId, :v_issue)";
                expressionAttributeValues.Add(":v_title", new AttributeValue
                {
                    S = "Compilation error"
                });
                expressionAttributeValues.Add(":v_issue", new AttributeValue
                {
                    S = "A-"
                });

                // Select
                queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES";
            }
            else if (indexName == "DueDateIndex")
            {
                Console.WriteLine("Items that are due on 2013-11-30\n");

                keyConditionExpression = "DueDate = :v_date";
                expressionAttributeValues.Add(":v_date", new AttributeValue
                {
                    S = "2013-11-30"
                });

                // Select
                queryRequest.Select = "ALL_PROJECTED_ATTRIBUTES";
            }
            else
            {
                Console.WriteLine("\nNo valid index name provided");
                return;
            }

            queryRequest.KeyConditionExpression = keyConditionExpression;
            queryRequest.ExpressionAttributeValues = expressionAttributeValues;

            var result = client.Query(queryRequest);
            var items = result.Items;
            foreach (var currentItem in items)
            {
                foreach (string attr in currentItem.Keys)
                {
                    if (attr == "Priority")
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].N);
                    }
                    else
                    {
                        Console.WriteLine(attr + "---> " + currentItem[attr].S);
                    }
                }
                Console.WriteLine();
            }
        }

        private static void DeleteTable(string tableName)
        {
            Console.WriteLine("Deleting table " + tableName + "...");
            client.DeleteTable(new DeleteTableRequest
            {
                TableName = tableName
            });
            WaitForTableToBeDeleted(tableName);
        }

        private static void WaitUntilTableReady(string tableName)
        {
            string status = null;
            // Let us wait until table is created. Call DescribeTable.
            do
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                    status = res.Table.TableStatus;
                }
                catch (ResourceNotFoundException)
                {
                    // DescribeTable is eventually consistent. So you might
                    // get resource not found. So we handle the potential exception.
                }
            } while (status != "ACTIVE");
        }

        private static void WaitForTableToBeDeleted(string tableName)
        {
            bool tablePresent = true;

            while (tablePresent)
            {
                System.Threading.Thread.Sleep(5000); // Wait 5 seconds.
                try
                {
                    var res = client.DescribeTable(new DescribeTableRequest
                    {
                        TableName = tableName
                    });

                    Console.WriteLine("Table name: {0}, status: {1}",
                              res.Table.TableName,
                              res.Table.TableStatus);
                }
                catch (ResourceNotFoundException)
                {
                    tablePresent = false;
                }
            }
        }
    }
}
```

# Gestion des index secondaires globaux dans DynamoDB à l’aide de l’AWS CLI
<a name="GCICli"></a>

Vous pouvez utiliser l’AWS CLI pour créer une table Amazon DynamoDB avec un ou plusieurs index secondaires globaux, 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 global](#GCICli.CreateTableWithIndex)
+ [Ajouter un index secondaire global à une table existante](#GCICli.CreateIndexAfterTable)
+ [Décrire une table avec un index secondaire global](#GCICli.DescribeTableWithIndex)
+ [Interroger un index secondaire global](#GCICli.QueryAnIndex)

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

Vous pouvez créer des index secondaires globaux 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 globaux. L’exemple suivant crée une table nommée `GameScores` avec un index secondaire global nommé `GameTitleIndex`. La table de base a une clé de partition `UserId` et une clé de tri `GameTitle`, vous permettant de trouver efficacement le meilleur score d’un utilisateur pour un jeu spécifique, tandis que l’index secondaire global (GSI) a une clé de partition `GameTitle` et une clé de tri `TopScore`, vous permettant de trouver rapidement le score le plus élevé pour un jeu particulier.

```
aws dynamodb create-table \
    --table-name GameScores \
    --attribute-definitions AttributeName=UserId,AttributeType=S \
                            AttributeName=GameTitle,AttributeType=S \
                            AttributeName=TopScore,AttributeType=N  \
    --key-schema AttributeName=UserId,KeyType=HASH \
                 AttributeName=GameTitle,KeyType=RANGE \
    --provisioned-throughput ReadCapacityUnits=10,WriteCapacityUnits=5 \
    --global-secondary-indexes \
        "[
            {
                \"IndexName\": \"GameTitleIndex\",
                \"KeySchema\": [{\"AttributeName\":\"GameTitle\",\"KeyType\":\"HASH\"},
                                {\"AttributeName\":\"TopScore\",\"KeyType\":\"RANGE\"}],
                \"Projection\":{
                    \"ProjectionType\":\"INCLUDE\",
                    \"NonKeyAttributes\":[\"UserId\"]
                },
                \"ProvisionedThroughput\": {
                    \"ReadCapacityUnits\": 10,
                    \"WriteCapacityUnits\": 5
                }
            }
        ]"
```

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.

## Ajouter un index secondaire global à une table existante
<a name="GCICli.CreateIndexAfterTable"></a>

Vous pouvez également ajouter ou modifier des index secondaires globaux après la création de la table. Pour ce faire, utilisez le paramètre `update-table` et fournissez vos spécifications pour un ou plusieurs index secondaires globaux. L’exemple suivant utilise le même schéma que l’exemple précédent, mais part du principe que la table a déjà été créée et que nous ajoutons le GSI par la suite.

```
aws dynamodb update-table \
    --table-name GameScores \
    --attribute-definitions AttributeName=TopScore,AttributeType=N  \
    --global-secondary-index-updates \
        "[
            {
                \"Create\": {
                    \"IndexName\": \"GameTitleIndex\",
                    \"KeySchema\": [{\"AttributeName\":\"GameTitle\",\"KeyType\":\"HASH\"},
                                    {\"AttributeName\":\"TopScore\",\"KeyType\":\"RANGE\"}],
                    \"Projection\":{
                        \"ProjectionType\":\"INCLUDE\",
                        \"NonKeyAttributes\":[\"UserId\"]
                    }
                }
            }
        ]"
```

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

Pour obtenir des informations concernant les index secondaires globaux 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 GameScores
```

## Interroger un index secondaire global
<a name="GCICli.QueryAnIndex"></a>

Vous pouvez utiliser l’opération `query` sur un index secondaire global 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 `GameTitleIndex` et la clé de tri d’index est `GameTitle`.

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](GSI.md#GSI.Projections).

```
aws dynamodb query --table-name GameScores\
    --index-name GameTitleIndex \
    --key-condition-expression "GameTitle = :v_game" \
    --expression-attribute-values '{":v_game":{"S":"Alien Adventure"} }'
```

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

# Gestion des flux complexes avec des transactions Amazon DynamoDB
<a name="transactions"></a>

Les transactions Amazon DynamoDB simplifient l'expérience des développeurs en apportant des modifications coordonnées all-or-nothing à plusieurs éléments à la fois au sein des tables et entre elles. Les transactions introduisent l’atomicité, la cohérence, l’isolation et la durabilité (ACID) dans DynamoDB, ce qui permet de maintenir facilement l’exactitude des données dans vos applications.

Vous pouvez utiliser la lecture et l' APIs écriture transactionnelles DynamoDB pour gérer des flux de travail métier complexes qui nécessitent l'ajout, la mise à jour ou la suppression de plusieurs éléments en une seule opération. all-or-nothing Par exemple, un développeur de jeux vidéo peut ainsi s’assurer que les profils des joueurs sont mis à jour correctement lorsqu’ils échangent des objets ou effectuent des achats dans un jeu.

Avec l’API d’écriture de transaction, vous pouvez regrouper plusieurs actions `Put`, `Update`, `Delete` et `ConditionCheck`. Ensuite, vous pouvez soumettre les actions comme une seule opération `TransactWriteItems` qui réussit ou échoue en tant qu’unité. Il en va de même avec les actions `Get`, que vous pouvez regrouper et soumettre en une seule opération `TransactGetItems`.

L’activation des transactions pour vos tables DynamoDB n’occasionne pas de frais supplémentaires . Vous ne payez que pour les lectures ou écritures qui font partie de votre transaction. DynamoDB effectue deux lectures ou écritures sous-jacentes de chaque élément faisant partie de la transaction : l’une pour préparer la transaction, l’autre pour la valider. Ces deux read/write opérations sous-jacentes sont visibles dans vos CloudWatch statistiques Amazon.

Pour commencer à utiliser les transactions DynamoDB, téléchargez le AWS dernier SDK ou le (). AWS Command Line Interface AWS CLI Suivez ensuite l’[Exemple de transactions DynamoDB](transaction-example.md).

Les sections suivantes fournissent un aperçu détaillé de la transaction APIs et de la manière dont vous pouvez les utiliser dans DynamoDB.

**Topics**
+ [Comment ça marche](transaction-apis.md)
+ [Utilisation d’IAM avec des transactions](transaction-apis-iam.md)
+ [Exemple de code](transaction-example.md)

# Fonctionnement de transactions Amazon DynamoDB
<a name="transaction-apis"></a>

Avec les transactions Amazon DynamoDB, vous pouvez regrouper plusieurs actions et les soumettre sous forme d'une all-or-nothing `TransactWriteItems` seule opération. `TransactGetItems` Les sections suivantes décrivent les opérations d’API, la gestion de la capacité, les bonnes pratiques et d’autres détails concernant l’utilisation des opérations transactionnelles dans DynamoDB.

**Topics**
+ [TransactWriteItems API](#transaction-apis-txwriteitems)
+ [TransactGetItems API](#transaction-apis-txgetitems)
+ [Niveaux d’isolement pour les transactions DynamoDB](#transaction-isolation)
+ [Gestion des conflits de transactions dans DynamoDB](#transaction-conflict-handling)
+ [Utilisation du mode transactionnel APIs dans DynamoDB Accelerator (DAX)](#transaction-apis-dax)
+ [Gestion de capacité pour les transactions](#transaction-capacity-handling)
+ [Bonnes pratiques en matière de transactions](#transaction-best-practices)
+ [Utilisation du mode transactionnel APIs avec des tables globales](#transaction-integration)
+ [Transactions DynamoDB par rapport à la bibliothèque cliente de transactions AWSLabs](#transaction-vs-library)

## TransactWriteItems API
<a name="transaction-apis-txwriteitems"></a>

`TransactWriteItems`est une opération d'écriture synchrone et idempotente qui regroupe jusqu'à 100 actions d'écriture en une seule opération. all-or-nothing Ces actions peuvent cibler jusqu'à 100 éléments distincts dans une ou plusieurs tables DynamoDB au sein du AWS même compte et de la même région. La taille d’agrégation des éléments dans la transaction ne peut pas dépasser 4 Mo. Les actions sont exécutées de manière atomique, de sorte qu’elles réussissent toutes ou aucune ne réussit.

**Note**  
 Une opération `TransactWriteItems` diffère d’une opération `BatchWriteItem` en ceci que toutes les actions qui y sont contenues doivent réussir, faute de quoi aucune modification du tout n’est apportée. Avec une opération `BatchWriteItem`, il est possible que certaines actions du lot seulement réussissent, alors que d’autres échouent. 
 Les transactions ne peuvent pas être effectuées au moyen d’index 

Vous ne pouvez pas cibler le même élément avec plusieurs opérations contenues dans la même transaction. Par exemple, vous ne pouvez pas effectuer un `ConditionCheck` et une action `Update` sur le même élément de la même transaction.

Vous pouvez ajouter les types d’actions suivants à une transaction :
+ `Put` – Lance une opération `PutItem` pour créer un élément ou remplacer un ancien élément par un nouveau, de manière conditionnelle ou sans spécifier de condition.
+ `Update` – Lance une opération `UpdateItem` pour modifier les attributs d’un élément existant, ou ajouter un élément à la table s’il n’existe pas. Utilisez cette action pour ajouter, supprimer ou mettre à jour des attributs d’un élément existant, avec ou sans conditions.
+ `Delete` – Lance une opération `DeleteItem` pour supprimer un élément unique d’une table identifiée par sa clé primaire.
+ `ConditionCheck` – Vérifie l’existence d’un élément ou l’état d’attributs spécifiques de celui-ci.

Lorsqu'une transaction est terminée dans DynamoDB, ses modifications commencent à se propager aux index secondaires globaux GSIs (), aux flux et aux sauvegardes. Cette propagation se produit progressivement : les enregistrements de flux d’une même transaction peuvent s’afficher à des moments différents et s’entrelacer avec des enregistrements d’autres transactions. Les consommateurs de flux ne doivent pas présumer de l’atomicité des transactions ou des garanties d’ordre.

Pour garantir un instantané atomique des éléments modifiés lors d'une transaction, utilisez l' TransactGetItems opération pour lire tous les éléments pertinents ensemble. Cette opération fournit une vue cohérente des données, vous permettant soit de voir toutes les modifications apportées à une transaction terminée, soit de n’en voir aucune.

La propagation n'étant pas immédiate, si une table est restaurée à partir de backup ([RestoreTableFromBackup](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_RestoreTableFromBackup.html)) ou exportée à un point dans le temps ([ExportTableToPointInTime](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_ExportTableToPointInTime.html)) en cours de propagation, elle ne peut contenir que certaines des modifications apportées lors d'une transaction récente.

### Idempotence
<a name="transaction-apis-txwriteitems-idempotency"></a>

En option, vous pouvez inclure un jeton client lorsque vous faites un appel `TransactWriteItems` afin de garantir l’*idempotence* de la demande. Des transactions idempotentes évitent des erreurs d’application si la même opération est soumise plusieurs fois suite à une expiration de la connexion ou à tout autre problème de connectivité.

Si l’appel initial de `TransactWriteItems` réussit, les appels suivants de `TransactWriteItems` avec le même jeton client aboutissent sans apporter aucune modification. Si le paramètre `ReturnConsumedCapacity` est défini, l’appel `TransactWriteItems` initial renvoie le nombre d’unités de capacité en écriture consommées par l’exécution de ces modifications. Les appels `TransactWriteItems` subséquents avec le même jeton client renvoient le nombre d’unités de capacité en lecture consommées par la lecture de l’élément.

**Considérations importantes concernant l’idempotence**
+ Un jeton client est valide pendant 10 minutes après la fin de la demande qui l’utilise. Après 10 minutes, toute demande utilisant le même jeton client est traitée comme une nouvelle demande. Évitez donc de réutiliser le même jeton client pour la même demande après 10 minutes.
+ Si vous répétez une demande avec le même jeton client dans la fenêtre d’idempotence de 10 minutes, mais modifiez un autre paramètre de demande, DynamoDB renvoie une exception `IdempotentParameterMismatch`.

### Gestion des erreurs d’écriture
<a name="transaction-apis-txwriteitems-errors"></a>

Les transactions d’écriture échouent dans les conditions suivantes :
+ Lorsqu’une condition d’une des expressions de condition n’est pas remplie.
+ Lorsqu’une erreur de validation de la transaction se produit parce que plusieurs actions de la même opération `TransactWriteItems` ciblent le même élément.
+ Lorsqu’une demande `TransactWriteItems` est en conflit avec une opération `TransactWriteItems` en cours sur un ou plusieurs éléments dans la demande `TransactWriteItems`. Dans ce cas, la demande échoue avec une exception `TransactionCanceledException`.
+ Lorsque la capacité allouée est insuffisante pour achever la transaction.
+ Lorsqu’un élément devient trop volumineux (plus de 400 ko), qu’un index secondaire local (LSI) devient trop volumineux ou qu’une erreur de validation similaire se produit en raison de modifications effectuées par la transaction.
+ En cas d’erreur de la part de l’utilisateur, par exemple un format de données incorrect.

 Pour en savoir plus sur la gestion des conflits avec les opérations `TransactWriteItems`, consultez [Gestion des conflits de transactions dans DynamoDB](#transaction-conflict-handling).

## TransactGetItems API
<a name="transaction-apis-txgetitems"></a>

`TransactGetItems` est une opération de lecture synchrone qui regroupe jusqu’à 100 actions `Get`. Ces actions peuvent cibler jusqu'à 100 éléments distincts dans une ou plusieurs tables DynamoDB au sein d'un même compte et d'une AWS même région. La taille d’agrégation des éléments dans la transaction ne peut pas dépasser 4 Mo. 

Les actions `Get` sont exécutées de manière atomique, de sorte qu’elles réussissent toutes ou échouent toutes.
+ `Get` – Lance une opération `GetItem` afin d’extraire un ensemble d’attributs pour l’élément avec la clé primaire donnée. Si aucun élément correspondant n’est trouvé, `Get` ne renvoie pas de données.

### Gestion des erreurs de lecture
<a name="transaction-apis-txgetitems-errors"></a>

Les transactions de lecture échouent dans les conditions suivantes :
+ Lorsqu’une demande `TransactGetItems` est en conflit avec une opération `TransactWriteItems` en cours sur un ou plusieurs éléments dans la demande `TransactGetItems`. Dans ce cas, la demande échoue avec une exception `TransactionCanceledException`.
+ Lorsque la capacité allouée est insuffisante pour achever la transaction.
+ En cas d’erreur de la part de l’utilisateur, par exemple un format de données incorrect.

 Pour en savoir plus sur la gestion des conflits avec les opérations `TransactGetItems`, consultez [Gestion des conflits de transactions dans DynamoDB](#transaction-conflict-handling).

## Niveaux d’isolement pour les transactions DynamoDB
<a name="transaction-isolation"></a>

Les niveaux d’isolement des opérations transactionnelles (`TransactWriteItems` ou `TransactGetItems`) et autres opérations sont les suivants.

### SERIALIZABLE
<a name="transaction-isolation-serializable"></a>

Un isolement *sérialisable* assure que les résultats de plusieurs opérations concourantes sont les mêmes que si aucune opération ne commençait avant que la précédente soit terminée.

Il y a un isolement sérialisable entre les types d’opérations suivants :
+ Entre toute opération transactionnelle et toute opération d’écriture standard (`PutItem`, `UpdateItem` ou `DeleteItem`).
+ Entre toute opération transactionnelle et toute opération de lecture standard (`GetItem`).
+ Entre une opération `TransactWriteItems` et une opération `TransactGetItems`.

Bien qu’il y ait un isolement sérialisable entre les opérations transactionnelles et chaque écriture individuelle d’une opération `BatchWriteItem`, il n’y en a pas entre la transaction et l’opération `BatchWriteItem` en tant qu’ensemble.

De même, le niveau d’isolation entre une opération transactionnelle et un `GetItems` dans une opération `BatchGetItem` est sérialisable. Mais le niveau d’isolation entre la transaction et l’opération `BatchGetItem` en tant qu’unité est *read-committed*.

Une demande `GetItem` unique est sérialisable par rapport à une demande `TransactWriteItems` de deux façons, avant ou après la demande `TransactWriteItems`. Plusieurs demandes `GetItem` par rapport à des clés dans une demande `TransactWriteItems` simultanée peuvent s’exécuter dans n’importe quel ordre. C’est pourquoi les résultats sont *validés en lecture*.

Par exemple, si des demandes `GetItem` pour des éléments A et B sont exécutées en même temps qu’une demande `TransactWriteItems` qui modifie les éléments A et B, il y a quatre possibilités :
+ Les deux demandes `GetItem` sont exécutées avant la demande `TransactWriteItems`.
+ Les deux demandes `GetItem` sont exécutées après la demande `TransactWriteItems`.
+ La demande `GetItem` pour l’élément A est exécutée avant la demande `TransactWriteItems`. Pour l’élément B, la demande `GetItem` est exécutée après la demande `TransactWriteItems`.
+ La demande `GetItem` pour l’élément B est exécutée avant la demande `TransactWriteItems`. Pour l’élément A, la demande `GetItem` est exécutée après la demande `TransactWriteItems`.

Vous devez utiliser la demande `TransactGetItems` si vous préférez un niveau d’isolement sérialisable pour plusieurs demandes `GetItem`.

Si une lecture non transactionnelle est effectuée sur plusieurs éléments faisant partie de la même demande d’écriture de transaction en cours, il est possible que vous puissiez lire le nouvel état de certains éléments et l’ancien état des autres éléments. Vous pouvez lire le nouvel état de tous les éléments qui faisaient partie de la demande d’écriture de transaction seulement en cas de réception d’une réponse de réussite de l’écriture de transaction indiquant que la transaction est terminée.

Une fois la transaction effectuée et la réponse reçue, les opérations ultérieures de lecture *cohérente à terme* peuvent toujours renvoyer l’ancien état pendant une courte période en raison du modèle de cohérence à terme de DynamoDB. Pour garantir la lecture du plus grand up-to-date nombre de données immédiatement après une transaction, vous devez utiliser des lectures [*très cohérentes*](HowItWorks.ReadConsistency.md#HowItWorks.ReadConsistency.Strongly) en définissant le paramètre `ConsistentRead` sur true.

### READ-COMMITTED
<a name="transaction-isolation-read-committed"></a>

L’isolement *validé en lecture* garantit que les opérations de lecture renvoient toujours des valeurs validées pour un élément. La lecture ne présentera jamais une vue de l’élément représentant un état issu d’une écriture transactionnelle qui n’a pas abouti. Un isolement validé en lecture n’empêche pas des modifications de l’élément juste après la lecture.

Le niveau d’isolement est validé en lecture entre toute opération transactionnelle et toute opération de lecture impliquant plusieurs lectures standard (`BatchGetItem`, `Query` ou `Scan`). Si une écriture transactionnelle met à jour un élément au milieu d’une opération `BatchGetItem`, `Query` ou `Scan`, la partie suivante de l’opération de lecture renvoie la valeur nouvellement validée (avec `ConsistentRead)` ou éventuellement une valeur déjà validée (lectures éventuellement cohérentes).

### Résumé des opérations
<a name="transaction-isolation-table"></a>

Pour résumer, le tableau qui suit montre les niveaux d’isolement entre une opération transactionnelle (`TransactWriteItems` ou `TransactGetItems`) et d’autres opérations :


| Opération | Niveau d’isolement | 
| --- | --- | 
| `DeleteItem` | *Sérialisable* | 
| `PutItem` | *Sérialisable* | 
| `UpdateItem` | *Sérialisable* | 
| `GetItem` | *Sérialisable* | 
| `BatchGetItem` | *Validé en lecture*\$1 | 
| `BatchWriteItem` | *NON sérialisable*\$1 | 
| `Query` | *Validé en lecture* | 
| `Scan` | *Validé en lecture* | 
| Autre opération transactionnelle | *Sérialisable* | 

Les niveaux marqués d’un astérisque (\$1) s’appliquent à l’opération dans son ensemble. Toutefois, les actions individuelles au sein de ces opérations ont un niveau d’isolement *sérialisable*.

## Gestion des conflits de transactions dans DynamoDB
<a name="transaction-conflict-handling"></a>

Un conflit transactionnel peut se produire lors de demandes simultanées au niveau de l’élément sur un élément au sein d’une transaction. Les conflits de transaction peuvent se produire dans les scénarios suivants : 
+ Une requête `PutItem`, `UpdateItem` ou `DeleteItem` pour un élément est en conflit avec une requête `TransactWriteItems` en cours qui inclut le même élément.
+ Un élément au sein d’une requête `TransactWriteItems` fait partie d’une autre requête `TransactWriteItems` en cours.
+ Un élément au sein d’une requête `TransactGetItems` fait partie d’une autre requête `TransactWriteItems`, `BatchWriteItem`, `PutItem`, `UpdateItem` ou `DeleteItem` en cours.

**Note**  
Quand une requête `PutItem`, `UpdateItem` ou `DeleteItem` est rejetée, la requête échoue avec un code `TransactionConflictException`. 
Si toute requête au niveau de l’élément au sein de `TransactWriteItems` ou `TransactGetItems` est rejetée, la requête échoue avec un code `TransactionCanceledException`. Si cette demande échoue, AWS SDKs ne réessayez pas.  
Si vous utilisez le AWS SDK pour Java, l'exception contient la liste de [CancellationReasons](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_CancellationReason.html), ordonnée en fonction de la liste des éléments du paramètre de `TransactItems` demande. Pour d’autres langues, une représentation sous forme de chaîne de la liste est incluse dans le message d’erreur de l’exception. 
Si une opération `TransactWriteItems` en cours ou une opération `TransactGetItems` est en conflit avec une demande `GetItem` concourante, les deux opérations peuvent réussir.

La [TransactionConflict CloudWatch métrique](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/metrics-dimensions.html) est incrémentée pour chaque demande échouée au niveau de l'élément.

## Utilisation du mode transactionnel APIs dans DynamoDB Accelerator (DAX)
<a name="transaction-apis-dax"></a>

Les demandes `TransactWriteItems` et `TransactGetItems` sont toutes deux prises en charge dans DynamoDB Accelerator (DAX) avec les mêmes niveaux d’isolement que dans DynamoDB.

La demande `TransactWriteItems` écrit via DAX. DAX transmet un appel `TransactWriteItems` à DynamoDB et renvoie la réponse. Pour remplir le cache après l’écriture, DAX appelle `TransactGetItems` en arrière-plan pour chaque élément dans l’opération `TransactWriteItems`, qui consomme des unités de capacité de lecture supplémentaires. (Pour en savoir plus, consultez [Gestion de capacité pour les transactions](#transaction-capacity-handling).) Cette fonctionnalité vous permet de simplifier la logique de votre application et d’utiliser DAX pour les opérations transactionnelles et non transactionnelles.

Les appels `TransactGetItems` sont transmis via DAX sans les éléments mis en cache localement. Il s'agit du même comportement que pour une lecture très cohérente APIs dans DAX.

## Gestion de capacité pour les transactions
<a name="transaction-capacity-handling"></a>

L'activation des transactions pour vos tables DynamoDB n'occasionne pas de frais supplémentaires . Vous ne payez que pour les lectures ou écritures qui font partie de votre transaction. DynamoDB effectue deux lectures ou écritures sous-jacentes de chaque élément faisant partie de la transaction : l’une pour préparer la transaction, l’autre pour la valider. Les deux read/write opérations sous-jacentes sont visibles dans vos CloudWatch statistiques Amazon.

Planifiez les lectures et écritures supplémentaires requises par le protocole transactionnel APIs lorsque vous allouez de la capacité à vos tables. Par exemple, supposons que votre application exécute une transaction par seconde et que chaque transaction écrit trois éléments de 500 octets dans votre table. Chaque article nécessite deux unités de capacité d'écriture (WCUs) : une pour préparer la transaction et une pour valider la transaction. Par conséquent, vous devez en fournir six WCUs à la table. 

Si vous utilisiez DynamoDB Accelerator (DAX) dans l'exemple précédent, vous utiliseriez également deux unités de capacité de lecture RCUs () pour chaque élément de l'appel. `TransactWriteItems` Vous devrez donc en prévoir six supplémentaires RCUs à la table.

De même, si votre application exécute une transaction de lecture par seconde et que chaque transaction lit trois éléments de 500 octets dans votre table, vous devez fournir six unités de capacité de lecture (RCUs) à la table. La lecture de chaque élément en nécessite deux RCUs : un pour préparer la transaction et un pour valider la transaction.

En outre, le comportement par défaut du SDK est de ressayer les transactions en cas d’exception `TransactionInProgressException`. Prévoyez les unités de capacité de lecture supplémentaires (RCUs) consommées par ces nouvelles tentatives. Il en va de même si vous réessayez des transactions dans votre propre code à l’aide d’un `ClientRequestToken`.

## Bonnes pratiques en matière de transactions
<a name="transaction-best-practices"></a>

Lorsque vous utilisez des transactions DynamoDB, prenez en compte les bonnes pratiques recommandées suivantes.
+ Activez la scalabilité automatique sur vos tables ou veillez à allouer suffisamment de capacité de débit pour effectuer les deux opérations de lecture et écriture pour chaque élément de votre transaction.
+ Si vous n'utilisez pas le SDK AWS fourni, incluez un `ClientRequestToken` attribut lorsque vous effectuez un `TransactWriteItems` appel pour vous assurer que la demande est idempotente.
+ Ne regroupez pas d’opérations en une transaction si ce n’est pas nécessaire. Par exemple, si une transaction unique avec 10 opérations peut être subdivisée en plusieurs transactions sans compromettre l’exactitude de l’application, nous recommandons de scinder la transaction. Des transactions plus simples améliorent le débit et sont plus susceptibles de réussir. 
+ Si plusieurs transactions mettent à jour simultanément les mêmes éléments, il peut y avoir des conflits qui annulent ces transactions. Nous recommandons de suivre les bonnes pratiques DynamoDB en matière de modélisation des données pour minimiser de tels conflits.
+ Si un ensemble d’attributs est souvent mis à jour sur plusieurs éléments dans le cadre d’une seule et même transaction, envisagez de regrouper les attributs dans un seul élément afin de réduire la portée de la transaction.
+ Évitez d’utiliser des transactions pour ingérer des données en masse. Pour les écritures en masse, il est préférable d’utiliser `BatchWriteItem`.

## Utilisation du mode transactionnel APIs avec des tables globales
<a name="transaction-integration"></a>

Les opérations transactionnelles fournissent des garanties d'atomicité, de cohérence, d'isolation et de durabilité (ACID) uniquement dans la AWS région où l'API d'écriture a été invoquée. Les transactions des tables globales ne sont pas prises en charge dans toutes les régions. Par exemple, supposons que vous disposiez d’une table globale avec des réplicas dans les régions USA Est (Ohio) et USA Ouest (Oregon) et que vous effectuiez une opération `TransactWriteItems` dans la région USA Est (Virginie du Nord). Vous risquez d’observer des transactions partiellement terminées dans la région USA Ouest (Oregon) lorsque les modifications sont répliquées. Les modifications ne sont répliquées dans les autres régions qu’une fois validées dans la région source.

## Transactions DynamoDB par rapport à la bibliothèque cliente de transactions AWSLabs
<a name="transaction-vs-library"></a>

Les transactions DynamoDB constituent un remplacement plus rentable, plus robuste et plus performant de [AWSLabs](https://github.com/awslabs)la bibliothèque cliente de transactions. Nous vous suggérons de mettre à jour vos applications pour utiliser la transaction native côté serveur. APIs

# Utilisation d’IAM avec des transactions DynamoDB
<a name="transaction-apis-iam"></a>

Vous pouvez utiliser Gestion des identités et des accès AWS (IAM) pour restreindre les actions que les opérations transactionnelles peuvent effectuer dans Amazon DynamoDB. Pour en savoir plus sur l’utilisation de politiques IAM dans DynamoDB, consultez [Politiques basées sur l’identité pour DynamoDB](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies).

Les autorisations pour `Put`, `Update`, `Delete` et `Get` sont régies par celle utilisées pour les opérations `PutItem`, `UpdateItem`, `DeleteItem` et `GetItem` sous-jacentes. Pour l’action `ConditionCheck`, vous pouvez utiliser l’autorisation `dynamodb:ConditionCheckItem` dans des politiques IAM.

Vous trouverez ci-dessous des exemples de politiques IAM que vous pouvez utiliser pour configurer des transactions DynamoDB.

## Exemple 1 : autoriser les opérations transactionnelles
<a name="tx-policy-example-1"></a>

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ]
        }
    ]
}
```

------

## Exemple 2 : autoriser uniquement les opérations transactionnelles
<a name="tx-policy-example-2"></a>

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ],
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "dynamodb:EnclosingOperation": [
                        "TransactWriteItems",
                        "TransactGetItems"
                    ]
                }
            }
        }
    ]
}
```

------

## Exemple 3 : autoriser les lectures et écritures non transactionnelles, bloquer les lectures et écritures transactionnelles
<a name="tx-policy-example-3"></a>

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": [
                "arn:aws:dynamodb:*:*:table/table04"
            ],
            "Condition": {
                "ForAnyValue:StringEquals": {
                    "dynamodb:EnclosingOperation": [
                        "TransactWriteItems",
                        "TransactGetItems"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
             "Action": [
                 "dynamodb:PutItem",
                 "dynamodb:DeleteItem",
                 "dynamodb:GetItem",
                 "dynamodb:UpdateItem"
             ],
             "Resource": [
                 "arn:aws:dynamodb:*:*:table/table04"
             ]
         }
    ]
}
```

------

## Exemple 4 : Empêcher le renvoi d'informations en ConditionCheck cas de panne
<a name="tx-policy-example-4"></a>

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:ConditionCheckItem",
                "dynamodb:PutItem",
                "dynamodb:UpdateItem",
                "dynamodb:DeleteItem",
                "dynamodb:GetItem"
            ],
            "Resource": "arn:aws:dynamodb:*:*:table/table01",
            "Condition": {
                "StringEqualsIfExists": {
                    "dynamodb:ReturnValues": "NONE"
                }
            }
        }
    ]
}
```

------

# Exemple de transactions DynamoDB
<a name="transaction-example"></a>

A titre d'exemple de situation dans laquelle des transactions Amazon DynamoDB peuvent être utiles, considérez cette application Java pour une place de marché en ligne.

L'application dispose de trois tables DynamoDB dans le backend :
+ `Customers` – Cette table stocke des détails sur les clients de la place de marché. Sa clé primaire est un identifiant unique `CustomerId`.
+ `ProductCatalog` – Ce tableau stocke des détails tels que le prix et la disponibilité des produits en vente sur la place de marché. Sa clé primaire est un identifiant unique `ProductId`.
+ `Orders` – Cette table stocke des détails sur les commandes en provenance de la place de marché. Sa clé primaire est un identifiant unique `OrderId`.

## Passation d'une commande
<a name="transaction-example-write-order"></a>

Les extraits de code suivants montrent comment utiliser des transactions DynamoDB pour coordonner les différentes étapes de la création et du traitement d'une commande. L'utilisation d'une seule all-or-nothing opération garantit qu'en cas d'échec d'une partie de la transaction, aucune action de la transaction n'est exécutée et aucune modification n'est apportée.

Dans cet exemple, vous configurez une commande à partir d'un client dont le `customerId` est `09e8e9c8-ec48`. Vous l'exécutez ensuite en tant que transaction unique à l'aide du simple flux de traitement de commandes suivant :

1. Déterminez si l'ID client est valide.

1. Assurez-vous que l'état du produit est `IN_STOCK` et mettez à jour son état en `SOLD`.

1. Assurez-vous que la commande n'existe pas déjà, puis créez la commande.

### Valider le client
<a name="transaction-example-order-part-a"></a>

Commencez par définir une action pour vérifier qu'un client avec `customerId` égal à `09e8e9c8-ec48` existe dans la table client.

```
final String CUSTOMER_TABLE_NAME = "Customers";
final String CUSTOMER_PARTITION_KEY = "CustomerId";
final String customerId = "09e8e9c8-ec48";
final HashMap<String, AttributeValue> customerItemKey = new HashMap<>();
customerItemKey.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));

ConditionCheck checkCustomerValid = new ConditionCheck()
    .withTableName(CUSTOMER_TABLE_NAME)
    .withKey(customerItemKey)
    .withConditionExpression("attribute_exists(" + CUSTOMER_PARTITION_KEY + ")");
```

### Mettre à jour l'état du produit
<a name="transaction-example-order-part-b"></a>

Ensuite, définissez une action pour mettre à jour l'état du produit sur `SOLD` si la condition que l'état du produit soit actuellement défini sur `IN_STOCK` est `true`. La définition du paramètre `ReturnValuesOnConditionCheckFailure` a pour effet de renvoyer l'article si l'attribut d'état de produit de celui-ci n'est pas `IN_STOCK`.

```
final String PRODUCT_TABLE_NAME = "ProductCatalog";
final String PRODUCT_PARTITION_KEY = "ProductId";
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
expressionAttributeValues.put(":new_status", new AttributeValue("SOLD"));
expressionAttributeValues.put(":expected_status", new AttributeValue("IN_STOCK"));

Update markItemSold = new Update()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey)
    .withUpdateExpression("SET ProductStatus = :new_status")
    .withExpressionAttributeValues(expressionAttributeValues)
    .withConditionExpression("ProductStatus = :expected_status")
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD);
```

### Créer la commande
<a name="transaction-example-order-part-c"></a>

Enfin, créez la commande pour autant qu'il n'existe pas de commande avec cet `OrderId`.

```
final String ORDER_PARTITION_KEY = "OrderId";
final String ORDER_TABLE_NAME = "Orders";

HashMap<String, AttributeValue> orderItem = new HashMap<>();
orderItem.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));
orderItem.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));
orderItem.put(CUSTOMER_PARTITION_KEY, new AttributeValue(customerId));
orderItem.put("OrderStatus", new AttributeValue("CONFIRMED"));
orderItem.put("OrderTotal", new AttributeValue("100"));

Put createOrder = new Put()
    .withTableName(ORDER_TABLE_NAME)
    .withItem(orderItem)
    .withReturnValuesOnConditionCheckFailure(ReturnValuesOnConditionCheckFailure.ALL_OLD)
    .withConditionExpression("attribute_not_exists(" + ORDER_PARTITION_KEY + ")");
```

### Exécuter la transaction
<a name="transaction-example-order-part-d"></a>

L'exemple suivant montre comment exécuter les actions définies précédemment en une seule all-or-nothing opération.

```
    Collection<TransactWriteItem> actions = Arrays.asList(
        new TransactWriteItem().withConditionCheck(checkCustomerValid),
        new TransactWriteItem().withUpdate(markItemSold),
        new TransactWriteItem().withPut(createOrder));

    TransactWriteItemsRequest placeOrderTransaction = new TransactWriteItemsRequest()
        .withTransactItems(actions)
        .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

    // Run the transaction and process the result.
    try {
        client.transactWriteItems(placeOrderTransaction);
        System.out.println("Transaction Successful");

    } catch (ResourceNotFoundException rnf) {
        System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
    } catch (InternalServerErrorException ise) {
        System.err.println("Internal Server Error" + ise.getMessage());
    } catch (TransactionCanceledException tce) {
        System.out.println("Transaction Canceled " + tce.getMessage());
    }
```

## Lecture des détails de la commande
<a name="transaction-example-read-order"></a>

L'exemple suivant montre comment lire la commande terminée de manière transactionnelle dans les tables `Orders` et `ProductCatalog`.

```
HashMap<String, AttributeValue> productItemKey = new HashMap<>();
productItemKey.put(PRODUCT_PARTITION_KEY, new AttributeValue(productKey));

HashMap<String, AttributeValue> orderKey = new HashMap<>();
orderKey.put(ORDER_PARTITION_KEY, new AttributeValue(orderId));

Get readProductSold = new Get()
    .withTableName(PRODUCT_TABLE_NAME)
    .withKey(productItemKey);
Get readCreatedOrder = new Get()
    .withTableName(ORDER_TABLE_NAME)
    .withKey(orderKey);

Collection<TransactGetItem> getActions = Arrays.asList(
    new TransactGetItem().withGet(readProductSold),
    new TransactGetItem().withGet(readCreatedOrder));

TransactGetItemsRequest readCompletedOrder = new TransactGetItemsRequest()
    .withTransactItems(getActions)
    .withReturnConsumedCapacity(ReturnConsumedCapacity.TOTAL);

// Run the transaction and process the result.
try {
    TransactGetItemsResult result = client.transactGetItems(readCompletedOrder);
    System.out.println(result.getResponses());
} catch (ResourceNotFoundException rnf) {
    System.err.println("One of the table involved in the transaction is not found" + rnf.getMessage());
} catch (InternalServerErrorException ise) {
    System.err.println("Internal Server Error" + ise.getMessage());
} catch (TransactionCanceledException tce) {
    System.err.println("Transaction Canceled" + tce.getMessage());
}
```

# Récupération de données de modification avec Amazon DynamoDB
<a name="streamsmain"></a>

Bon nombre d’applications bénéficient de la récupération des modifications apportées aux éléments stockés dans une table DynamoDB au moment elles se produisent. Voici quelques exemples de cas d’utilisation.
+ Une application mobile populaire modifie des données dans une table DynamoDB au rythme de milliers de mises à jour par seconde. Une autre application capture et stocke les données relatives à ces mises à jour, fournissant des mesures near-real-time d'utilisation pour l'application mobile.
+ Une application financière modifie des données boursières dans une table DynamoDB. Différentes applications exécutées en parallèle suivent ces changements en temps réel value-at-risk, calculent et rééquilibrent automatiquement les portefeuilles en fonction de l'évolution du cours des actions.
+ Des capteurs dans des véhicules de transport et des équipements industriels envoient des données à une table DynamoDB. Différentes applications contrôlent les performances et envoient des alertes par messagerie lors de la détection d’un problème, prédisent des défaillances potentielles en appliquant des algorithmes de machine learning, et compressent et archivent les données dans Amazon Simple Storage Service (Amazon S3).
+ Une application envoie automatiquement des notifications sur les appareils mobiles de tous les amis dans un groupe dès qu’un ami télécharge une nouvelle image.
+ Un nouveau client ajoute des données à une table DynamoDB. Cet événement appelle une autre application qui envoie un e-mail de bienvenue au nouveau client.

DynamoDB prend en charge le streaming des enregistrements de récupération de données de modification au niveau élément en quasi-temps réel. Vous pouvez créer des applications qui consomment ces flux et entreprennent des actions basées sur le contenu.

**Note**  
L’ajout de balises à DynamoDB Streams et l’utilisation du [contrôle d’accès par attributs (ABAC)](access-control-resource-based.md) avec DynamoDB Streams ne sont pas pris en charge.

La vidéo suivante vous présente le concept de capture des données de modification.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/VVv_-mZ5Ge8/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/VVv_-mZ5Ge8)


**Topics**
+ [Options de streaming pour la récupération de données de modification](#streamsmain.choose)
+ [Utilisation de Kinesis Data Streams pour récupérer les modifications apportées à DynamoDB](kds.md)
+ [Modifier la récupération de données pour DynamoDB Streams](Streams.md)

## Options de streaming pour la récupération de données de modification
<a name="streamsmain.choose"></a>

DynamoDB offre deux modèles de streaming pour la récupération de données de modification : Kinesis Data Streams pour DynamoDB et DynamoDB Streams.

Afin de vous aider à choisir la solution appropriée pour votre application, le tableau suivant récapitule les fonctions de chaque modèle de streaming. 

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

Vous pouvez activer les deux modèles de streaming sur la même table DynamoDB.

La vidéo suivante évoque plus en détail les différences entre les deux options.

[![AWS Videos](http://img.youtube.com/vi/https://www.youtube.com/embed/UgG17Wh2y0g/0.jpg)](http://www.youtube.com/watch?v=https://www.youtube.com/embed/UgG17Wh2y0g)


# Utilisation de Kinesis Data Streams pour récupérer les modifications apportées à DynamoDB
<a name="kds"></a>

Vous pouvez utiliser Amazon Kinesis Data Streams pour capturer les modifications apportées à Amazon DynamoDB.

Kinesis Data Streams récupère les modifications au niveau élément dans n’importe quelle table DynamoDB et les réplique dans un [flux de données Kinesis](https://docs.aws.amazon.com/streams/latest/dev/introduction.html) de votre choix. Vos applications peuvent accéder à ce flux et afficher les modifications au niveau élément en quasi-temps réel. Vous pouvez récupérer et stocker en continu des téraoctets de données par heure. Vous pouvez profiter d’un temps de conservation des données plus long et, grâce à une capacité de déploiement améliorée, vous pouvez atteindre simultanément deux applications en aval ou plus. Les autres avantages incluent des audits et une transparence de sécurité supplémentaires.

Kinesis Data Streams vous donne également accès à [Amazon Data Firehose](https://docs.aws.amazon.com/firehose/latest/dev/what-is-this-service.html) et au [service géré Amazon pour Apache Flink](https://docs.aws.amazon.com/kinesisanalytics/latest/dev/what-is.html). Ces services peuvent vous aider à créer des applications qui alimentent des tableaux de bord en temps réel, génèrent des alertes, implémentent une tarification et une publicité dynamiques, et mettent en œuvre une analytique des données sophistiquée et des algorithmes de machine learning.

**Note**  
[L'utilisation des flux de données Kinesis pour DynamoDB est soumise à la fois à la tarification Kinesis Data Streams pour le flux de [données et à la tarification DynamoDB pour](https://aws.amazon.com/kinesis/data-streams/pricing/) la table source.](https://aws.amazon.com/dynamodb/pricing/)

Pour activer le streaming Kinesis sur une table DynamoDB à l'aide de la console ou du SDK Java AWS CLI, consultez. [Prise en main de Kinesis Data Streams pour Amazon DynamoDB](kds_gettingstarted.md)

**Topics**
+ [Comment Kinesis Data Streams fonctionne avec DynamoDB](#kds_howitworks)
+ [Prise en main de Kinesis Data Streams pour Amazon DynamoDB](kds_gettingstarted.md)
+ [Utilisation de partitions et de métriques avec DynamoDB Streams et Kinesis Data Streams](kds_using-shards-and-metrics.md)
+ [Utilisation de politiques IAM personnalisées pour Amazon Kinesis Data Streams et Amazon DynamoDB](kds_iam.md)

## Comment Kinesis Data Streams fonctionne avec DynamoDB
<a name="kds_howitworks"></a>

Lorsqu’un flux de données Kinesis est activé pour une table DynamoDB, la table envoie un enregistrement de données qui récupère toutes les modifications apportées aux données de cette table. Cet enregistrement de données comprend :
+ L’heure spécifique à laquelle un élément a été récemment créé, mis à jour ou supprimé
+ La clé primaire de cet élément
+ Un instantané de l’enregistrement avant la modification
+ Un instantané de l’enregistrement après la modification 

Ces enregistrements de données sont capturés et publiés en quasi-temps réel. Une fois écrits dans le flux de données Kinesis, ils peuvent être lus comme tout autre enregistrement. Vous pouvez utiliser la bibliothèque cliente Kinesis, utiliser AWS Lambda, appeler l'API Kinesis Data Streams et utiliser d'autres services connectés. Pour en savoir plus, consultez [Lecture de données à partir d’Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html) dans le Guide du développeur Amazon Kinesis Data Streams.

Ces modifications apportées aux données sont également récupérées de manière asynchrone. Kinesis n’a aucun impact sur les performances d’une table depuis laquelle elle est diffusée en continu. Les enregistrements de flux stockés dans votre flux de données Kinesis sont aussi chiffrés au repos. Pour en savoir plus, consultez [Protection des données dans Amazon Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/server-side-encryption.html).

Les enregistrements de flux de données Kinesis peuvent s’afficher dans un ordre différent de celui dans lequel les modifications des éléments ont eu lieu. Les mêmes notifications d’éléments peuvent également apparaître plusieurs fois dans le flux. Vous pouvez vérifier l’attribut `ApproximateCreationDateTime` pour identifier l’ordre dans lequel les modifications des éléments ont eu lieu et les enregistrements en double. 

Lorsque vous activez un flux de données Kinesis comme destination de streaming d’une table DynamoDB, vous pouvez configurer la précision des valeurs `ApproximateCreationDateTime` en millisecondes ou microsecondes. Par défaut, `ApproximateCreationDateTime` indique l’heure de la modification en millisecondes. De plus, vous pouvez modifier cette valeur sur une destination de streaming active. Après cette mise à jour, les enregistrements de flux écrits dans Kinesis ont des valeurs `ApproximateCreationDateTime` de la précision souhaitée. 

Les valeurs binaires écrites dans DynamoDB doivent être codées au [format codé en base64](HowItWorks.NamingRulesDataTypes.md). Toutefois, lorsque des enregistrements de données sont écrits dans un flux de données Kinesis, ces valeurs binaires codées sont codées une deuxième fois avec un codage base64. Lorsqu’il s’agit de lire ces enregistrements à partir d’un flux de données Kinesis, pour récupérer les valeurs binaires brutes, les applications doivent décoder ces valeurs deux fois.

DynamoDB facture l’utilisation de Kinesis Data Streams en unités de capture de données de modification. 1 Ko de modification par élément unique est considéré comme une unité de capture de données de modification. Le Ko de modification dans chaque élément est calculé par la plus grande des images « avant » et « après » de l’élément écrit dans le flux, en utilisant la même logique que [la consommation d’unités de capacité pour les opérations d’écriture](read-write-operations.md#write-operation-consumption). Comme pour le fonctionnement du mode [à la demande](capacity-mode.md#capacity-mode-on-demand) de DynamoDB, vous n’aurez pas besoin d’allouer le débit de capacité pour les unités de capture des données de modification.

### Activer un flux de données Kinesis pour votre table DynamoDB
<a name="kds_howitworks.enabling"></a>

Vous pouvez activer ou désactiver le streaming vers Kinesis à partir de votre table DynamoDB existante à l'aide du AWS SDK ou du AWS Management Console(). AWS Command Line Interface AWS CLI
+ Vous ne pouvez diffuser des données de DynamoDB vers Kinesis Data Streams que dans le même AWS compte et dans AWS la même région que votre table. 
+ Vous pouvez uniquement diffuser des données depuis une table DynamoDB vers un flux de données Kinesis.

  

### Modification d’une destination Kinesis Data Streams de votre table DynamoDB
<a name="kds_howitworks.makingchanges"></a>

Par défaut, tous les enregistrements de flux de données Kinesis incluent un attribut `ApproximateCreationDateTime`. Cet attribut représente un horodatage en millisecondes de l’heure approximative à laquelle chaque enregistrement a été créé. Vous pouvez modifier la précision de ces valeurs à l'aide du fichier [https://console.aws.amazon.com/kinesis](https://console.aws.amazon.com/kinesis), du SDK ou du AWS CLI 

# Prise en main de Kinesis Data Streams pour Amazon DynamoDB
<a name="kds_gettingstarted"></a>

Cette section explique comment utiliser les tables Kinesis Data Streams pour Amazon DynamoDB avec la console Amazon DynamoDB, le () et l'API. AWS Command Line Interface AWS CLI

## Création d’un flux de données Amazon Kinesis actif
<a name="kds_gettingstarted.making-changes"></a>

Tous ces exemples utilisent la table DynamoDB `Music` créée dans le cadre du tutoriel [Mise en route avec DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html).

Pour en savoir plus sur la façon de créer des consommateurs et de connecter votre flux de données Kinesis à d’autres services AWS , consultez [Lecture de données à partir de Kinesis Data Streams](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html) dans le *Guide du développeur Amazon Kinesis Data Streams*.

**Note**  
 Lorsque vous utilisez les partitions KDS pour la première fois, nous vous recommandons de les configurer de manière à ce que leur capacité s’adapte à la hausse ou à la baisse en fonction de vos modèles d’utilisation. Une fois que vous aurez accumulé davantage de données sur les modèles d’utilisation, vous pourrez ajuster les partitions de votre flux en conséquence. 

------
#### [ Console ]

1. Connectez-vous à la console Kinesis AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/kinesis/](https://console.aws.amazon.com/kinesis/)

1. Choisissez **Create data stream (Créer un flux de données)**, puis suivez les instructions pour créer un flux appelé `samplestream`. 

1. Ouvrez la console DynamoDB à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le volet de navigation sur le côté gauche de la console, choisissez **Tables**.

1. Choisissez la table **Music**.

1. Choisissez l’onglet **Exportations et flux**.

1. (Facultatif) Sous **Informations sur le flux de données Amazon Kinesis**, vous pouvez modifier la précision de l’horodatage des enregistrements de microseconde (par défaut) à milliseconde. 

1. Choisissez **samplestream** dans la liste déroulante.

1. Cliquez sur le bouton **Activer**.

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

1. Créez un flux de données Kinesis nommé `samplestream` à l’aide de la [commande create-stream](https://docs.aws.amazon.com/cli/latest/reference/kinesis/create-stream.html).

   ```
   aws kinesis create-stream --stream-name samplestream --shard-count 3 
   ```

   Consultez [Considérations relatives à la gestion des partitions pour Kinesis Data Streams](kds_using-shards-and-metrics.md#kds_using-shards-and-metrics.shardmanagment) avant de définir le nombre de partitions du flux de données Kinesis.

1. Vérifiez que le flux Kinesis est actif et prêt pour utilisation à l’aide de la [commande describe-stream](https://docs.aws.amazon.com/cli/latest/reference/kinesis/describe-stream.html).

   ```
   aws kinesis describe-stream --stream-name samplestream
   ```

1. Activez le streaming Kinesis sur la table DynamoDB à l’aide de la commande DynamoDB `enable-kinesis-streaming-destination`. Remplacez la valeur `stream-arn` par celle que la commande `describe-stream` a renvoyée à l’étape précédente. Activez éventuellement le streaming avec une précision plus détaillée (microseconde) des valeurs d’horodatage renvoyées sur chaque enregistrement.

   Activez le streaming avec une précision d’horodatage de l’ordre de la microseconde :

   ```
   aws dynamodb enable-kinesis-streaming-destination \
     --table-name Music \
     --stream-arn arn:aws:kinesis:us-west-2:12345678901:stream/samplestream
     --enable-kinesis-streaming-configuration ApproximateCreationDateTimePrecision=MICROSECOND
   ```

   Ou activez le streaming avec la précision d’horodatage par défaut (milliseconde) :

   ```
   aws dynamodb enable-kinesis-streaming-destination \
     --table-name Music \
     --stream-arn arn:aws:kinesis:us-west-2:12345678901:stream/samplestream
   ```

1. Vérifiez si le streaming Kinesis est actif sur la table à l’aide de la commande DynamoDB `describe-kinesis-streaming-destination`.

   ```
   aws dynamodb describe-kinesis-streaming-destination --table-name Music
   ```

1. Écrivez des données dans la table DynamoDB à l’aide de la commande `put-item`, comme décrit dans le [Guide du développeur DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-2.html).

   ```
   aws dynamodb put-item \
       --table-name Music  \
       --item \
           '{"Artist": {"S": "No One You Know"}, "SongTitle": {"S": "Call Me Today"}, "AlbumTitle": {"S": "Somewhat Famous"}, "Awards": {"N": "1"}}'
   
   aws dynamodb put-item \
       --table-name Music \
       --item \
           '{"Artist": {"S": "Acme Band"}, "SongTitle": {"S": "Happy Day"}, "AlbumTitle": {"S": "Songs About Life"}, "Awards": {"N": "10"} }'
   ```

1. Utilisez la commande CLI [get-records](https://docs.aws.amazon.com/cli/latest/reference/kinesis/get-records.html) de Kinesis pour extraire le contenu du flux Kinesis. Ensuite, utilisez l’extrait de code suivant pour désérialiser le contenu du flux.

   ```
   /**
    * Takes as input a Record fetched from Kinesis and does arbitrary processing as an example.
    */
   public void processRecord(Record kinesisRecord) throws IOException {
       ByteBuffer kdsRecordByteBuffer = kinesisRecord.getData();
       JsonNode rootNode = OBJECT_MAPPER.readTree(kdsRecordByteBuffer.array());
       JsonNode dynamoDBRecord = rootNode.get("dynamodb");
       JsonNode oldItemImage = dynamoDBRecord.get("OldImage");
       JsonNode newItemImage = dynamoDBRecord.get("NewImage");
       Instant recordTimestamp = fetchTimestamp(dynamoDBRecord);
   
       /**
        * Say for example our record contains a String attribute named "stringName" and we want to fetch the value
        * of this attribute from the new item image. The following code fetches this value.
        */
       JsonNode attributeNode = newItemImage.get("stringName");
       JsonNode attributeValueNode = attributeNode.get("S"); // Using DynamoDB "S" type attribute
       String attributeValue = attributeValueNode.textValue();
       System.out.println(attributeValue);
   }
   
   private Instant fetchTimestamp(JsonNode dynamoDBRecord) {
       JsonNode timestampJson = dynamoDBRecord.get("ApproximateCreationDateTime");
       JsonNode timestampPrecisionJson = dynamoDBRecord.get("ApproximateCreationDateTimePrecision");
       if (timestampPrecisionJson != null && timestampPrecisionJson.equals("MICROSECOND")) {
           return Instant.EPOCH.plus(timestampJson.longValue(), ChronoUnit.MICROS);
       }
       return Instant.ofEpochMilli(timestampJson.longValue());
   }
   ```

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

1. Suivez les instructions du Guide du développeur Kinesis Data Streams pour [créer](https://docs.aws.amazon.com/streams/latest/dev/kinesis-using-sdk-java-create-stream.html) un flux de données Kinesis nommé `samplestream` à l’aide de Java.

   Consultez [Considérations relatives à la gestion des partitions pour Kinesis Data Streams](kds_using-shards-and-metrics.md#kds_using-shards-and-metrics.shardmanagment) avant de définir le nombre de partitions pour le flux de données Kinesis. 

1. Utilisez l’extrait de code suivant pour activer le streaming Kinesis sur la table DynamoDB. Activez éventuellement le streaming avec une précision plus détaillée (microseconde) des valeurs d’horodatage renvoyées sur chaque enregistrement. 

   Activez le streaming avec une précision d’horodatage de l’ordre de la microseconde :

   ```
   EnableKinesisStreamingConfiguration enableKdsConfig = EnableKinesisStreamingConfiguration.builder()
     .approximateCreationDateTimePrecision(ApproximateCreationDateTimePrecision.MICROSECOND)
     .build();
   
   EnableKinesisStreamingDestinationRequest enableKdsRequest = EnableKinesisStreamingDestinationRequest.builder()
     .tableName(tableName)
     .streamArn(kdsArn)
     .enableKinesisStreamingConfiguration(enableKdsConfig)
     .build();
   
   EnableKinesisStreamingDestinationResponse enableKdsResponse = ddbClient.enableKinesisStreamingDestination(enableKdsRequest);
   ```

   Ou activez le streaming avec la précision d’horodatage par défaut (milliseconde) :

   ```
   EnableKinesisStreamingDestinationRequest enableKdsRequest = EnableKinesisStreamingDestinationRequest.builder()
     .tableName(tableName)
     .streamArn(kdsArn)
     .build();
   
   EnableKinesisStreamingDestinationResponse enableKdsResponse = ddbClient.enableKinesisStreamingDestination(enableKdsRequest);
   ```

1. Suivez les instructions du *Guide du développeur Kinesis Data Streams* pour [lire](https://docs.aws.amazon.com/streams/latest/dev/building-consumers.html) le flux de données créé.

1. Utilisez l’extrait de code suivant pour désérialiser le contenu du flux

   ```
   /**
    * Takes as input a Record fetched from Kinesis and does arbitrary processing as an example.
    */
   public void processRecord(Record kinesisRecord) throws IOException {
       ByteBuffer kdsRecordByteBuffer = kinesisRecord.getData();
       JsonNode rootNode = OBJECT_MAPPER.readTree(kdsRecordByteBuffer.array());
       JsonNode dynamoDBRecord = rootNode.get("dynamodb");
       JsonNode oldItemImage = dynamoDBRecord.get("OldImage");
       JsonNode newItemImage = dynamoDBRecord.get("NewImage");
       Instant recordTimestamp = fetchTimestamp(dynamoDBRecord);
   
       /**
        * Say for example our record contains a String attribute named "stringName" and we wanted to fetch the value
        * of this attribute from the new item image, the below code would fetch this.
        */
       JsonNode attributeNode = newItemImage.get("stringName");
       JsonNode attributeValueNode = attributeNode.get("S"); // Using DynamoDB "S" type attribute
       String attributeValue = attributeValueNode.textValue();
       System.out.println(attributeValue);
   }
   
   private Instant fetchTimestamp(JsonNode dynamoDBRecord) {
       JsonNode timestampJson = dynamoDBRecord.get("ApproximateCreationDateTime");
       JsonNode timestampPrecisionJson = dynamoDBRecord.get("ApproximateCreationDateTimePrecision");
       if (timestampPrecisionJson != null && timestampPrecisionJson.equals("MICROSECOND")) {
           return Instant.EPOCH.plus(timestampJson.longValue(), ChronoUnit.MICROS);
       }
       return Instant.ofEpochMilli(timestampJson.longValue());
   }
   ```

------

## Modification d’un flux de données Amazon Kinesis actif
<a name="kds_gettingstarted.making-changes"></a>

Cette section décrit comment apporter des modifications à une configuration Kinesis Data Streams pour DynamoDB active à l'aide de la console et de l'API. AWS CLI 

**AWS Management Console**

1. Ouvrez la console DynamoDB à l'adresse [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Accédez à votre table.

1. Choisissez l’onglet **Exportations et flux**.

**AWS CLI**

1. Appelez `describe-kinesis-streaming-destination` pour vérifier que le stream est `ACTIVE`. 

1. Appelez `UpdateKinesisStreamingDestination`, comme dans cet exemple :

   ```
   aws dynamodb update-kinesis-streaming-destination --table-name enable_test_table --stream-arn arn:aws:kinesis:us-east-1:12345678901:stream/enable_test_stream --update-kinesis-streaming-configuration ApproximateCreationDateTimePrecision=MICROSECOND
   ```

1. Appelez `describe-kinesis-streaming-destination` pour vérifier que le stream est `UPDATING`.

1. Appelez `describe-kinesis-streaming-destination` régulièrement jusqu’à ce que le statut de streaming redevienne `ACTIVE`. Les mises à jour de précision de l’horodatage prennent effet généralement sous 5 minutes. Une fois ce statut mis à jour, cela indique que la mise à jour est terminée et que la nouvelle valeur de précision sera appliquée aux futurs enregistrements.

1. Écrivez dans la table à l’aide de `putItem`.

1. Utilisez la commande `get-records` de Kinesis pour récupérer le contenu du flux.

1. Vérifiez que la valeur `ApproximateCreationDateTime` des écritures possède la précision souhaitée.

**API Java**

1. Fournissez un extrait de code qui construit une demande `UpdateKinesisStreamingDestination` et une réponse `UpdateKinesisStreamingDestination`. 

1. Fournissez un extrait de code qui construit une demande `DescribeKinesisStreamingDestination` et une réponse `DescribeKinesisStreamingDestination response`.

1. Appelez `describe-kinesis-streaming-destination` régulièrement jusqu’à ce que le statut de streaming redevienne `ACTIVE`, indiquant que la mise à jour est terminée et que la nouvelle valeur de précision sera appliquée aux futurs enregistrements.

1. Effectuez des écritures sur la table.

1.  Lisez le flux et désérialisez son contenu.

1. Vérifiez que la valeur `ApproximateCreationDateTime` des écritures possède la précision souhaitée.

# Utilisation de partitions et de métriques avec DynamoDB Streams et Kinesis Data Streams
<a name="kds_using-shards-and-metrics"></a>

## Considérations relatives à la gestion des partitions pour Kinesis Data Streams
<a name="kds_using-shards-and-metrics.shardmanagment"></a>

Un flux de données Kinesis compte son débit dans les [partitions](https://docs.aws.amazon.com/streams/latest/dev/key-concepts.html). Dans Amazon Kinesis Data Streams, vous pouvez choisir entre le mode **à la demande** et le mode **provisionné** pour vos flux de données. 

Nous vous recommandons d’utiliser le mode à la demande pour votre flux de données Kinesis si votre charge de travail d’écriture DynamoDB est très variable et imprévisible. En mode à la demande, aucune planification de la capacité n’est nécessaire, car Kinesis Data Streams gère automatiquement les partitions afin de fournir le débit nécessaire.

En cas de charges de travail prévisibles, vous pouvez utiliser le mode provisionné pour votre flux de données Kinesis. En mode provisionné, vous devez spécifier le nombre de partitions du flux de données nécessaires pour accueillir les enregistrements de capture des données de modification provenant de DynamoDB. Pour déterminer le nombre de partitions dont le flux de données Kinesis aura besoin pour prendre en charge votre table DynamoDB, vous devez disposer des valeurs d’entrée suivantes :
+ Taille moyenne d’enregistrement de votre table DynamoDB en octets (`average_record_size_in_bytes`).
+ Nombre maximum d’opérations d’écriture que votre table DynamoDB effectuera par seconde. Ce nombre inclut les opérations de création, de suppression et de mise à jour effectuées par vos applications, ainsi que les opérations générées automatiquement, comme les opérations de suppression générées par Time-to-Live (`write_throughput`).
+ Pourcentage d’opérations de mise à jour et de remplacement que vous effectuez sur votre table par rapport aux opérations de création ou de suppression (`percentage_of_updates`). N’oubliez pas que les opérations de mise à jour et de remplacement répliquent les anciennes et les nouvelles images de l’élément modifié dans le flux. Elles génèrent ainsi deux fois la taille de l’élément DynamoDB.

Vous pouvez calculer le nombre de partitions (`number_of_shards`) dont votre flux de données Kinesis a besoin à l’aide des valeurs d’entrée de la formule suivante :

```
number_of_shards = ceiling( max( ((write_throughput * (4+percentage_of_updates) * average_record_size_in_bytes) / 1024 / 1024), (write_throughput/1000)), 1)
```

Par exemple, vous pouvez avoir un débit maximal de 1 040 opérations d’écriture par seconde (`write_throughput`) avec une taille d’enregistrement moyenne de 800 octets (`average_record_size_in_bytes)`. Si 25 % de ces opérations d’écriture sont des opérations de mise à jour (`percentage_of_updates`), vous aurez besoin de deux partitions (`number_of_shards`) pour accueillir votre débit de streaming DynamoDB :

```
ceiling( max( ((1040 * (4+25/100) * 800)/ 1024 / 1024), (1040/1000)), 1).
```

Tenez compte des points suivants avant d’utiliser la formule de calcul du nombre de partitions requises en mode provisionné pour les flux de données Kinesis :
+ Cette formule permet d’estimer le nombre de partitions nécessaires pour accueillir vos enregistrements de données de modification DynamoDB. Elle ne représente pas le nombre total de partitions dont votre flux de données Kinesis a besoin, comme le nombre de partitions requises pour prendre en charge des consommateurs de flux de données Kinesis supplémentaires.
+ Vous pouvez toujours rencontrer des exceptions de débit de lecture et d’écriture en mode provisionné si vous ne configurez pas votre flux de données pour gérer votre débit maximal. Dans ce cas, vous devez mettre à l’échelle manuellement votre flux de données pour l’adapter à votre trafic de données. 
+ Cette formule prend en compte le gonflement supplémentaire généré par DynamoDB avant de diffuser les enregistrements de données du journal des modifications à Kinesis Data Streams.

Pour en savoir plus sur les modes de capacité de Kinesis Data Streams, consultez [Choix du mode de capacité du flux de données](https://docs.aws.amazon.com/streams/latest/dev/how-do-i-size-a-stream.html). Pour en savoir plus sur les différences tarifaires entre les différents modes de capacité, consultez la [Tarification d’Amazon Kinesis Data Streams](https://aws.amazon.com/kinesis/data-streams/pricing/).

## Surveiller la récupération de données de modification avec Kinesis Data Streams
<a name="kds_using-shards-and-metrics.monitoring"></a>

DynamoDB fournit plusieurs indicateurs CloudWatch Amazon pour vous aider à surveiller la réplication de la capture des données de modification vers Kinesis. Pour une liste complète des CloudWatch indicateurs, voir[Métriques et dimensions DynamoDB](metrics-dimensions.md).

Afin de déterminer si votre flux dispose d’une capacité suffisante, nous vous recommandons de contrôler les éléments suivants, tant pendant l’activation du flux qu’en production :
+ `ThrottledPutRecordCount` : nombre d’enregistrements limités par votre flux de données Kinesis en raison d’une capacité insuffisante de flux de données Kinesis. La valeur `ThrottledPutRecordCount` devrait rester aussi basse que possible, quoique vous pourriez rencontrer une certaine limitation lors de pics d’utilisation exceptionnels. DynamoDB réessaie d’envoyer des enregistrements limités dans le flux de données Kinesis, mais cela peut engendrer une latence de réplication plus élevée. 

  Si vous rencontrez une limitation excessive et régulière, il se peut que vous deviez augmenter le nombre de partitions de flux Kinesis en proportion du débit d’écriture observé de votre table. Pour en savoir plus sur la détermination de la taille d’un flux de données Kinesis, consultez [Détermination de la taille initiale d’un flux de données Kinesis](https://docs.aws.amazon.com/streams/latest/dev/amazon-kinesis-streams.html#how-do-i-size-a-stream).
+ `AgeOfOldestUnreplicatedRecord` : temps écoulé depuis que la modification au niveau élément la plus ancienne restant à répliquer vers le flux de données Kinesis est apparue dans la table DynamoDB. Dans des conditions normales de fonctionnement, la valeur `AgeOfOldestUnreplicatedRecord` devrait être de l’ordre de quelques millisecondes. Ce nombre augmente en fonction des tentatives de réplication infructueuses, lorsque celles-ci sont causées par des choix de configuration contrôlés par le client.

   Si la métrique `AgeOfOldestUnreplicatedRecord` dépasse 168 heures, la réplication des modifications apportées au niveau des éléments de la table DynamoDB dans le flux de données Kinesis est automatiquement désactivée.

  Les configurations contrôlées par le client qui peuvent entraîner des tentatives de réplication infructueuses sont, par exemple, une capacité de flux de données Kinesis sous-allouée causant une limitation excessive ou une mise à jour manuelle des stratégies d’accès de votre flux de données Kinesis empêchant DynamoDB d’ajouter des données à votre flux de données. Vous devrez peut-être allouer une capacité de flux de données Kinesis suffisante et vous assurer que les autorisations de DynamoDB sont inchangées pour que cette métrique reste aussi faible que possible. 
+ `FailedToReplicateRecordCount` : nombre d’enregistrements que DynamoDB n’a pas pu répliquer sur votre flux de données Kinesis. Certains éléments de plus de 34 Ko peuvent augmenter en taille pour modifier les enregistrements de données supérieurs à la limite de taille d’élément de 1 Mo de Kinesis Data Streams. Cette augmentation de taille se produit lorsque les éléments de plus de 34 Ko incluent un grand nombre de valeurs d’attribut booléennes ou vides. Les valeurs d’attribut booléennes et vides sont stockées sous la forme d’un octet dans DynamoDB. Toutefois, elles peuvent atteindre 5 octets lorsqu’elles sont sérialisées à l’aide de JSON standard pour la réplication Kinesis Data Streams. DynamoDB ne peut pas répliquer de tels enregistrements de modification dans votre flux de données Kinesis. DynamoDB ignore ces enregistrements de données de modification et continue automatiquement la réplication des enregistrements suivants. 

   

Vous pouvez créer des CloudWatch alarmes Amazon qui envoient un message Amazon Simple Notification Service (Amazon SNS) pour notification lorsque l'une des mesures précédentes dépasse un seuil spécifique. 

# Utilisation de politiques IAM personnalisées pour Amazon Kinesis Data Streams et Amazon DynamoDB
<a name="kds_iam"></a>

La première fois que vous activez Amazon Kinesis Data Streams pour Amazon DynamoDB, DynamoDB crée automatiquement Gestion des identités et des accès AWS un rôle lié à un service (IAM) pour vous. Ce rôle, `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication`, permet à DynamoDB de gérer pour vous la réplication des modifications au niveau élément dans Kinesis Data Streams. Ne supprimez pas ce rôle lié à un service.

Pour en savoir plus sur l’utilisation des rôles liés à un service, consultez [Utilisation des rôles liés à un service](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) dans le *Guide de l’utilisateur IAM*.

**Note**  
DynamoDB ne prend pas en charge les conditions basées sur une balise pour les politiques IAM.

Pour activer Amazon Kinesis Data Streams pour Amazon DynamoDB, vous devez disposer des autorisations suivantes sur la table.
+ `dynamodb:EnableKinesisStreamingDestination`
+ `kinesis:ListStreams`
+ `kinesis:PutRecords`
+ `kinesis:DescribeStream`

Pour décrire Amazon Kinesis Data Streams pour Amazon DynamoDB pour une table DynamoDB donnée, vous devez disposer des autorisations suivantes sur la table.
+ `dynamodb:DescribeKinesisStreamingDestination`
+ `kinesis:DescribeStreamSummary`
+ `kinesis:DescribeStream`

Pour désactiver Amazon Kinesis Data Streams pour Amazon DynamoDB, vous devez disposer des autorisations suivantes sur la table.
+ `dynamodb:DisableKinesisStreamingDestination`

Pour mettre à jour Amazon Kinesis Data Streams pour Amazon DynamoDB, vous devez disposer des autorisations suivantes sur la table.
+ `dynamodb:UpdateKinesisStreamingDestination`

Les exemples suivants montrent comment utiliser des politiques IAM afin d’accorder des autorisations pour Amazon Kinesis Data Streams pour Amazon DynamoDB.

## Exemple : Activer Amazon Kinesis Data Streams pour Amazon DynamoDB
<a name="access-policy-kds-example1"></a>

La politique IAM suivante octroie les autorisations nécessaires pour activer Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`. Elle n’accorde pas les autorisations permettant de désactiver, de mettre à jour ou de décrire Kinesis Data Streams pour DynamoDB pour la table `Music`. 

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "iam:CreateServiceLinkedRole",
            "Resource": "arn:aws:iam::*:role/aws-service-role/kinesisreplication.dynamodb.amazonaws.com/AWSServiceRoleForDynamoDBKinesisDataStreamsReplication",
            "Condition": {
                "StringLike": {
                    "iam:AWSServiceName": "kinesisreplication.dynamodb.amazonaws.com"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:EnableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Exemple : mise à jour Amazon Kinesis Data Streams pour Amazon DynamoDB
<a name="access-policy-kds-example2"></a>

La politique IAM suivante octroie les autorisations nécessaires pour mettre à jour Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`. Elle n’accorde pas les autorisations permettant d’activer, de désactiver ou de décrire Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`. 

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:UpdateKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Exemple : Désactiver Amazon Kinesis Data Streams pour Amazon DynamoDB
<a name="access-policy-kds-example2"></a>

La politique IAM suivante octroie les autorisations nécessaires pour désactiver Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`. Elle n’accorde pas les autorisations permettant d’activer, de mettre à jour ou de décrire Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`. 

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:DisableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        }
    ]
}
```

------

## Exemple : Appliquer de manière sélective des autorisations pour Amazon Kinesis Data Streams pour Amazon DynamoDB en fonction de la ressource
<a name="access-policy-kds-example3"></a>

La politique IAM suivante octroie les autorisations nécessaires pour activer et décrire Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Music`, et n’accorde pas les autorisations permettant de désactiver Amazon Kinesis Data Streams pour Amazon DynamoDB pour la table `Orders`. 

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

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "dynamodb:EnableKinesisStreamingDestination",
                "dynamodb:DescribeKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Music"
        },
        {
            "Effect": "Deny",
            "Action": [
                "dynamodb:DisableKinesisStreamingDestination"
            ],
            "Resource": "arn:aws:dynamodb:us-west-2:111122223333:table/Orders"
        }
    ]
}
```

------

## Utilisation de rôles liés à un service pour Kinesis Data Streams pour DynamoDB
<a name="kds-service-linked-roles"></a>

[Amazon Kinesis Data Streams pour Amazon Gestion des identités et des accès AWS DynamoDB utilise des rôles liés à un service (IAM).](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_terms-and-concepts.html#iam-term-service-linked-role) Un rôle lié à un service est un type unique de rôle IAM lié directement à Kinesis Data Streams pour DynamoDB. Les rôles liés à un service sont prédéfinis par Kinesis Data Streams for DynamoDB et incluent toutes les autorisations dont le service a besoin pour appeler d'autres services en votre nom. AWS 

Un rôle lié à un service simplifie la configuration de Kinesis Data Streams pour DynamoDB, car vous n’avez pas besoin d’ajouter manuellement les autorisations nécessaires. Kinesis Data Streams pour DynamoDB définit les autorisations de ses rôles liés à un service et, sauf définition contraire, seul Kinesis Data Streams pour DynamoDB peut endosser ses rôles. Les autorisations définies comprennent la politique d’approbation et la politique d’autorisation. De plus, cette politique d’autorisation ne peut pas être attachée à une autre entité IAM.

Pour plus d'informations sur les autres services qui prennent en charge les rôles liés à un service, veuillez consulter [Services AWS qui fonctionnent avec IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html) et recherchez les services où **Oui **figure dans la colonne **Rôle lié à un service**. Choisissez un **Oui** ayant un lien permettant de consulter les détails du rôle pour ce service.

### Autorisations de rôle lié à un service pour Kinesis Data Streams pour DynamoDB
<a name="slr-permissions"></a>

Kinesis Data Streams for DynamoDB utilise le rôle lié à un service nommé. **AWSServiceRoleForDynamoDBKinesisDataStreamsReplication** L’objectif du rôle lié à un service est d’autoriser Amazon DynamoDB à gérer pour vous la réplication des modifications au niveau élément dans Kinesis Data Streams.

Le rôle lié à un service `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` approuve les services suivants pour endosser le rôle :
+ `kinesisreplication.dynamodb.amazonaws.com`

La politique d’autorisations de rôle permet à Kinesis Data Streams pour DynamoDB d’accomplir les actions suivantes sur les ressources spécifiées :
+ Action : `Put records and describe` sur `Kinesis stream`
+ Action : `Generate data keys` activée pour placer les données `AWS KMS` dans les flux Kinesis chiffrés à l'aide de clés générées par l'utilisateur AWS KMS .

Pour le contenu exact du document de politique, voir [Dynamo. DBKinesis ReplicationServiceRolePolicy](https://console.aws.amazon.com/iam/home#policies/arn:aws:iam::aws:policy/aws-service-role/DynamoDBKinesisReplicationServiceRolePolicy)

Vous devez configurer les autorisations de manière à permettre à une entité IAM (comme un utilisateur, un groupe ou un rôle) de créer, modifier ou supprimer un rôle lié à un service. Pour en savoir plus, consultez [Service-Linked Role Permissions (autorisations du rôle lié à un service)](https://docs.aws.amazon.com/IAM/latest/UserGuide/contributorinsights-service-linked-roles.html#service-linked-role-permissions) dans le *Guide de l’utilisateur IAM*.

### Création d’un rôle lié à un service pour Kinesis Data Streams pour DynamoDB
<a name="create-slr"></a>

Vous n’avez pas besoin de créer manuellement un rôle lié à un service. Lorsque vous activez Kinesis Data Streams pour DynamoDB dans, dans ou dans AWS Management Console l'API, AWS CLI AWS Kinesis Data Streams for DynamoDB crée pour vous le rôle lié au service. 

Si vous supprimez ce rôle lié à un service et que vous avez ensuite besoin de le recréer, vous pouvez utiliser la même procédure pour recréer le rôle dans votre compte. Lorsque vous activez Kinesis Data Streams pour DynamoDB, le service crée pour vous le rôle lié à un service. 

### Modification d’un rôle lié à un service pour Kinesis Data Streams pour DynamoDB
<a name="edit-slr"></a>

Kinesis Data Streams pour DynamoDB ne vous permet pas de modifier le rôle lié à un service `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication`. Après avoir créé un rôle lié à un service, vous ne pouvez pas changer le nom du rôle, car plusieurs entités peuvent faire référence à ce rôle. Néanmoins, vous pouvez modifier la description du rôle à l’aide d’IAM. Pour en savoir plus, consultez [Modification d’un rôle lié à un service](https://docs.aws.amazon.com/IAM/latest/UserGuide/contributorinsights-service-linked-roles.html#edit-service-linked-role) dans le *Guide de l’utilisateur IAM*.

### Suppression d’un rôle lié à un service pour Kinesis Data Streams pour DynamoDB
<a name="delete-slr"></a>

Vous pouvez également utiliser la console IAM AWS CLI ou l' AWS API pour supprimer manuellement le rôle lié à un service. Pour ce faire, vous devez commencer par nettoyer les ressources de votre rôle lié à un service. Vous pouvez ensuite supprimer ce rôle manuellement.

**Note**  
Si le service Kinesis Data Streams pour DynamoDB utilise le rôle lorsque vous essayez de supprimer les ressources, la suppression peut échouer. Si cela se produit, patientez quelques minutes et réessayez.

**Pour supprimer manuellement le rôle lié au service à l’aide d’IAM**

Utilisez la console IAM, le AWS CLI, ou l' AWS API pour supprimer le rôle lié au `AWSServiceRoleForDynamoDBKinesisDataStreamsReplication` service. Pour en savoir plus, consultez [Suppression d’un rôle lié à un service](https://docs.aws.amazon.com/IAM/latest/UserGuide/using-service-linked-roles.html) dans le *Guide de l’utilisateur IAM*.

# Modifier la récupération de données pour DynamoDB Streams
<a name="Streams"></a>

 DynamoDB Streams récupère une séquence chronologique des modifications au niveau élément dans toute table DynamoDB et stocke ces informations dans un journal pendant jusqu’à 24 heures. Les applications ont accès à ce journal et affichent les éléments de données à mesure qu’ils s’affichent avant et après qu’ils ont été modifiés, pratiquement en temps réel.

 Le chiffrement au repos chiffre les données dans les flux DynamoDB Streams. Pour en savoir plus, consultez [Chiffrement de DynamoDB au repos](EncryptionAtRest.md).

Un *flux DynamoDB* est un flux ordonné d’informations sur les modifications apportées aux éléments d’une table DynamoDB. Lorsque vous activez un flux sur une table, DynamoDB récupère des informations sur chaque modification apportée à des éléments de données dans la table.

Chaque fois qu’une application crée, met à jour ou supprime des éléments dans la table, DynamoDB Streams écrit un enregistrement de flux avec le ou les attributs de clé primaire des éléments qui ont été modifiés. Un *registre de flux* contient des informations sur une modification de données dans un seul élément d’une table DynamoDB. Vous pouvez configurer le flux de telle sorte que les enregistrements de flux récupèrent des informations supplémentaires, telles que les images « avant » et « après » d’éléments modifiés.

DynamoDB Streams permet de s’assurer de ce qui suit :
+ Chaque enregistrement de flux s’affiche exactement une fois dans le flux.
+ Pour chaque élément modifié dans une table DynamoDB, les enregistrements de flux apparaissent dans l’ordre des modifications réelles.

DynamoDB Streams écrit les enregistrements de flux en quasi-temps réel, afin que vous puissiez créer des applications qui consomment ces flux et entreprennent des actions basées sur le contenu.

**Topics**
+ [Points de terminaison pour DynamoDB Streams](#Streams.Endpoints)
+ [Activation d’un flux](#Streams.Enabling)
+ [Lecture et traitement de flux](#Streams.Processing)
+ [DynamoDB Streams et time-to-live](time-to-live-ttl-streams.md)
+ [Utilisation de l’adaptateur DynamoDB Streams Kinesis pour traiter des enregistrements de flux](Streams.KCLAdapter.md)
+ [API de bas niveau DynamoDB Streams : exemple Java](Streams.LowLevel.Walkthrough.md)
+ [Streams et déclencheurs DynamoDB AWS Lambda](Streams.Lambda.md)
+ [DynamoDB Streams et Apache Flink](StreamsApacheFlink.xml.md)

## Points de terminaison pour DynamoDB Streams
<a name="Streams.Endpoints"></a>

AWS gère des points de terminaison distincts pour DynamoDB et DynamoDB Streams. Pour utiliser des tables et index de base de données, votre application doit accéder à un point de terminaison DynamoDB. Pour lire et traiter des enregistrements DynamoDB Streams, votre application doit pouvoir accéder à un point de terminaison DynamoDB Streams dans la même région.

DynamoDB Streams propose deux ensembles de points de terminaison. Il s'agit des options suivantes :
+ **IPv4-points de terminaison uniquement : points** de terminaison dotés de la `streams.dynamodb.<region>.amazonaws.com` convention de dénomination.
+ **Points de terminaison à double pile** : nouveaux points de terminaison compatibles avec les deux IPv4 IPv6 et conformes à la `streams-dynamodb.<region>.api.aws` convention de dénomination.

**Note**  
Pour accéder à la liste complète des régions et points de terminaison DynamoDB et DynamoDB Streams, consultez [Régions et points de terminaison](https://docs.aws.amazon.com/general/latest/gr/rande.html) dans *Références générales AWS*.

Ils AWS SDKs fournissent des clients distincts pour DynamoDB et DynamoDB Streams. En fonction de vos exigences, votre application peut accéder à un point de terminaison DynamoDB, un point de terminaison DynamoDB Streams, ou aux deux en même temps. Pour vous connecter aux deux points de terminaison, votre application doit instancier deux clients, l’un pour DynamoDB, et l’autre pour DynamoDB Streams.

## Activation d’un flux
<a name="Streams.Enabling"></a>

Vous pouvez activer un flux sur une nouvelle table lorsque vous le créez à l'aide du AWS CLI ou de l'un des AWS SDKs. Vous pouvez également activer ou désactiver un flux sur une table existante, ou modifier les paramètres d’un flux. DynamoDB Streams opérant de manière asynchrone, l’activation d’un flux n’a aucune incidence sur les performances d’une table.

La manière la plus simple de gérer DynamoDB Streams consiste à utiliser l’ AWS Management Console.

1. Connectez-vous à la console DynamoDB AWS Management Console et ouvrez-la à l'adresse. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Dans le tableau de bord de la console DynamoDB, choisissez **Tables**, puis sélectionnez une table.

1. Choisissez l’onglet **Exportations et flux**.

1. Dans la section **Détails du flux DynamoDB**, choisissez **Activer**.

1. Sur la page **Activer le flux DynamoDB**, choisissez les informations qui seront écrites dans le flux chaque fois que des données de la table seront modifiées :
   + **Attributs de clés uniquement** – Uniquement les attributs de clé de l’élément modifié.
   + **New image (Nouvelle image)** – L’élément entier, tel qu’il apparaît après sa modification.
   + **Old image (Ancienne image)** – L’élément entier, tel qu’il apparaissait avant sa modification.
   + **New and old images (Nouvelle et ancienne images)** – La nouvelle image et l’ancienne image de l’élément.

   Lorsque les paramètres vous conviennent, choisissez **Activer le streaming**.

1. (Facultatif) Pour désactiver un flux existant, choisissez **Désactiver** sous **Détails du flux DynamoDB**.

Vous pouvez également utiliser les API `CreateTable` ou `UpdateTable` pour activer ou modifier un flux. Le paramètre `StreamSpecification` détermine la façon dont le flux est configuré :
+ `StreamEnabled` – Spécifique si un flux de données est activé (`true`) ou désactivé (`false`) pour la table.
+ `StreamViewType` – Spécifie les informations à écrire dans le flux à chaque modification des données de la table :
  + `KEYS_ONLY` – Uniquement les attributs de clé de l’élément modifié.
  + `NEW_IMAGE` – L’élément entier, tel qu’il apparaît après sa modification.
  + `OLD_IMAGE` – L’élément entier, tel qu’il apparaissait avant sa modification.
  + `NEW_AND_OLD_IMAGES` – La nouvelle image et l’ancienne image de l’élément.

Vous pouvez activer ou désactiver un flux à tout moment. Cependant, vous recevez un `ValidationException` si vous essayez d’activer un flux sur une table qui en possède déjà un. Vous recevez également un `ValidationException` si vous essayez de désactiver un flux sur une table qui n’en possède pas.

Lorsque vous définissez `StreamEnabled` sur `true`, DynamoDB crée un flux avec un descripteur de flux unique qui lui est attribué. Si vous désactivez et puis réactivez un flux sur la table, un flux est créé avec un descripteur de flux différent.

Chaque flux est identifié de manière unique par un Amazon Resource Name (ARN). Voici un exemple d’ARN pour un flux sur une table DynamoDB nommée `TestTable`.

```
arn:aws:dynamodb:us-west-2:111122223333:table/TestTable/stream/2015-05-11T21:21:33.291
```

Pour déterminer le dernier descripteur de flux pour une table, émettez une demande DynamoDB `DescribeTable`, puis recherchez l’élément `LatestStreamArn` dans la réponse.

**Note**  
Il n’est pas possible de modifier un `StreamViewType` une fois qu’un flux a été configuré. Si vous devez apporter des modifications à un flux après sa configuration, vous devez désactiver le flux actuel et en créer un nouveau.

## Lecture et traitement de flux
<a name="Streams.Processing"></a>

Pour lire et traiter un flux, votre application doit se connecter à un point de terminaison DynamoDB Streams et émettre des demandes d’API.

Un flux se compose d’*enregistrements de flux*. Chaque enregistrement de flux représente une modification de donnée unique dans la table DynamoDB à laquelle le flux appartient. Chaque enregistrement de flux se voit attribuer un numéro de séquence, ce qui reflète l’ordre dans lequel l’enregistrement a été publié dans le flux.

Les enregistrements de flux sont organisés en groupes, ou *partitions*. Chaque partition agit comme un conteneur pour plusieurs enregistrements de flux et contient les informations requises pour accéder à ces enregistrements et les itérer. Les enregistrements de flux au sein d’une partition sont automatiquement supprimés au bout de 24 heures.

Les partitions sont éphémères. Elles sont créées et supprimées automatiquement, en fonction des besoins. Toute partition peut également se diviser en plusieurs partitions nouvelles. Cela se produit également automatiquement. (Notez qu’il est aussi possible pour une partition parent d’avoir une seule partition enfant). Une partition peut se diviser en réponse à des niveaux élevés d’activité d’écriture sur sa table parent, de telle sorte que les applications puissent traiter les enregistrements issus de plusieurs partitions en parallèle.

Si vous désactivez un flux, toute partition ouverte sera fermée. Les données du flux restent lisibles pendant 24 heures.

Comme les partitions ont une lignée (parent et enfants), une application doit toujours traiter une partition parent avant de traiter une partition enfant. Cela garantit que les enregistrements de flux sont également traités dans l’ordre adéquat. (Si vous utilisez l’adaptateur DynamoDB Streams Kinesis, cela est géré automatiquement. Votre application traite les partitions et les enregistrements de flux dans l’ordre correct. Elle gère automatiquement les partitions nouvelles ou ayant expiré, en plus des partitions qui ont été scindées pendant l’exécution de l’application. Pour plus d’informations, consultez [Utilisation de l’adaptateur DynamoDB Streams Kinesis pour traiter des enregistrements de flux](Streams.KCLAdapter.md).)

Le schéma suivant illustre la relation entre un flux de données, les partitions dans le flux et les enregistrements de flux dans les partitions.

![\[Structure de DynamoDB Streams. Les enregistrements de flux qui représentent des modifications de données sont organisés en partitions.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/streams-terminology.png)


**Note**  
Si vous effectuez une opération `PutItem` ou `UpdateItem` qui ne modifie aucune donnée dans un élément, DynamoDB Streams n’écrit *pas* d’enregistrement de flux pour cette opération.

Pour accéder à un flux de données et traiter les enregistrements de flux qu’il contient, vous devez effectuer les opérations suivantes :
+ Déterminer l’Amazon Resource Name (ARN) unique du flux auquel vous souhaitez accéder.
+ Déterminer quelles sont la ou les partitions du flux qui contiennent les enregistrements de flux qui vous intéressent.
+ Accéder aux partitions et récupérer les enregistrements de flux que vous voulez.

**Note**  
Deux processus au maximum doivent lire simultanément à partir de la même partition de flux. Avoir plus de 2 lecteurs par partition peut entraîner une limitation.

L’API DynamoDB Streams fournit les actions suivantes à l’usage des programmes d’application :
+  `[ListStreams](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_ListStreams.html)` – Renvoie la liste des descripteurs de flux pour le compte et le point de terminaison actuels. Vous pouvez en option demander uniquement les descripteurs de flux pour un nom de table particulier.
+ `[DescribeStream](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_DescribeStream.html)` – Renvoie des informations sur un flux, y compris le statut actuel du flux, son Amazon Resource Name (ARN), la composition de ses partitions et sa table DynamoDB correspondante. Vous pouvez éventuellement récupérer la partition enfant associée à la partition parent à l’aide du champ `ShardFilter`.
+ `[GetShardIterator](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_GetShardIterator.html)` – Renvoie un *itérateur de partition* décrivant un emplacement au sein d’une partition. Vous pouvez demander que l’itérateur fournisse un accès au point le plus ancien, au point le plus récent ou à un point particulier dans le flux.
+ `[GetRecords](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_streams_GetRecords.html)` – Renvoie les enregistrements de flux à partir d’une partition donnée. Vous devez fournir l’itérateur de partition renvoyé à partir d’une requête `GetShardIterator`.

Pour obtenir une description complète de ces opérations d’API, y compris des exemples de demandes et de réponses, consultez la [Référence des API Amazon DynamoDB Streams](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Operations_Amazon_DynamoDB_Streams.html).

### Découverte de partitions
<a name="Streams.ShardDiscovery"></a>



Découvrez de nouvelles partitions dans votre flux DynamoDB à l’aide de deux méthodes puissantes. En tant qu’utilisateur d’Amazon DynamoDB Streams, vous disposez de deux méthodes efficaces pour suivre et identifier de nouvelles partitions :

**Interrogation de l’ensemble de la topologie du flux**  
Interrogez régulièrement le flux à l’aide de l’API `DescribeStream`. Celle-ci renvoie toutes les partitions du flux, y compris celles qui ont été créées. En comparant les résultats au fil du temps, vous pouvez détecter les partitions ajoutées récemment.

**Découverte de partitions enfants**  
Recherchez un sous-ensemble de partitions à l’aide de l’API `DescribeStream` avec le paramètre `ShardFilter`. En spécifiant une partition parent dans la demande, DynamoDB Streams renvoie ses partitions enfants immédiates. Cette approche est utile lorsque vous avez uniquement besoin de suivre la lignée des partitions sans analyser l’intégralité du flux.   
Les applications consommant des données de DynamoDB Streams peuvent passer efficacement de la lecture d’une partition fermée à sa partition enfant à l’aide du paramètre `ShardFilter`, évitant ainsi des appels répétés à l’API `DescribeStream` afin de récupérer et de parcourir la carte des partitions à la recherche des partitions fermées et ouvertes. Vous pouvez ainsi découvrir rapidement les partitions enfants après la fermeture d’une partition parent, ce qui rend vos applications de traitement de flux plus réactives et plus économiques.

Les deux méthodes vous permettent de suivre l’évolution de la structure de vos flux DynamoDB, afin de ne jamais manquer les mises à jour de données ou les modifications critiques de partitions.

### Limite de conservation des données pour DynamoDB Streams
<a name="Streams.DataRetention"></a>

Toutes les données dans DynamoDB Streams ont un time-to-live de 24 heures. Vous pouvez extraire et analyser les 24 dernières heures d’activité d’une table donnée. Cependant, les données datant de plus de 24 heures sont susceptibles d’être supprimées à tout moment.

Si vous désactivez un flux sur une table, les données du flux continueront d’être lisibles pendant 24 heures. Passé ce délai, les données expirent et les enregistrements de flux sont supprimés automatiquement. Il n’existe pas de mécanisme pour supprimer manuellement un flux existant. Vous devez attendre que la limite de rétention expire (24 heures) et tous les enregistrements de flux seront supprimés.

# DynamoDB Streams et time-to-live
<a name="time-to-live-ttl-streams"></a>

Vous pouvez sauvegarder, ou traiter de toute autre façon, les éléments supprimés par [Time-to-live](TTL.md) (TTL) en activant Amazon DynamoDB Streams sur la table et en traitant les enregistrements de flux des éléments expirés. Pour en savoir plus, consultez [Lecture et traitement de flux](Streams.md#Streams.Processing).

L’enregistrement de flux contient un champ d’identité utilisateur `Records[<index>].userIdentity`.

Les éléments supprimés par le processus Time-to-live après expiration ont les champs suivants :
+ `Records[<index>].userIdentity.type`

  `"Service"`
+ `Records[<index>].userIdentity.principalId`

  `"dynamodb.amazonaws.com"`

**Note**  
Lorsque vous utilisez le processus TTL dans une table globale, le champ `userIdentity` est défini dans la région dans laquelle ce processus a été effectué. Ce champ n’est pas défini dans les autres régions lorsque la suppression est répliquée.

Le JSON suivant montre la partie pertinente d’un seul enregistrement de flux.

```
"Records": [
    {
        ...

        "userIdentity": {
            "type": "Service",
            "principalId": "dynamodb.amazonaws.com"
        }

        ...

    }
]
```

## Utilisation de DynamoDB Streams et Lambda pour archiver les éléments supprimés TTL
<a name="streams-archive-ttl-deleted-items"></a>

La combinaison de la [DynamoDB time-to-live (TTL)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html), de [DynamoDB Streams](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Streams.html), et de [AWS Lambda](https://aws.amazon.com/lambda/) peut permettre de simplifier l’archivage des données, de réduire les coûts de stockage de DynamoDB et de réduire la complexité du code. L’utilisation de Lambda comme consommateur de flux offre de nombreux avantages, notamment la réduction des coûts par rapport à d’autres consommateurs tels que Kinesis Client Library (KCL). Vous n’êtes pas facturé pour les appels d’API `GetRecords` sur votre flux DynamoDB lorsque vous utilisez Lambda pour consommer des événements, et Lambda peut fournir un filtrage d’événements en identifiant les modèles JSON dans un événement de flux. Avec le filtrage de contenu des modèles d’événements, vous pouvez définir jusqu’à cinq filtres différents pour contrôler quels événements sont envoyés à Lambda en vue d’être traités. Cela permet de réduire les appels de vos fonctions Lambda, de simplifier le code et de réduire le coût global.

Alors que DynamoDB Streams contient toutes les modifications de données, telles que les actions `Create`, `Modify` et `Remove`, cela peut entraîner des appels indésirables de votre fonction Lambda d’archivage. Par exemple, supposons que vous ayez une table contenant 2 millions de modifications de données par heure dans le flux, mais que moins de 5 % d’entre elles soient des suppressions d’éléments qui expireront via le processus TTL et devront être archivées. Avec les [filtres de source d’événement Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html), la fonction Lambda n’effectue que 100 000 appels par heure. Il en résulte que le filtrage des événements vous est facturé uniquement pour les appels nécessaires au lieu des 2 millions d’appels que vous auriez sans le filtrage des événements.

Le filtrage des événements est appliqué au [mappage de source d’événement Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html), une ressource qui lit à partir d’un événement choisi (le flux DynamoDB) et appelle une fonction Lambda. Dans le diagramme suivant, vous pouvez voir comment un élément time-to-live supprimé est consommé par une fonction Lambda utilisant des flux et des filtres d’événements.

![\[Un élément supprimé au moyen du processus TTL lance une fonction Lambda qui utilise des flux et des filtres d’événements.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/streams-lambda-ttl.png)


### Modèle de filtrage d’événement DynamoDB time-to-live
<a name="ttl-event-filter-pattern"></a>

L’ajout du JSON suivant à vos [critères de filtrage](https://docs.aws.amazon.com/lambda/latest/dg/API_FilterCriteria.html) du mappage de source d’événement permet l’appel de votre fonction Lambda uniquement pour les éléments supprimés TTL :

```
{
    "Filters": [
        {
            "Pattern": { "userIdentity": { "type": ["Service"], "principalId": ["dynamodb.amazonaws.com"] } }
        }
    ]
}
```

### Création d'un mappage des sources d' AWS Lambda événements
<a name="create-event-source-mapping"></a>

Utilisez les extraits de code suivants pour créer un mappage de source d’événement filtré que vous pouvez connecter au flux DynamoDB d’une table. Chaque bloc de code inclut le modèle de filtre d’événement.

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

```
aws lambda create-event-source-mapping \
--event-source-arn 'arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000' \
--batch-size 10 \
--enabled \
--function-name test_func \
--starting-position LATEST \
--filter-criteria '{"Filters": [{"Pattern": "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}"}]}'
```

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

```
LambdaClient client = LambdaClient.builder()
        .region(Region.EU_WEST_1)
        .build();

Filter userIdentity = Filter.builder()
        .pattern("{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}")
        .build();

FilterCriteria filterCriteria = FilterCriteria.builder()
        .filters(userIdentity)
        .build();

CreateEventSourceMappingRequest mappingRequest = CreateEventSourceMappingRequest.builder()
        .eventSourceArn("arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000")
        .batchSize(10)
        .enabled(Boolean.TRUE)
        .functionName("test_func")
        .startingPosition("LATEST")
        .filterCriteria(filterCriteria)
        .build();

try{
    CreateEventSourceMappingResponse eventSourceMappingResponse = client.createEventSourceMapping(mappingRequest);
    System.out.println("The mapping ARN is "+eventSourceMappingResponse.eventSourceArn());

}catch (ServiceException e){
    System.out.println(e.getMessage());
}
```

------
#### [ Node ]

```
const client = new LambdaClient({ region: "eu-west-1" });

const input = {
    EventSourceArn: "arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000",
    BatchSize: 10,
    Enabled: true,
    FunctionName: "test_func",
    StartingPosition: "LATEST",
    FilterCriteria: { "Filters": [{ "Pattern": "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}" }] }
}

const command = new CreateEventSourceMappingCommand(input);

try {
    const results = await client.send(command);
    console.log(results);
} catch (err) {
    console.error(err);
}
```

------
#### [ Python ]

```
session = boto3.session.Session(region_name = 'eu-west-1')
client = session.client('lambda')

try:
    response = client.create_event_source_mapping(
        EventSourceArn='arn:aws:dynamodb:eu-west-1:012345678910:table/test/stream/2021-12-10T00:00:00.000',
        BatchSize=10,
        Enabled=True,
        FunctionName='test_func',
        StartingPosition='LATEST',
        FilterCriteria={
            'Filters': [
                {
                    'Pattern': "{\"userIdentity\":{\"type\":[\"Service\"],\"principalId\":[\"dynamodb.amazonaws.com\"]}}"
                },
            ]
        }
    )
    print(response)
except Exception as e:
    print(e)
```

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

```
{
  "userIdentity": {
     "type": ["Service"],
     "principalId": ["dynamodb.amazonaws.com"]
   }
}
```

------

# Utilisation de l’adaptateur DynamoDB Streams Kinesis pour traiter des enregistrements de flux
<a name="Streams.KCLAdapter"></a>

L’utilisation de l’adaptateur Amazon Kinesis est la méthode recommandée pour consommer des flux d’Amazon DynamoDB. L’API DynamoDB Streams est volontairement semblable à celle de Kinesis Data Streams. Dans les deux services, les flux de données sont composés de partitions qui sont des conteneurs pour enregistrements de flux. Les deux services APIs contiennent`ListStreams`, `DescribeStream``GetShards`, et `GetShardIterator` opérations. (Si ces actions de DynamoDB Streams sont similaires à leurs homologues dans Kinesis Data Streams, elles ne sont pas identiques à 100 %.)

En tant qu’utilisateur de DynamoDB Streams, vous pouvez utiliser les modèles de conception figurant dans la KCL pour traiter les partitions et les enregistrements de flux de DynamoDB Streams. Pour ce faire, vous utilisez l’adaptateur Kinesis DynamoDB Streams. L’adaptateur Kinesis implémente l’interface Kinesis Data Streams afin que la KCL puisse être utilisée pour la consommation et le traitement des enregistrements de DynamoDB Streams. [Pour obtenir des instructions sur la configuration et l'installation de l'adaptateur DynamoDB Streams Kinesis, consultez le référentiel. GitHub](https://github.com/awslabs/dynamodb-streams-kinesis-adapter)

Vous pouvez écrire des applications pour Kinesis Data Streams à l’aide de la bibliothèque client Kinesis (KCL). La KCL simplifie le codage en fournissant des abstractions utiles par-dessus l’API Kinesis Data Streams de bas niveau. Pour en savoir plus sur la KCL, consultez [Développement d’applications consommateur à l’aide de la bibliothèque client Kinesis](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) dans le *Guide du développeur Amazon Kinesis Data Streams*.

DynamoDB recommande d'utiliser la version 3.x de KCL avec le SDK AWS pour Java v2.x. [La version 1.x de l'adaptateur DynamoDB Streams Kinesis actuelle AWS avec SDK AWS SDK pour Java pour v1.x continuera d'être entièrement prise en charge tout au long de son cycle de vie, comme prévu pendant la période de transition, conformément à la politique de maintenance des outils.AWS SDKs ](https://docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html)

**Note**  
Les versions 1.x et 2.x de la bibliothèque client Amazon Kinesis (KCL) sont obsolètes. KCL 1.x arrivera end-of-support le 30 janvier 2026. Nous vous recommandons vivement de migrer vos applications KCL utilisant la version 1.x vers la version la plus récente de la KCL avant le 30 janvier 2026. Pour trouver la dernière version de KCL, consultez la page de la bibliothèque [client Amazon Kinesis](https://github.com/awslabs/amazon-kinesis-client) sur. GitHub Pour en savoir plus sur la bibliothèque client Kinesis, consultez [Use Kinesis Client Library](https://docs.aws.amazon.com/streams/latest/dev/kcl.html). Pour en savoir plus sur la migration de la KCL 1.x vers la KCL 3.x, consultez Migration de la KCL 1.x vers la KCL 3.x.

Le diagramme suivant illustre la manière dont ces bibliothèques interagissent entre elles.

![\[Interactions entre DynamoDB Streams, Kinesis Data Streams et la KCL pour le traitement des enregistrements DynamoDB Streams.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/streams-kinesis-adapter.png)


Avec l’adaptateur Kinesis DynamoDB Streams en place, vous pouvez commencer à développer sur l’interface KCL, avec les appels d’API dirigés de manière transparente vers le point de terminaison DynamoDB Streams.

Lorsque votre application démarre, elle appelle la KCL pour instancier un worker. Vous devez fournir au travailleur les informations de configuration de l'application, telles que le descripteur de flux et les AWS informations d'identification, ainsi que le nom d'une classe de processeur d'enregistrements que vous fournissez. À mesure qu’il exécute le code dans le processeur d’enregistrements, le worker effectue les tâches suivantes :
+ Se connecte au flux
+ Énumère les partitions dans le flux
+ Vérifie et énumère les partitions enfants d’une partition parent fermée dans le flux
+ Coordonne les associations de partition avec les autres travaux (le cas échéant)
+ Instancie un processeur d’enregistrements pour chaque partition qu’il gère
+ Extrait des enregistrements du flux
+ Évalue le taux d'appels d' GetRecords API en cas de débit élevé (si le mode rattrapage est configuré)
+ Pousse les enregistrements sur le processeur d’enregistrements correspondant
+ Contrôle les enregistrements traités
+ Équilibre les associations partition-worker lorsque le nombre d’instances de worker change
+ Équilibre les associations partition-worker quand des partitions sont fractionnées

L'adaptateur KCL prend en charge le mode rattrapage, une fonction de réglage automatique du débit d'appels permettant de gérer les augmentations de débit temporaires. Lorsque le délai de traitement du flux dépasse un seuil configurable (une minute par défaut), le mode rattrapage redimensionne la fréquence des appels d' GetRecords API d'une valeur configurable (3 fois par défaut) pour récupérer les enregistrements plus rapidement, puis revient à la normale une fois le décalage réduit. Cela est utile pendant les périodes de haut débit où l'activité d'écriture DynamoDB peut submerger les consommateurs en utilisant les taux d'interrogation par défaut. Le mode rattrapage peut être activé via le paramètre de `catchupEnabled` configuration (faux par défaut).

**Note**  
Pour une description des concepts de KCL évoqués ici, consultez [Développement d’applications consommateur à l’aide de la bibliothèque client Kinesis](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) dans le *Guide du développeur Amazon Kinesis Data Streams*.  
Pour plus d'informations sur l'utilisation des flux avec, AWS Lambda voir [Streams et déclencheurs DynamoDB AWS Lambda](Streams.Lambda.md)

# Migration de la KCL 1.x vers la KCL 3.x
<a name="streams-migrating-kcl"></a>

## Présentation de
<a name="migrating-kcl-overview"></a>

Ce guide fournit des instructions pour migrer votre application consommateur de la KCL 1.x vers la KCL 3.x. En raison des différences architecturales entre la KCL 1.x et la KCL 3.x, la migration nécessite la mise à jour de plusieurs composants pour garantir la compatibilité.

La KCL 1.x utilise des classes et interfaces différentes rapport à la KCL 3.x. Vous devez d’abord migrer le processeur d’enregistrements, la fabrique de processeurs d’enregistrements et les classes de workers vers le format compatible avec la KCL 3.x, puis suivre les étapes de migration de la KCL 1.x vers la KCL 3.x.

## Étapes de la migration
<a name="migration-steps"></a>

**Topics**
+ [Étape 1 : migrer le processeur d’enregistrements](#step1-record-processor)
+ [Étape 2 : migrer la fabrique de processeurs d’enregistrements](#step2-record-processor-factory)
+ [Étape 3 : migrer le worker](#step3-worker-migration)
+ [Étape 4 : présentation de la configuration de la KCL 3.x et recommandations](#step4-configuration-migration)
+ [Étape 5 : migrer de la KCL 2.x vers la KCL 3.x](#step5-kcl2-to-kcl3)

### Étape 1 : migrer le processeur d’enregistrements
<a name="step1-record-processor"></a>

L’exemple suivant illustre un processeur d’enregistrements implémenté pour l’adaptateur DynamoDB Streams Kinesis version 1.x :

```
package com.amazonaws.kcl;

import com.amazonaws.services.kinesis.clientlibrary.exceptions.InvalidStateException;
import com.amazonaws.services.kinesis.clientlibrary.exceptions.ShutdownException;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.IRecordProcessorCheckpointer;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware;
import com.amazonaws.services.kinesis.clientlibrary.lib.worker.ShutdownReason;
import com.amazonaws.services.kinesis.clientlibrary.types.InitializationInput;
import com.amazonaws.services.kinesis.clientlibrary.types.ProcessRecordsInput;
import com.amazonaws.services.kinesis.clientlibrary.types.ShutdownInput;

public class StreamsRecordProcessor implements IRecordProcessor, IShutdownNotificationAware {
    @Override
    public void initialize(InitializationInput initializationInput) {
        //
        // Setup record processor
        //
    }

    @Override
    public void processRecords(ProcessRecordsInput processRecordsInput) {
        for (Record record : processRecordsInput.getRecords()) {
            String data = new String(record.getData().array(), Charset.forName("UTF-8"));
            System.out.println(data);
            if (record instanceof RecordAdapter) {
                // record processing and checkpointing logic
            }
        }
    }

    @Override
    public void shutdown(ShutdownInput shutdownInput) {
        if (shutdownInput.getShutdownReason() == ShutdownReason.TERMINATE) {
            try {
                shutdownInput.getCheckpointer().checkpoint();
            } catch (ShutdownException | InvalidStateException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Override
    public void shutdownRequested(IRecordProcessorCheckpointer checkpointer) {
        try {
            checkpointer.checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow exception
            //
            e.printStackTrace();
        }
    }
}
```

**Pour migrer la RecordProcessor classe**

1. Remplacez les interfaces `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor` et `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware` par `com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor` comme suit :

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
   // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IShutdownNotificationAware;
   
   import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
   ```

1. Mettez à jour les instructions d’importation des méthodes `initialize` et `processRecords` :

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.types.InitializationInput;
   import software.amazon.kinesis.lifecycle.events.InitializationInput;
   
   // import com.amazonaws.services.kinesis.clientlibrary.types.ProcessRecordsInput;
   import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
   ```

1. Remplacez la méthode `shutdownRequested` par les nouvelles méthodes suivantes : `leaseLost`, `shardEnded` et `shutdownRequested`.

   ```
   //    @Override
   //    public void shutdownRequested(IRecordProcessorCheckpointer checkpointer) {
   //        //
   //        // This is moved to shardEnded(...) and shutdownRequested(ShutdownReauestedInput)
   //        //
   //        try {
   //            checkpointer.checkpoint();
   //        } catch (ShutdownException | InvalidStateException e) {
   //            //
   //            // Swallow exception
   //            //
   //            e.printStackTrace();
   //        }
   //    }
   
       @Override
       public void leaseLost(LeaseLostInput leaseLostInput) {
   
       }
   
       @Override
       public void shardEnded(ShardEndedInput shardEndedInput) {
           try {
               shardEndedInput.checkpointer().checkpoint();
           } catch (ShutdownException | InvalidStateException e) {
               //
               // Swallow the exception
               //
               e.printStackTrace();
           }
       }
   
       @Override
       public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
           try {
               shutdownRequestedInput.checkpointer().checkpoint();
           } catch (ShutdownException | InvalidStateException e) {
               //
               // Swallow the exception
               //
               e.printStackTrace();
           }
       }
   ```

Voici la version mise à jour de la classe du processeur d’enregistrements :

```
package com.amazonaws.codesamples;

import software.amazon.kinesis.exceptions.InvalidStateException;
import software.amazon.kinesis.exceptions.ShutdownException;
import software.amazon.kinesis.lifecycle.events.InitializationInput;
import software.amazon.kinesis.lifecycle.events.LeaseLostInput;
import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
import software.amazon.kinesis.lifecycle.events.ShardEndedInput;
import software.amazon.kinesis.lifecycle.events.ShutdownRequestedInput;
import software.amazon.dynamodb.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import software.amazon.dynamodb.streamsadapter.adapter.DynamoDBStreamsKinesisClientRecord;
import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import com.amazonaws.services.dynamodbv2.streamsadapter.adapter.DynamoDBStreamsClientRecord;
import software.amazon.awssdk.services.dynamodb.model.Record;

public class StreamsRecordProcessor implements DynamoDBStreamsShardRecordProcessor {

    @Override
    public void initialize(InitializationInput initializationInput) {
        
    }

    @Override
    public void processRecords(DynamoDBStreamsProcessRecordsInput processRecordsInput) {
        for (DynamoDBStreamsKinesisClientRecord record: processRecordsInput.records())
            Record ddbRecord = record.getRecord();
            // processing and checkpointing logic for the ddbRecord
        }
    }

    @Override
    public void leaseLost(LeaseLostInput leaseLostInput) {
        
    }

    @Override
    public void shardEnded(ShardEndedInput shardEndedInput) {
        try {
            shardEndedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow the exception
            //
            e.printStackTrace();
        }
    }

    @Override
    public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
        try {
            shutdownRequestedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            //
            // Swallow the exception
            //
            e.printStackTrace();
        }
    }
}
```

**Note**  
L'adaptateur DynamoDB Streams Kinesis utilise désormais le modèle Record. SDKv2 Dans SDKv2, les `AttributeValue` objets complexes (`BS`,,`NS`, `M``L`,`SS`) ne renvoient jamais la valeur nulle. Vérifiez si ces valeurs existent à l’aide des méthodes `hasBs()`, `hasNs()`, `hasM()`, `hasL()` et `hasSs()`.

### Étape 2 : migrer la fabrique de processeurs d’enregistrements
<a name="step2-record-processor-factory"></a>

La fabrique de processeurs d’enregistrements est responsable de la création des processeurs d’enregistrements lorsqu’un bail est acquis. Voici un exemple de fabrique KCL 1.x :

```
package com.amazonaws.codesamples;

import software.amazon.dynamodb.AmazonDynamoDB;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory;

public class StreamsRecordProcessorFactory implements IRecordProcessorFactory {
    
    @Override
    public IRecordProcessor createProcessor() {
        return new StreamsRecordProcessor(dynamoDBClient, tableName);
    }
}
```

**Pour migrer la `RecordProcessorFactory`**
+ Remplacez l’interface implémentée `com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory` par `software.amazon.kinesis.processor.ShardRecordProcessorFactory` comme suit :

  ```
  // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessor;
  import software.amazon.kinesis.processor.ShardRecordProcessor;
  
  // import com.amazonaws.services.kinesis.clientlibrary.interfaces.v2.IRecordProcessorFactory;
  import software.amazon.kinesis.processor.ShardRecordProcessorFactory;
  
  // public class TestRecordProcessorFactory implements IRecordProcessorFactory {
  public class StreamsRecordProcessorFactory implements ShardRecordProcessorFactory {
  
  Change the return signature for createProcessor.
  
  // public IRecordProcessor createProcessor() {
  public ShardRecordProcessor shardRecordProcessor() {
  ```

Voici un exemple de fabrique de processeurs d’enregistrements dans 3.0 :

```
package com.amazonaws.codesamples;

import software.amazon.kinesis.processor.ShardRecordProcessor;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;

public class StreamsRecordProcessorFactory implements ShardRecordProcessorFactory {

    @Override
    public ShardRecordProcessor shardRecordProcessor() {
        return new StreamsRecordProcessor();
    }
}
```

### Étape 3 : migrer le worker
<a name="step3-worker-migration"></a>

Dans la version 3.0 de la KCL, une nouvelle classe, appelée **Scheduler**, remplace la classe **Worker**. Voici un exemple de worker KCL 1.x :

```
final KinesisClientLibConfiguration config = new KinesisClientLibConfiguration(...)
final IRecordProcessorFactory recordProcessorFactory = new RecordProcessorFactory();
final Worker worker = StreamsWorkerFactory.createDynamoDbStreamsWorker(
        recordProcessorFactory,
        workerConfig,
        adapterClient,
        amazonDynamoDB,
        amazonCloudWatchClient);
```

**Pour migrer le worker**

1. Modifiez l’instruction `import` de la classe `Worker` pour les instructions d’importation pour les classes `Scheduler` et `ConfigsBuilder`.

   ```
   // import com.amazonaws.services.kinesis.clientlibrary.lib.worker.Worker;
   import software.amazon.kinesis.coordinator.Scheduler;
   import software.amazon.kinesis.common.ConfigsBuilder;
   ```

1. Importez `StreamTracker` et remplacez l’importation `StreamsWorkerFactory` par `StreamsSchedulerFactory`.

   ```
   import software.amazon.kinesis.processor.StreamTracker;
   // import software.amazon.dynamodb.streamsadapter.StreamsWorkerFactory;
   import software.amazon.dynamodb.streamsadapter.StreamsSchedulerFactory;
   ```

1. Choisissez la position à partir de laquelle vous souhaitez démarrer l’application. Vous avez le choix entre `TRIM_HORIZON` et `LATEST`.

   ```
   import software.amazon.kinesis.common.InitialPositionInStream;
   import software.amazon.kinesis.common.InitialPositionInStreamExtended;
   ```

1. Créez une instance `StreamTracker`.

   ```
   StreamTracker streamTracker = StreamsSchedulerFactory.createSingleStreamTracker(
           streamArn,
           InitialPositionInStreamExtended.newInitialPosition(InitialPositionInStream.TRIM_HORIZON)
   );
   ```

1. Créez l’objet `AmazonDynamoDBStreamsAdapterClient`.

   ```
   import software.amazon.dynamodb.streamsadapter.AmazonDynamoDBStreamsAdapterClient; 
   import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
   import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
   
   ...
   
   AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create();
   
   AmazonDynamoDBStreamsAdapterClient adapterClient = new AmazonDynamoDBStreamsAdapterClient(
           credentialsProvider, awsRegion);
   ```

1. Créez l’objet `ConfigsBuilder`.

   ```
   import software.amazon.kinesis.common.ConfigsBuilder;
   
   ...
   ConfigsBuilder configsBuilder = new ConfigsBuilder(
                   streamTracker,
                   applicationName,
                   adapterClient,
                   dynamoDbAsyncClient,
                   cloudWatchAsyncClient,
                   UUID.randomUUID().toString(),
                   new StreamsRecordProcessorFactory());
   ```

1. Créez le `Scheduler` à l’aide de `ConfigsBuilder`, comme illustré dans l’exemple suivant :

   ```
   import java.util.UUID;
   
   import software.amazon.awssdk.regions.Region;
   import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
   import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
   import software.amazon.awssdk.services.kinesis.KinesisAsyncClient;
   
   import software.amazon.kinesis.common.KinesisClientUtil;
   import software.amazon.kinesis.coordinator.Scheduler;
   
   ...
   
                   
   DynamoDbAsyncClient dynamoClient = DynamoDbAsyncClient.builder().region(region).build();
   CloudWatchAsyncClient cloudWatchClient = CloudWatchAsyncClient.builder().region(region).build();
   
                   
   DynamoDBStreamsPollingConfig pollingConfig = new DynamoDBStreamsPollingConfig(adapterClient);
   pollingConfig.idleTimeBetweenReadsInMillis(idleTimeBetweenReadsInMillis);
   
   // Use ConfigsBuilder to configure settings
   RetrievalConfig retrievalConfig = configsBuilder.retrievalConfig();
   retrievalConfig.retrievalSpecificConfig(pollingConfig);
   
   CoordinatorConfig coordinatorConfig = configsBuilder.coordinatorConfig();
   coordinatorConfig.clientVersionConfig(CoordinatorConfig.ClientVersionConfig.CLIENT_VERSION_CONFIG_COMPATIBLE_WITH_2X);
                   
   Scheduler scheduler = StreamsSchedulerFactory.createScheduler(
                   configsBuilder.checkpointConfig(),
                   coordinatorConfig,
                   configsBuilder.leaseManagementConfig(),
                   configsBuilder.lifecycleConfig(),
                   configsBuilder.metricsConfig(),
                   configsBuilder.processorConfig(),
                   retrievalConfig,
                   adapterClient
           );
   ```

**Important**  
Le paramètre `CLIENT_VERSION_CONFIG_COMPATIBLE_WITH_2X` assure la compatibilité entre l’adaptateur DynamoDB Streams Kinesis pour la KCL v3 et la KCL v1, et non entre la KCL v2 et la KCL v3.

### Étape 4 : présentation de la configuration de la KCL 3.x et recommandations
<a name="step4-configuration-migration"></a>

Pour obtenir une description détaillée des configurations introduites après la KCL 1.x qui sont pertinentes dans la KCL 3.x, consultez [KCL configurations](https://docs.aws.amazon.com//streams/latest/dev/kcl-configuration.html) et [KCL migration client configuration](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration.html#client-configuration).

**Important**  
Au lieu de créer directement des objets de `checkpointConfig`, `coordinatorConfig`, `leaseManagementConfig`, `metricsConfig`, `processorConfig` et `retrievalConfig`, nous vous recommandons de définir des configurations dans la KCL 3.x et versions ultérieures à l’aide de `ConfigsBuilder`, afin d’éviter les problèmes d’initialisation du Scheduler. `ConfigsBuilder` fournit une méthode plus flexible et plus facile à gérer pour configurer votre application KCL.

#### Configurations avec mise à jour de la valeur par défaut dans la KCL 3.x
<a name="kcl3-configuration-overview"></a>

`billingMode`  
Dans la KCL version 1.x, la valeur par défaut de `billingMode` est définie sur `PROVISIONED`. En revanche, avec la KCL version 3.x, le `billingMode` par défaut est `PAY_PER_REQUEST` (mode à la demande). Nous vous recommandons d’utiliser le mode de capacité à la demande pour votre table de baux, afin d’ajuster automatiquement la capacité en fonction de votre utilisation. Pour obtenir des conseils sur l’utilisation de la capacité allouée pour vos tables de baux, consultez [Best practices for the lease table with provisioned capacity mode](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration-lease-table.html).

`idleTimeBetweenReadsInMillis`  
Dans la KCL version 1.x, la valeur par défaut de `idleTimeBetweenReadsInMillis` est définie sur 1 000 (soit 1 seconde). La KCL version 3.x définit la valeur par défaut de i`dleTimeBetweenReadsInMillis` sur 1 500 (soit 1,5 seconde), mais l’adaptateur Amazon DynamoDB Streams Kinesis remplace la valeur par défaut par 1 000 (soit 1 seconde).

#### Nouvelles configurations de la KCL 3.x
<a name="kcl3-new-configs"></a>

`leaseAssignmentIntervalMillis`  
Cette configuration définit l’intervalle de temps avant que les partitions récemment découvertes ne commencent à être traitées. Elle est calculée comme suit : 1,5 × `leaseAssignmentIntervalMillis`. Si ce paramètre n’est pas explicitement configuré, l’intervalle de temps est défini par défaut sur 1,5 × `failoverTimeMillis`. Le traitement des nouvelles partitions consiste à analyser la table de baux et à interroger un index secondaire global (GSI) de la table de baux. La réduction de `leaseAssignmentIntervalMillis` augmente la fréquence de ces opérations d’analyse et d’interrogation, ce qui entraîne une augmentation des coûts de DynamoDB. Nous vous recommandons de définir cette valeur sur 2 000 (soit 2 secondes) afin de réduire le délai de traitement des nouvelles partitions.

`shardConsumerDispatchPollIntervalMillis`  
Cette configuration définit l’intervalle entre les interrogations successives effectuées par le consommateur de partitions pour déclencher des transitions d’état. Dans la KCL version 1.x, ce comportement était contrôlé par le paramètre `idleTimeInMillis`, qui n’était pas exposé en tant que paramètre configurable. Avec la KCL version 3.x, nous vous recommandons de définir cette configuration de sorte qu’elle corresponde à la valeur utilisée pour ` idleTimeInMillis` dans votre configuration de la KCL version 1.x.

### Étape 5 : migrer de la KCL 2.x vers la KCL 3.x
<a name="step5-kcl2-to-kcl3"></a>

Pour garantir une transition fluide et une compatibilité avec la version la plus récente de la bibliothèque client Kinesis (KCL), suivez les étapes 5 à 8 des instructions du guide de migration pour la [mise à niveau de la KCL 2.x vers la KCL 3.x](https://docs.aws.amazon.com//streams/latest/dev/kcl-migration-from-2-3.html#kcl-migration-from-2-3-worker-metrics).

Pour la résolution des problèmes courants liés à la KCL 3.x, consultez [Troubleshooting KCL consumer applications](https://docs.aws.amazon.com//streams/latest/dev/troubleshooting-consumers.html).

# Restauration par régression de la version précédente de la KCL
<a name="kcl-migration-rollback"></a>

Cette rubrique explique comment restaurer la version précédente de la KCL pour votre application consommateur. Le processus de restauration par régression comprend deux étapes :

1. Exécuter l’[outil de migration de la KCL](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py)

1. Redéployer le code de la version précédente de la KCL

## Étape 1 : exécuter l’outil de migration de la KCL
<a name="kcl-migration-rollback-step1"></a>

Si vous avez besoin de restaurer la version précédente de la KCL, vous devez exécuter l’outil de migration de la KCL. L’outil effectue deux tâches importantes :
+ Il supprime une table de métadonnées appelée table des métriques de worker, ainsi qu’un index secondaire global de la table des baux dans DynamoDB. Ces artefacts sont créés par la KCL 3.x, mais ils ne sont pas nécessaires lorsque vous restaurez la version précédente.
+ Ainsi, tous les workers peuvent s’exécuter dans un mode compatible avec la KCL 1.x et commencer à utiliser l’algorithme d’équilibrage de charge utilisé dans les versions précédentes de la KCL. Si vous rencontrez des problèmes avec le nouvel algorithme d’équilibrage de charge dans la KCL 3.x, cela permettra de les résoudre immédiatement.

**Important**  
La table des états de coordinateur de DynamoDB doit exister et ne doit pas être supprimée pendant les processus de migration, de restauration par régression et de restauration par progression.

**Note**  
Il est important que tous les workers de votre application consommateur utilisent le même algorithme d’équilibrage de charge à un moment donné. L’outil de migration de la KCL s’assure que tous les workers de votre application consommateur KCL 3.x basculent vers le mode compatible avec la KCL 1.x, afin qu’ils exécutent le même algorithme d’équilibrage de charge lors de la restauration par régression de l’application vers la version précédente de la KCL.

Vous pouvez télécharger l'[outil de migration KCL](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py) dans le répertoire des scripts du référentiel [KCL GitHub](https://github.com/awslabs/amazon-kinesis-client/tree/master). Exécutez le script à partir d’un worker ou d’un hôte disposant des autorisations appropriées pour écrire dans la table des états de coordinateur, la table des métriques de worker et la table des baux. Assurez-vous que les [autorisations IAM](https://docs.aws.amazon.com/streams/latest/dev/kcl-iam-permissions.html) appropriées sont configurées pour les applications consommateur KCL. Exécutez le script une seule fois par application KCL à l’aide de la commande spécifiée :

```
python3 ./KclMigrationTool.py --region region --mode rollback [--application_name applicationName] [--lease_table_name leaseTableName] [--coordinator_state_table_name coordinatorStateTableName] [--worker_metrics_table_name workerMetricsTableName]
```

### Parameters
<a name="kcl-migration-rollback-parameters"></a>

`--region`  
*region*Remplacez-le par votre Région AWS.

`--application_name`  
Ce paramètre est obligatoire si vous utilisez des noms par défaut pour vos tables de métadonnées DynamoDB (table des baux, table des états de coordinateur et table des métriques de worker). Si vous avez spécifié des noms personnalisés pour ces tables, vous pouvez omettre ce paramètre. *applicationName*Remplacez-le par le nom réel de votre application KCL. L’outil l’utilise pour créer les noms de table par défaut si aucun nom personnalisé n’est fourni.

`--lease_table_name`  
Ce paramètre est nécessaire si vous avez défini un nom personnalisé pour la table des baux dans votre configuration KCL. Si vous utilisez le nom de table par défaut, vous pouvez omettre ce paramètre. *leaseTableName*Remplacez-le par le nom de table personnalisé que vous avez spécifié pour votre table de location.

`--coordinator_state_table_name`  
Ce paramètre est nécessaire si vous avez défini un nom personnalisé pour la table des états de coordinateur dans votre configuration KCL. Si vous utilisez le nom de table par défaut, vous pouvez omettre ce paramètre. *coordinatorStateTableName*Remplacez-le par le nom de table personnalisé que vous avez spécifié pour votre table d'état des coordinateurs.

`--worker_metrics_table_name`  
Ce paramètre est nécessaire si vous avez défini un nom personnalisé pour la table des métriques de worker dans votre configuration KCL. Si vous utilisez le nom de table par défaut, vous pouvez omettre ce paramètre. *workerMetricsTableName*Remplacez-le par le nom de table personnalisé que vous avez spécifié pour votre tableau des métriques des travailleurs.

## Étape 2 : redéployer le code avec la version précédente de la KCL
<a name="kcl-migration-rollback-step2"></a>

**Important**  
Toute mention de la version 2.x dans la sortie générée par l’outil de migration de la KCL doit être interprétée comme faisant référence à la KCL version 1.x. L’exécution du script n’effectue pas de restauration par régression complète : elle fait uniquement basculer l’algorithme d’équilibrage de charge vers celui utilisé dans la KCL version 1.x.

Après avoir exécuté l’outil de migration de la KCL pour effectuer une restauration par régression, l’un des messages suivants s’affiche :

Message 1  
« Restauration par régression terminée. Votre application exécutait une fonctionnalité compatible avec la version 2x. Veuillez restaurer les fichiers binaires précédents de votre application en déployant le code avec votre version précédente de la KCL. »  
**Action requise :** vos workers s’exécutaient dans le mode compatible avec la KCL 1.x. Redéployez le code avec la version précédente de la KCL sur vos workers.

Message 2  
« Restauration par régression terminée. Votre application KCL exécutait une fonctionnalité compatible avec la version 3x. Une fonctionnalité compatible avec la version 2x a été restaurée par régression. Si vous ne constatez aucune amélioration après un court laps de temps, restaurez les fichiers binaires précédents de votre application en déployant le code avec votre version précédente de la KCL. »  
**Action requise :** vos workers s’exécutaient dans le mode compatible avec la KCL 3.x et l’outil de migration de la KCL a fait basculer tous les workers vers le mode compatible avec la KCL 1.x. Redéployez le code avec la version précédente de la KCL sur vos workers.

Message 3  
« L’application a déjà fait l’objet d’une restauration par régression. Toutes KCLv3 les ressources susceptibles d'être supprimées ont été nettoyées afin d'éviter des frais jusqu'à ce que l'application puisse être reportée avec la migration. »  
**Action requise :** vos workers ont déjà fait l’objet d’une restauration par régression pour s’exécuter dans le mode compatible avec la KCL 1.x. Redéployez le code avec la version précédente de la KCL sur vos workers.

# Restauration par progression de la KCL 3.x après une restauration par régression
<a name="kcl-migration-rollforward"></a>

Cette rubrique explique comment restaurer par progression votre application consommateur vers la KCL 3.x après une restauration par régression. Lorsque vous devez effectuer une restauration par progression, vous devez suivre un processus en deux étapes :

1. Exécuter l’[outil de migration de la KCL](https://github.com/awslabs/amazon-kinesis-client/blob/master/amazon-kinesis-client/scripts/KclMigrationTool.py)

1. Déployer le code avec la KCL 3.x

## Étape 1 : exécuter l’outil de migration de la KCL
<a name="kcl-migration-rollforward-step1"></a>

Exécutez l’outil de migration de la KCL avec la commande suivante pour effectuer une restauration par progression vers la KCL 3.x :

```
python3 ./KclMigrationTool.py --region region --mode rollforward [--application_name applicationName] [--coordinator_state_table_name coordinatorStateTableName]
```

### Parameters
<a name="kcl-migration-rollforward-parameters"></a>

`--region`  
*region*Remplacez-le par votre Région AWS.

`--application_name`  
Ce paramètre est obligatoire si vous utilisez des noms par défaut pour votre table des états de coordinateur. Si vous avez spécifié des noms personnalisés pour la table des états de coordinateur, vous pouvez omettre ce paramètre. *applicationName*Remplacez-le par le nom réel de votre application KCL. L’outil l’utilise pour créer les noms de table par défaut si aucun nom personnalisé n’est fourni.

`--coordinator_state_table_name`  
Ce paramètre est nécessaire si vous avez défini un nom personnalisé pour la table des états de coordinateur dans votre configuration KCL. Si vous utilisez le nom de table par défaut, vous pouvez omettre ce paramètre. *coordinatorStateTableName*Remplacez-le par le nom de table personnalisé que vous avez spécifié pour votre table d'état des coordinateurs.

Une fois que vous avez exécuté l’outil de migration en mode restauration par progression, la KCL crée les ressources DynamoDB suivantes requises pour la KCL 3.x :
+ Un index secondaire global sur la table des baux
+ Une table des métriques de worker

## Étape 2 : déployer le code avec la KCL 3.x
<a name="kcl-migration-rollforward-step2"></a>

Après avoir exécuté l’outil de migration de la KCL pour une restauration par progression, déployez votre code avec la KCL 3.x sur vos workers. Pour terminer votre migration, consultez [Step 8: Complete the migration](https://docs.aws.amazon.com/streams/latest/dev/kcl-migration-from-2-3.html#kcl-migration-from-2-3-finish).

# Démonstration : adaptateur Kinesis DynamoDB Streams
<a name="Streams.KCLAdapter.Walkthrough"></a>

Cette section est une démonstration d’une application Java qui utilise la bibliothèque client Amazon Kinesis et l’adaptateur Amazon DynamoDB Streams. L’application illustre un exemple de la réplication de données, où l’activité d’écriture d’une table est appliquée à une seconde table, avec le contenu des deux tables demeurant synchronisé. Pour le code source, consultez [Programme complet : adaptateur DynamoDB Streams Kinesis](Streams.KCLAdapter.Walkthrough.CompleteProgram.md).

Le programme exécute les tâches suivantes :

1. Crée deux tables DynamoDB nommées `KCL-Demo-src` et `KCL-Demo-dst`. Chacune de ces tables dispose d’un flux activé sur elle-même.

1. Génère une activité de mise à jour de la table source en ajoutant, mettant à jour et supprimant des éléments. Cela entraîne l’écriture des données sur le flux de la table.

1. Lit les enregistrements du flux, les reconstruit en tant que demandes DynamoDB, et applique les demandes à la table de destination.

1. Analyse les tables source et de destination afin de s’assurer que leurs contenus sont identiques.

1. Nettoie en supprimant les tables.

Ces étapes sont décrites dans les sections suivantes et l’application complète est illustrée à la fin de la procédure pas à pas.

**Topics**
+ [Étape 1 : créer des tables DynamoDB](#Streams.KCLAdapter.Walkthrough.Step1)
+ [Étape 2 : générer une activité de mise à jour de la table source](#Streams.KCLAdapter.Walkthrough.Step2)
+ [Étape 3 : traiter le flux](#Streams.KCLAdapter.Walkthrough.Step3)
+ [Étape 4 : s’assurer que les deux tables ont un contenu identique](#Streams.KCLAdapter.Walkthrough.Step4)
+ [Étape 5 : nettoyer](#Streams.KCLAdapter.Walkthrough.Step5)
+ [Programme complet : adaptateur DynamoDB Streams Kinesis](Streams.KCLAdapter.Walkthrough.CompleteProgram.md)

## Étape 1 : créer des tables DynamoDB
<a name="Streams.KCLAdapter.Walkthrough.Step1"></a>

La première étape consiste à créer deux tables DynamoDB : une table source et une table de destination. Le `StreamViewType` sur le flux de la table source est `NEW_IMAGE`. Cela signifie que chaque fois qu’un élément est modifié dans la table, l’image « après » de l’élément est écrite dans le flux. Ainsi, le flux assure le suivi des toute l’activité d’écriture sur la table.

L’extrait de code suivant illustre le code utilisé pour la création des deux tables.

```
java.util.List<AttributeDefinition> attributeDefinitions = new ArrayList<AttributeDefinition>();
attributeDefinitions.add(new AttributeDefinition().withAttributeName("Id").withAttributeType("N"));

java.util.List<KeySchemaElement> keySchema = new ArrayList<KeySchemaElement>();
keySchema.add(new KeySchemaElement().withAttributeName("Id").withKeyType(KeyType.HASH)); // Partition
                                                                                         // key

ProvisionedThroughput provisionedThroughput = new ProvisionedThroughput().withReadCapacityUnits(2L)
    .withWriteCapacityUnits(2L);

StreamSpecification streamSpecification = new StreamSpecification();
streamSpecification.setStreamEnabled(true);
streamSpecification.setStreamViewType(StreamViewType.NEW_IMAGE);
CreateTableRequest createTableRequest = new CreateTableRequest().withTableName(tableName)
    .withAttributeDefinitions(attributeDefinitions).withKeySchema(keySchema)
    .withProvisionedThroughput(provisionedThroughput).withStreamSpecification(streamSpecification);
```

## Étape 2 : générer une activité de mise à jour de la table source
<a name="Streams.KCLAdapter.Walkthrough.Step2"></a>

L’étape suivante consiste à créer une activité d’écriture sur la table source. Tandis que cette activité a lieu, le flux de la table source est aussi mis à jour en quasi-temps réel.

L’application définit une classe d’assistance avec les méthodes qui appellent les actions d’API `PutItem`, `UpdateItem` et `DeleteItem` pour écrire les données. L’extrait de code suivant montre comment ces méthodes sont utilisées.

```
StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "101", "test1");
StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "101", "test2");
StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "101");
StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName, "102", "demo3");
StreamsAdapterDemoHelper.updateItem(dynamoDBClient, tableName, "102", "demo4");
StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName, "102");
```

## Étape 3 : traiter le flux
<a name="Streams.KCLAdapter.Walkthrough.Step3"></a>

Maintenant le programme commence à traiter le flux. L’adaptateur DynamoDB Streams Kinesis agit comme une couche transparente entre la KCL et le point de terminaison DynamoDB Streams, afin que le code puisse pleinement exploiter la KCL au lieu de devoir effectuer des appels DynamoDB Streams de bas niveau. Le programme effectue les tâches suivantes :
+ Il définit une classe de processeur d’enregistrements, `StreamsRecordProcessor`, avec des méthodes conformes à la définition de l’interface KCL : `initialize`, `processRecords` et `shutdown`. La méthode `processRecords` contient la logique nécessaire pour lire à partir du flux de la table source et écrire dans la table de destination.
+ Il définit une fabrique de classe pour la classe de processeur d’enregistrements (`StreamsRecordProcessorFactory`). Cette action est obligatoire pour les programmes Java qui utilisent le KCL.
+ Il instancie un nouveau KCL `Worker`, associé à la fabrique de classe.
+ Il arrête le `Worker` lorsque le traitement des enregistrements est terminé.

Activez éventuellement le mode rattrapage dans la configuration de votre adaptateur Streams KCL pour augmenter automatiquement le taux d'appels d' GetRecords API de 3 fois (par défaut) lorsque le délai de traitement des flux dépasse une minute (par défaut), afin d'aider votre consommateur de flux à gérer les pics de débit élevés dans votre table.

Pour en savoir plus sur la définition de l’interface de la KCL, consultez [Développement d’applications consommateur à l’aide de la bibliothèque client Kinesis](https://docs.aws.amazon.com/kinesis/latest/dev/developing-consumers-with-kcl.html) dans le *Guide du développeur Amazon Kinesis Data Streams*. 

L’extrait de code suivant illustre la boucle principale dans `StreamsRecordProcessor`. L’instruction `case` détermine l’action à exécuter, en fonction de l’`OperationType` qui s’affiche dans l’enregistrement de flux.

```
for (Record record : records) {
    String data = new String(record.getData().array(), Charset.forName("UTF-8"));
    System.out.println(data);
    if (record instanceof RecordAdapter) {
                software.amazon.dynamodb.model.Record streamRecord = ((RecordAdapter) record)
                    .getInternalObject();

                switch (streamRecord.getEventName()) {
                    case "INSERT":
                    case "MODIFY":
                        StreamsAdapterDemoHelper.putItem(dynamoDBClient, tableName,
                            streamRecord.getDynamodb().getNewImage());
                        break;
                    case "REMOVE":
                        StreamsAdapterDemoHelper.deleteItem(dynamoDBClient, tableName,
                            streamRecord.getDynamodb().getKeys().get("Id").getN());
                }
    }
    checkpointCounter += 1;
    if (checkpointCounter % 10 == 0) {
        try {
            checkpointer.checkpoint();
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }
}
```

## Étape 4 : s’assurer que les deux tables ont un contenu identique
<a name="Streams.KCLAdapter.Walkthrough.Step4"></a>

À ce stade, le contenu des tables source et destination est synchronisé. L’application émet des demandes `Scan` sur les deux tables afin de vérifier que leurs contenus sont, en fait, identiques.

La classe `DemoHelper` contient une méthode `ScanTable` qui appelle l’API `Scan` de bas niveau. L’exemple suivant illustre la marche à suivre.

```
if (StreamsAdapterDemoHelper.scanTable(dynamoDBClient, srcTable).getItems()
    .equals(StreamsAdapterDemoHelper.scanTable(dynamoDBClient, destTable).getItems())) {
    System.out.println("Scan result is equal.");
}
else {
    System.out.println("Tables are different!");
}
```

## Étape 5 : nettoyer
<a name="Streams.KCLAdapter.Walkthrough.Step5"></a>

Comme la démonstration est terminée, l’application supprime les tables source et destination. Consultez l’exemple de code suivant. Même après que les tables sont supprimées, leurs flux demeurent accessibles 24 heures, délai au-delà duquel ils sont automatiquement supprimés.

```
dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(srcTable));
dynamoDBClient.deleteTable(new DeleteTableRequest().withTableName(destTable));
```

# Programme complet : adaptateur DynamoDB Streams Kinesis
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram"></a>

Voici le programme Java complet qui effectue les tâches décrites dans [Démonstration : adaptateur Kinesis DynamoDB Streams](Streams.KCLAdapter.Walkthrough.md). Lorsque vous l’exécutez, vous devez visualiser une sortie similaire à ce qui suit.

```
Creating table KCL-Demo-src
Creating table KCL-Demo-dest
Table is active.
Creating worker for stream: arn:aws:dynamodb:us-west-2:111122223333:table/KCL-Demo-src/stream/2015-05-19T22:48:56.601
Starting worker...
Scan result is equal.
Done.
```

**Important**  
 Pour exécuter ce programme, assurez-vous que l'application cliente a accès à DynamoDB et à CloudWatch Amazon à l'aide de politiques. Pour de plus amples informations, veuillez consulter [Politiques basées sur l’identité pour DynamoDB](security_iam_service-with-iam.md#security_iam_service-with-iam-id-based-policies). 

Le code source se compose de quatre `.java` fichiers. Pour créer ce programme, ajoutez la dépendance suivante, qui inclut la bibliothèque client Amazon Kinesis (KCL) 3.x et le SDK pour AWS Java v2 en tant que dépendances transitives :

------
#### [ Maven ]

```
<dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>dynamodb-streams-kinesis-adapter</artifactId>
    <version>2.1.0</version>
</dependency>
```

------
#### [ Gradle ]

```
implementation 'com.amazonaws:dynamodb-streams-kinesis-adapter:2.1.0'
```

------

Les fichiers sources sont les suivants :
+ `StreamsAdapterDemo.java`
+ `StreamsRecordProcessor.java`
+ `StreamsRecordProcessorFactory.java`
+ `StreamsAdapterDemoHelper.java`

## StreamsAdapterDemo.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsAdapterDemo"></a>

```
package com.amazonaws.codesamples;

import com.amazonaws.services.dynamodbv2.streamsadapter.AmazonDynamoDBStreamsAdapterClient;
import com.amazonaws.services.dynamodbv2.streamsadapter.StreamsSchedulerFactory;
import com.amazonaws.services.dynamodbv2.streamsadapter.polling.DynamoDBStreamsPollingConfig;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.cloudwatch.CloudWatchAsyncClient;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.kinesis.common.ConfigsBuilder;
import software.amazon.kinesis.common.InitialPositionInStream;
import software.amazon.kinesis.common.InitialPositionInStreamExtended;
import software.amazon.kinesis.coordinator.Scheduler;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;
import software.amazon.kinesis.processor.StreamTracker;
import software.amazon.kinesis.retrieval.RetrievalConfig;

public class StreamsAdapterDemo {

    private static DynamoDbAsyncClient dynamoDbAsyncClient;
    private static CloudWatchAsyncClient cloudWatchAsyncClient;
    private static AmazonDynamoDBStreamsAdapterClient amazonDynamoDbStreamsAdapterClient;

    private static String tablePrefix = "KCL-Demo";
    private static String streamArn;

    private static Region region = Region.US_EAST_1;
    private static AwsCredentialsProvider credentialsProvider = DefaultCredentialsProvider.create();

    public static void main( String[] args ) throws Exception {
        System.out.println("Starting demo...");
        dynamoDbAsyncClient = DynamoDbAsyncClient.builder()
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build();
        cloudWatchAsyncClient = CloudWatchAsyncClient.builder()
                .credentialsProvider(credentialsProvider)
                .region(region)
                .build();
        amazonDynamoDbStreamsAdapterClient = new AmazonDynamoDBStreamsAdapterClient(credentialsProvider, region);

        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";

        setUpTables();

        StreamTracker streamTracker = StreamsSchedulerFactory.createSingleStreamTracker(streamArn,
                InitialPositionInStreamExtended.newInitialPosition(InitialPositionInStream.TRIM_HORIZON));

        ShardRecordProcessorFactory shardRecordProcessorFactory =
                new StreamsAdapterDemoProcessorFactory(dynamoDbAsyncClient, destTable);

        ConfigsBuilder configsBuilder = new ConfigsBuilder(
                streamTracker,
                "streams-adapter-demo",
                amazonDynamoDbStreamsAdapterClient,
                dynamoDbAsyncClient,
                cloudWatchAsyncClient,
                "streams-demo-worker",
                shardRecordProcessorFactory
        );

        DynamoDBStreamsPollingConfig pollingConfig = new DynamoDBStreamsPollingConfig(amazonDynamoDbStreamsAdapterClient);
        RetrievalConfig retrievalConfig = configsBuilder.retrievalConfig();
        retrievalConfig.retrievalSpecificConfig(pollingConfig);

        System.out.println("Creating scheduler for stream " + streamArn);
        Scheduler scheduler = StreamsSchedulerFactory.createScheduler(
                configsBuilder.checkpointConfig(),
                configsBuilder.coordinatorConfig(),
                configsBuilder.leaseManagementConfig(),
                configsBuilder.lifecycleConfig(),
                configsBuilder.metricsConfig(),
                configsBuilder.processorConfig(),
                retrievalConfig,
                amazonDynamoDbStreamsAdapterClient
        );

        System.out.println("Starting scheduler...");
        Thread t = new Thread(scheduler);
        t.start();

        Thread.sleep(250000);

        System.out.println("Stopping scheduler...");
        scheduler.shutdown();
        t.join();

        if (StreamsAdapterDemoHelper.scanTable(dynamoDbAsyncClient, srcTable).items()
                .equals(StreamsAdapterDemoHelper.scanTable(dynamoDbAsyncClient, destTable).items())) {
            System.out.println("Scan result is equal.");
        } else {
            System.out.println("Tables are different!");
        }

        System.out.println("Done.");
        cleanupAndExit(0);
    }

    private static void setUpTables() {
        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";
        streamArn = StreamsAdapterDemoHelper.createTable(dynamoDbAsyncClient, srcTable);
        StreamsAdapterDemoHelper.createTable(dynamoDbAsyncClient, destTable);

        awaitTableCreation(srcTable);

        performOps(srcTable);
    }

    private static void awaitTableCreation(String tableName) {
        Integer retries = 0;
        Boolean created = false;
        while (!created && retries < 100) {
            DescribeTableResponse result = StreamsAdapterDemoHelper.describeTable(dynamoDbAsyncClient, tableName);
            created = result.table().tableStatusAsString().equals("ACTIVE");
            if (created) {
                System.out.println("Table is active.");
                return;
            } else {
                retries++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // do nothing
                }
            }
        }
        System.out.println("Timeout after table creation. Exiting...");
        cleanupAndExit(1);
    }

    private static void performOps(String tableName) {
        StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName, "101", "test1");
        StreamsAdapterDemoHelper.updateItem(dynamoDbAsyncClient, tableName, "101", "test2");
        StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName, "101");
        StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName, "102", "demo3");
        StreamsAdapterDemoHelper.updateItem(dynamoDbAsyncClient, tableName, "102", "demo4");
        StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName, "102");
    }

    private static void cleanupAndExit(Integer returnValue) {
        String srcTable = tablePrefix + "-src";
        String destTable = tablePrefix + "-dest";
        dynamoDbAsyncClient.deleteTable(DeleteTableRequest.builder().tableName(srcTable).build());
        dynamoDbAsyncClient.deleteTable(DeleteTableRequest.builder().tableName(destTable).build());
        System.exit(returnValue);
    }
}
```

## StreamsRecordProcessor.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsRecordProcessor"></a>

```
package com.amazonaws.codesamples;

import com.amazonaws.services.dynamodbv2.streamsadapter.adapter.DynamoDBStreamsClientRecord;
import com.amazonaws.services.dynamodbv2.streamsadapter.model.DynamoDBStreamsProcessRecordsInput;
import com.amazonaws.services.dynamodbv2.streamsadapter.processor.DynamoDBStreamsShardRecordProcessor;
import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.Record;
import software.amazon.kinesis.exceptions.InvalidStateException;
import software.amazon.kinesis.exceptions.ShutdownException;
import software.amazon.kinesis.lifecycle.events.InitializationInput;
import software.amazon.kinesis.lifecycle.events.LeaseLostInput;
import software.amazon.kinesis.lifecycle.events.ShardEndedInput;
import software.amazon.kinesis.lifecycle.events.ShutdownRequestedInput;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

public class StreamsRecordProcessor implements DynamoDBStreamsShardRecordProcessor {

    private Integer checkpointCounter;

    private final DynamoDbAsyncClient dynamoDbAsyncClient;
    private final String tableName;

    public StreamsRecordProcessor(DynamoDbAsyncClient dynamoDbAsyncClient, String tableName) {
        this.dynamoDbAsyncClient = dynamoDbAsyncClient;
        this.tableName = tableName;
    }

    @Override
    public void initialize(InitializationInput initializationInput) {
        this.checkpointCounter = 0;
    }

    @Override
    public void processRecords(DynamoDBStreamsProcessRecordsInput dynamoDBStreamsProcessRecordsInput) {
        for (DynamoDBStreamsClientRecord record: dynamoDBStreamsProcessRecordsInput.records()) {
            String data = new String(record.data().array(), StandardCharsets.UTF_8);
            System.out.println(data);
            Record streamRecord = record.getRecord();

            switch (streamRecord.eventName()) {
                case INSERT:
                case MODIFY:
                    StreamsAdapterDemoHelper.putItem(dynamoDbAsyncClient, tableName,
                            streamRecord.dynamodb().newImage());
                case REMOVE:
                    StreamsAdapterDemoHelper.deleteItem(dynamoDbAsyncClient, tableName,
                            streamRecord.dynamodb().keys().get("Id").n());
            }
            checkpointCounter += 1;
            if (checkpointCounter % 10 == 0) {
                try {
                    dynamoDBStreamsProcessRecordsInput.checkpointer().checkpoint();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public void leaseLost(LeaseLostInput leaseLostInput) {
        System.out.println("Lease Lost");
    }

    @Override
    public void shardEnded(ShardEndedInput shardEndedInput) {
        try {
            shardEndedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void shutdownRequested(ShutdownRequestedInput shutdownRequestedInput) {
        try {
            shutdownRequestedInput.checkpointer().checkpoint();
        } catch (ShutdownException | InvalidStateException e) {
            e.printStackTrace();
        }
    }
}
```

## StreamsRecordProcessorFactory.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsRecordProcessorFactory"></a>

```
package com.amazonaws.codesamples;

import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.kinesis.processor.ShardRecordProcessor;
import software.amazon.kinesis.processor.ShardRecordProcessorFactory;

public class StreamsAdapterDemoProcessorFactory implements ShardRecordProcessorFactory {
    private final String tableName;
    private final DynamoDbAsyncClient dynamoDbAsyncClient;

    public StreamsAdapterDemoProcessorFactory(DynamoDbAsyncClient asyncClient, String tableName) {
        this.tableName = tableName;
        this.dynamoDbAsyncClient = asyncClient;
    }

    @Override
    public ShardRecordProcessor shardRecordProcessor() {
        return new StreamsRecordProcessor(dynamoDbAsyncClient, tableName);
    }
}
```

## StreamsAdapterDemoHelper.java
<a name="Streams.KCLAdapter.Walkthrough.CompleteProgram.StreamsAdapterDemoHelper"></a>

```
package com.amazonaws.codesamples;

import software.amazon.awssdk.services.dynamodb.DynamoDbAsyncClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.OnDemandThroughput;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.ResourceInUseException;
import software.amazon.awssdk.services.dynamodb.model.ScanRequest;
import software.amazon.awssdk.services.dynamodb.model.ScanResponse;
import software.amazon.awssdk.services.dynamodb.model.StreamSpecification;
import software.amazon.awssdk.services.dynamodb.model.StreamViewType;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class StreamsAdapterDemoHelper {

    /**
     * @return StreamArn
     */
    public static String createTable(DynamoDbAsyncClient client, String tableName) {
        List<AttributeDefinition> attributeDefinitions = new ArrayList<>();
        attributeDefinitions.add(AttributeDefinition.builder()
                .attributeName("Id")
                .attributeType("N")
                .build());

        List<KeySchemaElement> keySchema = new ArrayList<>();
        keySchema.add(KeySchemaElement.builder()
                .attributeName("Id")
                .keyType(KeyType.HASH) // Partition key
                .build());

        StreamSpecification streamSpecification = StreamSpecification.builder()
                .streamEnabled(true)
                .streamViewType(StreamViewType.NEW_IMAGE)
                .build();

        CreateTableRequest createTableRequest = CreateTableRequest.builder()
                .tableName(tableName)
                .attributeDefinitions(attributeDefinitions)
                .keySchema(keySchema)
                .billingMode(BillingMode.PAY_PER_REQUEST)
                .streamSpecification(streamSpecification)
                .build();

        try {
            System.out.println("Creating table " + tableName);
            CreateTableResponse result = client.createTable(createTableRequest).join();
            return result.tableDescription().latestStreamArn();
        } catch (Exception e) {
            if (e.getCause() instanceof ResourceInUseException) {
                System.out.println("Table already exists.");
                return describeTable(client, tableName).table().latestStreamArn();
            }
            throw e;
        }
    }

    public static DescribeTableResponse describeTable(DynamoDbAsyncClient client, String tableName) {
        return client.describeTable(DescribeTableRequest.builder()
                        .tableName(tableName)
                        .build())
                .join();
    }

    public static ScanResponse scanTable(DynamoDbAsyncClient dynamoDbClient, String tableName) {
        return dynamoDbClient.scan(ScanRequest.builder()
                        .tableName(tableName)
                        .build())
                .join();
    }

    public static void putItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id, String val) {
        Map<String, AttributeValue> item = new HashMap<>();
        item.put("Id", AttributeValue.builder().n(id).build());
        item.put("attribute-1", AttributeValue.builder().s(val).build());

        putItem(dynamoDbClient, tableName, item);
    }

    public static void putItem(DynamoDbAsyncClient dynamoDbClient, String tableName,
                               Map<String, AttributeValue> items) {
        PutItemRequest putItemRequest = PutItemRequest.builder()
                .tableName(tableName)
                .item(items)
                .build();
        dynamoDbClient.putItem(putItemRequest).join();
    }

    public static void updateItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id, String val) {
        Map<String, AttributeValue> key = new HashMap<>();
        key.put("Id", AttributeValue.builder().n(id).build());

        Map<String, String> expressionAttributeNames = new HashMap<>();
        expressionAttributeNames.put("#attr2", "attribute-2");

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

        UpdateItemRequest updateItemRequest = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .updateExpression("SET #attr2 = :val")
                .expressionAttributeNames(expressionAttributeNames)
                .expressionAttributeValues(expressionAttributeValues)
                .build();

        dynamoDbClient.updateItem(updateItemRequest).join();
    }

    public static void deleteItem(DynamoDbAsyncClient dynamoDbClient, String tableName, String id) {
        Map<String, AttributeValue> key = new HashMap<>();
        key.put("Id", AttributeValue.builder().n(id).build());

        DeleteItemRequest deleteItemRequest = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(key)
                .build();
        dynamoDbClient.deleteItem(deleteItemRequest).join();
    }
}
```

# API de bas niveau DynamoDB Streams : exemple Java
<a name="Streams.LowLevel.Walkthrough"></a>

**Note**  
Le code sur cette page n’est pas exhaustif et ne gère pas tous les scénarios de consommation d’Amazon DynamoDB Streams. La manière recommandée d’utiliser les enregistrements de flux de DynamoDB est de le faire via l’adaptateur Amazon Kinesis en utilisant la bibliothèque client Kinesis (KCL), comme décrit dans [Utilisation de l’adaptateur DynamoDB Streams Kinesis pour traiter des enregistrements de flux](Streams.KCLAdapter.md).

Cette section contient un programme Java qui affiche DynamoDB Streams en action. Le programme exécute les tâches suivantes :

1. Crée une table DynamoDB avec un flux activé.

1. Décrit les paramètres de flux de cette table.

1. Modifie les données de la table.

1. Décrit les partitions du flux.

1. Lit les enregistrements de flux des partitions.

1. Récupère les partitions enfants et continue de lire les enregistrements.

1. Nettoie.

Lorsque vous exécutez le programme, vous obtenez une sortie similaire à ce qui suit :

```
Testing Streams Demo
Creating an Amazon DynamoDB table TestTableForStreams with a simple primary key: Id
Waiting for TestTableForStreams to be created...
Current stream ARN for TestTableForStreams: arn:aws:dynamodb:us-east-2:123456789012:table/TestTableForStreams/stream/2018-03-20T16:49:55.208
Stream enabled: true
Update view type: NEW_AND_OLD_IMAGES

Performing write activities on TestTableForStreams
Processing item 1 of 100
Processing item 2 of 100
Processing item 3 of 100
...
Processing item 100 of 100
Shard: {ShardId: shardId-1234567890-...,SequenceNumberRange: {StartingSequenceNumber: 100002572486797508907,},}
    Shard iterator: EjYFEkX2a26eVTWe...
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, NewImage={Message=AttributeValue(S=New Item!), Id=AttributeValue(S=4)}, SequenceNumber=2000001584047545833909, SizeBytes=22, StreamViewType=NEW_AND_OLD_IMAGES)
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, NewImage={Message=AttributeValue(S=This is an updated item), Id=AttributeValue(S=4)}, OldImage={Message=AttributeValue(S=New Item!), Id=AttributeValue(S=4)}, SequenceNumber=2100003604869767892701, SizeBytes=55, StreamViewType=NEW_AND_OLD_IMAGES)
        StreamRecord(ApproximateCreationDateTime=2025-04-09T13:11:58Z, Keys={Id=AttributeValue(S=4)}, OldImage={Message=AttributeValue(S=This is an updated item), Id=AttributeValue(S=4)}, SequenceNumber=2200001099771112898434, SizeBytes=36, StreamViewType=NEW_AND_OLD_IMAGES)
...
Deleting the table...
Table StreamsDemoTable deleted.
Demo complete
```

**Example Exemple**  

```
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import software.amazon.awssdk.core.waiters.WaiterResponse;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeAction;
import software.amazon.awssdk.services.dynamodb.model.AttributeDefinition;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.AttributeValueUpdate;
import software.amazon.awssdk.services.dynamodb.model.BillingMode;
import software.amazon.awssdk.services.dynamodb.model.CreateTableRequest;
import software.amazon.awssdk.services.dynamodb.model.CreateTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DeleteItemRequest;
import software.amazon.awssdk.services.dynamodb.model.DeleteTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeStreamRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeStreamResponse;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableRequest;
import software.amazon.awssdk.services.dynamodb.model.DescribeTableResponse;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.GetRecordsRequest;
import software.amazon.awssdk.services.dynamodb.model.GetRecordsResponse;
import software.amazon.awssdk.services.dynamodb.model.GetShardIteratorRequest;
import software.amazon.awssdk.services.dynamodb.model.GetShardIteratorResponse;
import software.amazon.awssdk.services.dynamodb.model.KeySchemaElement;
import software.amazon.awssdk.services.dynamodb.model.KeyType;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.Record;
import software.amazon.awssdk.services.dynamodb.model.ScalarAttributeType;
import software.amazon.awssdk.services.dynamodb.model.Shard;
import software.amazon.awssdk.services.dynamodb.model.ShardFilter;
import software.amazon.awssdk.services.dynamodb.model.ShardFilterType;
import software.amazon.awssdk.services.dynamodb.model.ShardIteratorType;
import software.amazon.awssdk.services.dynamodb.model.StreamSpecification;
import software.amazon.awssdk.services.dynamodb.model.TableDescription;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.streams.DynamoDbStreamsClient;
import software.amazon.awssdk.services.dynamodb.waiters.DynamoDbWaiter;

public class StreamsLowLevelDemo {


    public static void main(String[] args) {
        final String usage = "Testing Streams Demo";
        try {
            System.out.println(usage);

            String tableName = "StreamsDemoTable";
            String key = "Id";
            System.out.println("Creating an Amazon DynamoDB table " + tableName + " with a simple primary key: " + key);
            Region region = Region.US_WEST_2;
            DynamoDbClient ddb = DynamoDbClient.builder()
                    .region(region)
                    .build();

            DynamoDbStreamsClient ddbStreams = DynamoDbStreamsClient.builder()
                    .region(region)
                    .build();
            DescribeTableRequest describeTableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();
            TableDescription tableDescription = null;
            try{
                tableDescription = ddb.describeTable(describeTableRequest).table();
            }catch (Exception e){
                System.out.println("Table " + tableName + " does not exist.");
                tableDescription = createTable(ddb, tableName, key);
            }

            // Print the stream settings for the table
            String streamArn = tableDescription.latestStreamArn();
           
            StreamSpecification streamSpec = tableDescription.streamSpecification();
            System.out.println("Current stream ARN for " + tableDescription.tableName() + ": " +
                   streamArn);
            System.out.println("Stream enabled: " + streamSpec.streamEnabled());
            System.out.println("Update view type: " + streamSpec.streamViewType());
            System.out.println();
            // Generate write activity in the table
            System.out.println("Performing write activities on " + tableName);
            int maxItemCount = 100;
            for (Integer i = 1; i <= maxItemCount; i++) {
                System.out.println("Processing item " + i + " of " + maxItemCount);
                // Write a new item
                putItemInTable(key, i, tableName, ddb);
                // Update the item
                updateItemInTable(key, i, tableName, ddb);
                // Delete the item
                deleteDynamoDBItem(key, i, tableName, ddb);
            }

            // Process Stream
            processStream(streamArn, maxItemCount, ddb, ddbStreams, tableName);

            // Delete the table
            System.out.println("Deleting the table...");
            DeleteTableRequest deleteTableRequest = DeleteTableRequest.builder()
                    .tableName(tableName)
                    .build();
            ddb.deleteTable(deleteTableRequest);
            System.out.println("Table " + tableName + " deleted.");
            System.out.println("Demo complete");
            ddb.close();
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
    }

    private static void processStream(String streamArn, int maxItemCount, DynamoDbClient ddb, DynamoDbStreamsClient ddbStreams, String tableName) {
        // Get all the shard IDs from the stream. Note that DescribeStream returns
        // the shard IDs one page at a time.
        String lastEvaluatedShardId = null;
        do {
            DescribeStreamRequest describeStreamRequest = DescribeStreamRequest.builder()
                    .streamArn(streamArn)
                    .exclusiveStartShardId(lastEvaluatedShardId).build();
            DescribeStreamResponse describeStreamResponse = ddbStreams.describeStream(describeStreamRequest);

            List<Shard> shards = describeStreamResponse.streamDescription().shards();

            // Process each shard on this page

            fetchShardsAndReadRecords(streamArn, maxItemCount, ddbStreams, shards);

            // If LastEvaluatedShardId is set, then there is
            // at least one more page of shard IDs to retrieve
            lastEvaluatedShardId = describeStreamResponse.streamDescription().lastEvaluatedShardId();

        } while (lastEvaluatedShardId != null);

    }

    private static void fetchShardsAndReadRecords(String streamArn, int maxItemCount, DynamoDbStreamsClient ddbStreams, List<Shard> shards) {
        for (Shard shard : shards) {
            String shardId = shard.shardId();
            System.out.println("Shard: " + shard);

            // Get an iterator for the current shard
            GetShardIteratorRequest shardIteratorRequest = GetShardIteratorRequest.builder()
                    .streamArn(streamArn).shardId(shardId)
                    .shardIteratorType(ShardIteratorType.TRIM_HORIZON).build();

            GetShardIteratorResponse getShardIteratorResult = ddbStreams.getShardIterator(shardIteratorRequest);

            String currentShardIter = getShardIteratorResult.shardIterator();

            // Shard iterator is not null until the Shard is sealed (marked as READ_ONLY).
            // To prevent running the loop until the Shard is sealed, we process only the
            // items that were written into DynamoDB and then exit.
            int processedRecordCount = 0;
            while (currentShardIter != null && processedRecordCount < maxItemCount) {
                // Use the shard iterator to read the stream records
                GetRecordsRequest getRecordsRequest = GetRecordsRequest.builder()
                        .shardIterator(currentShardIter).build();
                GetRecordsResponse getRecordsResult = ddbStreams.getRecords(getRecordsRequest);
                List<Record> records = getRecordsResult.records();
                for (Record record : records) {
                    System.out.println("        " + record.dynamodb());
                }
                processedRecordCount += records.size();
                currentShardIter = getRecordsResult.nextShardIterator();
            }
            if (currentShardIter == null){
                System.out.println("Shard has been fully processed. Shard iterator is null.");
                System.out.println("Fetch the child shard to continue processing instead of bulk fetching all shards");
                DescribeStreamRequest describeStreamRequestForChildShards = DescribeStreamRequest.builder()
                        .streamArn(streamArn)
                        .shardFilter(ShardFilter.builder()
                                .type(ShardFilterType.CHILD_SHARDS)
                                .shardId(shardId).build())
                        .build();
                DescribeStreamResponse describeStreamResponseChildShards = ddbStreams.describeStream(describeStreamRequestForChildShards);
                fetchShardsAndReadRecords(streamArn, maxItemCount, ddbStreams, describeStreamResponseChildShards.streamDescription().shards());
            }
        }
    }

    private static void putItemInTable(String key, Integer i, String tableName, DynamoDbClient ddb) {
        Map<String, AttributeValue> item = new HashMap<>();
        item.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());
        item.put("Message", AttributeValue.builder()
                .s("New Item!")
                .build());
        PutItemRequest request = PutItemRequest.builder()
                .tableName(tableName)
                .item(item)
                .build();
        ddb.putItem(request);
    }

    private static void updateItemInTable(String key, Integer i, String tableName, DynamoDbClient ddb) {

        HashMap<String, AttributeValue> itemKey = new HashMap<>();
        itemKey.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());


        HashMap<String, AttributeValueUpdate> updatedValues = new HashMap<>();
        updatedValues.put("Message", AttributeValueUpdate.builder()
                .value(AttributeValue.builder().s("This is an updated item").build())
                .action(AttributeAction.PUT)
                .build());

        UpdateItemRequest request = UpdateItemRequest.builder()
                .tableName(tableName)
                .key(itemKey)
                .attributeUpdates(updatedValues)
                .build();
        ddb.updateItem(request);
    }

    public static void deleteDynamoDBItem(String key, Integer i, String tableName, DynamoDbClient ddb) {
        HashMap<String, AttributeValue> keyToGet = new HashMap<>();
        keyToGet.put(key, AttributeValue.builder()
                .s(i.toString())
                .build());

        DeleteItemRequest deleteReq = DeleteItemRequest.builder()
                .tableName(tableName)
                .key(keyToGet)
                .build();
        ddb.deleteItem(deleteReq);
    }

    public static TableDescription createTable(DynamoDbClient ddb, String tableName, String key) {
        DynamoDbWaiter dbWaiter = ddb.waiter();
        StreamSpecification streamSpecification = StreamSpecification.builder()
                .streamEnabled(true)
                .streamViewType("NEW_AND_OLD_IMAGES")
                .build();
        CreateTableRequest request = CreateTableRequest.builder()
                .attributeDefinitions(AttributeDefinition.builder()
                        .attributeName(key)
                        .attributeType(ScalarAttributeType.S)
                        .build())
                .keySchema(KeySchemaElement.builder()
                        .attributeName(key)
                        .keyType(KeyType.HASH)
                        .build())
                .billingMode(BillingMode.PAY_PER_REQUEST) //  DynamoDB automatically scales based on traffic.
                .tableName(tableName)
                .streamSpecification(streamSpecification)
                .build();

        TableDescription newTable;
        try {
            CreateTableResponse response = ddb.createTable(request);
            DescribeTableRequest tableRequest = DescribeTableRequest.builder()
                    .tableName(tableName)
                    .build();
                    
            System.out.println("Waiting for " + tableName + " to be created...");

            // Wait until the Amazon DynamoDB table is created.
            WaiterResponse<DescribeTableResponse> waiterResponse = dbWaiter.waitUntilTableExists(tableRequest);
            waiterResponse.matched().response().ifPresent(System.out::println);
            newTable = response.tableDescription();
            return newTable;

        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
        return null;
    }



}
```

# Streams et déclencheurs DynamoDB AWS Lambda
<a name="Streams.Lambda"></a>

Amazon DynamoDB est intégré afin que vous puissiez *créer AWS Lambda * des déclencheurs, des éléments de code qui répondent automatiquement aux événements dans DynamoDB Streams. Avec des déclencheurs, vous pouvez créer des applications qui réagissent à des modifications de données dans des tables DynamoDB.

**Topics**
+ [Tutoriel \$11 : Utilisation de filtres pour traiter tous les événements avec Amazon AWS Lambda DynamoDB et utilisation du AWS CLI](Streams.Lambda.Tutorial.md)
+ [Tutoriel n° 2 : utilisation de filtres pour traiter certains événements avec DynamoDB et Lambda](Streams.Lambda.Tutorial2.md)
+ [Bonnes pratiques relatives à l’utilisation de DynamoDB Streams avec Lambda](Streams.Lambda.BestPracticesWithDynamoDB.md)

Si vous activez DynamoDB Streams sur une table, vous pouvez associer le flux Amazon Resource Name (ARN) à une AWS Lambda fonction que vous écrivez. Toutes les actions de mutation vers cette table DynamoDB peuvent ensuite être capturées en tant qu’élément dans le flux. Par exemple, vous pouvez définir un déclencheur pour que, lorsqu’un élément de table est modifié, un nouvel enregistrement apparaisse immédiatement dans le flux de cette table. 

**Note**  
Si vous abonnez plus de deux fonctions Lambda à un flux DynamoDB, une limitation de lecture peut se produire.

Le service [AWS Lambda](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html) interroge le flux à la recherche de nouveaux enregistrements quatre fois par seconde. Lorsque de nouveaux enregistrements de flux sont disponibles, votre fonction Lambda est invoquée de manière synchrone. Vous pouvez abonner jusqu’à deux fonctions Lambda au même flux DynamoDB. Si vous abonnez plus de deux fonctions Lambda au même flux DynamoDB, une limitation de lecture peut se produire.

La fonction Lambda peut envoyer une notification, lancer un flux de travail ou effectuer un grand nombre d’actions spécifiées par vos soins. Vous pouvez écrire une fonction Lambda simplement afin de copier chaque enregistrement de flux vers un stockage permanent tel qu’Amazon S3 File Gateway (Amazon S3) et créer une piste d’audit permanente de l’activité d’écriture dans votre table. Ou supposons que vous ayez une application de jeux pour appareils mobiles qui écrive dans une table `GameScores`. Chaque fois que l’attribut `TopScore` de la table `GameScores` est mis à jour, un enregistrement de flux correspondant est écrit dans le flux de la table. Cet événement peut alors déclencher une fonction Lambda qui publie un message de félicitations sur un réseau social. Cette fonction ignorerait simplement tout enregistrement de flux qui ne serait pas une mise à jour de `GameScores`, ou qui ne modifierait pas l’attribut `TopScore`.

Si votre fonction renvoie une erreur, Lambda réessaie de traiter le lot jusqu’à ce que le traitement réussisse ou que les données expirent. Vous pouvez également configurer Lambda pour effectuer de nouvelles tentatives avec un lot plus petit, limiter le nombre de tentatives, supprimer les enregistrements une fois qu’ils sont trop anciens et d’autres options.

Afin de respecter les bonnes pratiques en matière de performances, la fonction Lambda doit être de courte durée. Pour éviter d’introduire des retards de traitement inutiles, elle ne doit pas non plus exécuter de logique complexe. Pour un flux à haute vitesse en particulier, il est préférable de déclencher des flux de travail asynchrones avec des fonctions de post-traitement par étapes plutôt que des Lambdas synchrones de longue durée.

 Vous pouvez utiliser des déclencheurs Lambda sur différents AWS comptes en configurant une politique basée sur les ressources sur le flux DynamoDB afin d'accorder à la fonction Lambda un accès en lecture entre comptes. Pour en savoir plus sur la façon de configurer votre flux afin d'autoriser l'accès entre comptes, voir [Partager l'accès avec les fonctions AWS Lambda entre comptes dans](rbac-cross-account-access.md#shared-access-cross-acount-lambda) le guide du développeur DynamoDB.

Pour plus d'informations à ce sujet AWS Lambda, consultez le [guide du AWS Lambda développeur](https://docs.aws.amazon.com/lambda/latest/dg/).

# Tutoriel \$11 : Utilisation de filtres pour traiter tous les événements avec Amazon AWS Lambda DynamoDB et utilisation du AWS CLI
<a name="Streams.Lambda.Tutorial"></a>

 

Dans ce didacticiel, vous allez créer un AWS Lambda déclencheur pour traiter un flux provenant d'une table DynamoDB.

**Topics**
+ [Étape 1 : créer une table DynamoDB avec un flux activé](#Streams.Lambda.Tutorial.CreateTable)
+ [Étape 2 : créer un rôle d’exécution Lambda](#Streams.Lambda.Tutorial.CreateRole)
+ [Étape 3 : créer une rubrique Amazon SNS](#Streams.Lambda.Tutorial.SNSTopic)
+ [Étape 4 : créer et tester une fonction Lambda](#Streams.Lambda.Tutorial.LambdaFunction)
+ [Étape 5 : créer et tester un déclencheur](#Streams.Lambda.Tutorial.CreateTrigger)

Le scénario de ce didacticiel est Woofer, un réseau social simple. Les utilisateurs de Woofer communiquent avec des *aboiements* (messages textuels brefs) qui sont envoyés à d’autres utilisateurs de Woofer. Le schéma suivant illustre les composants et le flux de travail de cette application.

![\[Flux de travail d’application Woofer composé d’une table DynamoDB, d’un enregistrement de flux, d’une fonction Lambda et d’une rubrique Amazon SNS.\]](http://docs.aws.amazon.com/fr_fr/amazondynamodb/latest/developerguide/images/StreamsAndTriggers.png)


1. Un utilisateur écrit un élément dans une table DynamoDB (`BarkTable`). Chaque élément de la table représente un aboiement.

1. Un nouvel enregistrement de flux est écrit pour refléter l’ajout de ce nouvel élément à `BarkTable`.

1. Le nouvel enregistrement du flux déclenche une AWS Lambda fonction (`publishNewBark`).

1. Si l’enregistrement de flux indique qu’un nouvel élément a été ajouté à `BarkTable`, la fonction Lambda lit les données de l’enregistrement de flux et publie un message sur une rubrique dans Amazon Simple Notification Service (Amazon SNS).

1. Le message est reçu par les abonnés à la rubrique Amazon SNS. Dans le cadre de ce didacticiel, le seul abonné est une adresse e-mail.

**Avant de commencer**  
Ce didacticiel utilise le AWS Command Line Interface AWS CLI. Si vous ne l’avez déjà fait, suivez les instructions du [Guide de l’utilisateur AWS Command Line Interface](https://docs.aws.amazon.com/cli/latest/userguide/) pour installer et configurer l’ AWS CLI.

## Étape 1 : créer une table DynamoDB avec un flux activé
<a name="Streams.Lambda.Tutorial.CreateTable"></a>

Au cours de cette étape, vous allez créer une table DynamoDB (`BarkTable`) pour stocker tous les aboiements des utilisateurs de Woofer. La clé primaire se compose de `Username` (clé de partition) et de `Timestamp` (clé de tri). Les deux attributs sont de type string (chaîne).

`BarkTable` a un flux activé. Plus loin dans ce didacticiel, vous allez créer un déclencheur en associant une AWS Lambda fonction au flux.

1. Créez le flux à l’aide de la commande suivante.

   ```
   aws dynamodb create-table \
       --table-name BarkTable \
       --attribute-definitions AttributeName=Username,AttributeType=S AttributeName=Timestamp,AttributeType=S \
       --key-schema AttributeName=Username,KeyType=HASH  AttributeName=Timestamp,KeyType=RANGE \
       --provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 \
       --stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
   ```

1. Dans la sortie, recherchez le `LatestStreamArn`.

   ```
   ...
   "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

   Notez `region` et `accountID`, car vous en aurez besoin pour les autres étapes de ce didacticiel.

## Étape 2 : créer un rôle d’exécution Lambda
<a name="Streams.Lambda.Tutorial.CreateRole"></a>

Au cours de cette étape, vous créez un rôle Gestion des identités et des accès AWS (IAM) (`WooferLambdaRole`) et vous lui attribuez des autorisations. Ce rôle sera utilisé par la fonction Lambda que vous allez créer dans [Étape 4 : créer et tester une fonction Lambda](#Streams.Lambda.Tutorial.LambdaFunction). 

Vous allez également créer une politique pour le rôle. Cette politique contient toutes les autorisations dont la fonction Lambda a besoin lors de l’exécution.

1. Créez un fichier nommé `trust-relationship.json` avec les contenus suivants.

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

****  

   ```
   {
      "Version":"2012-10-17",		 	 	 
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Service": "lambda.amazonaws.com"
          },
          "Action": "sts:AssumeRole"
        }
      ]
    }
   ```

------

1. Entrez la commande suivante pour créer `WooferLambdaRole`.

   ```
   aws iam create-role --role-name WooferLambdaRole \
       --path "/service-role/" \
       --assume-role-policy-document file://trust-relationship.json
   ```

1. Créez un fichier nommé `role-policy.json` avec les contenus suivants. (Remplacez `region` et `accountID` par votre AWS région et votre numéro de compte.)

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Effect": "Allow",
               "Action": [
                   "logs:CreateLogGroup",
                   "logs:CreateLogStream",
                   "logs:PutLogEvents"
               ],
               "Resource": "arn:aws:logs:us-east-1:111122223333:*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "dynamodb:DescribeStream",
                   "dynamodb:GetRecords",
                   "dynamodb:GetShardIterator",
                   "dynamodb:ListStreams"
               ],
               "Resource": "arn:aws:dynamodb:us-east-1:111122223333:table/BarkTable/stream/*"
           },
           {
               "Effect": "Allow",
               "Action": [
                   "sns:Publish"
               ],
               "Resource": [
                   "*"
               ]
           }
       ]
   }
   ```

------

   La politique comporte quatre instructions pour autoriser `WooferLambdaRole` à effectuer les opérations suivantes :
   + Exécutez une fonction Lambda (`publishNewBark`). Vous allez créer cette fonction plus tard dans le cadre de ce didacticiel.
   + Accédez à Amazon CloudWatch Logs. La fonction Lambda écrit les diagnostics dans les CloudWatch journaux au moment de l'exécution.
   + Lisez les données du flux DynamoDB pour `BarkTable`.
   + Publiez des messages sur Amazon SNS.

1. Exécutez la commande suivante pour associer la politique à `WooferLambdaRole`.

   ```
   aws iam put-role-policy --role-name WooferLambdaRole \
       --policy-name WooferLambdaRolePolicy \
       --policy-document file://role-policy.json
   ```

## Étape 3 : créer une rubrique Amazon SNS
<a name="Streams.Lambda.Tutorial.SNSTopic"></a>

Au cours de cette étape, vous allez créer une rubrique Amazon SNS (`wooferTopic`) et y abonner une adresse e-mail. Votre fonction Lambda utilise cette rubrique pour publier de nouveaux aboiements des utilisateurs de Woofer.

1. Entrez la commande suivante pour créer une rubrique Amazon SNS.

   ```
   aws sns create-topic --name wooferTopic
   ```

1. Tapez la commande suivante pour abonner une adresse e-mail à `wooferTopic`. (Remplacez `region` et `accountID` par votre région  AWS et votre ID de compte, puis remplacez `example@example.com` par une adresse e-mail valide.)

   ```
   aws sns subscribe \
       --topic-arn arn:aws:sns:region:accountID:wooferTopic \
       --protocol email \
       --notification-endpoint example@example.com
   ```

1. Amazon SNS envoie un message de confirmation à votre adresse e-mail. Cliquez sur le lien **Confirm subscription (Confirmer l’abonnement)** de ce message pour finaliser le processus d’abonnement.

## Étape 4 : créer et tester une fonction Lambda
<a name="Streams.Lambda.Tutorial.LambdaFunction"></a>

Au cours de cette étape, vous créez une AWS Lambda fonction (`publishNewBark`) pour traiter les enregistrements de flux à partir de`BarkTable`.

La fonction `publishNewBark` traite uniquement les événements de flux qui correspondent aux nouveaux éléments de `BarkTable`. La fonction lit les données d’un tel événement, puis appelle Amazon SNS pour les publier.

1. Créez un fichier nommé `publishNewBark.js` avec les contenus suivants. Remplacez `region` et `accountID` par votre AWS région et votre numéro de compte.

   ```
   'use strict';
   var AWS = require("aws-sdk");
   var sns = new AWS.SNS();
   
   exports.handler = (event, context, callback) => {
   
       event.Records.forEach((record) => {
           console.log('Stream record: ', JSON.stringify(record, null, 2));
   
           if (record.eventName == 'INSERT') {
               var who = JSON.stringify(record.dynamodb.NewImage.Username.S);
               var when = JSON.stringify(record.dynamodb.NewImage.Timestamp.S);
               var what = JSON.stringify(record.dynamodb.NewImage.Message.S);
               var params = {
                   Subject: 'A new bark from ' + who,
                   Message: 'Woofer user ' + who + ' barked the following at ' + when + ':\n\n ' + what,
                   TopicArn: 'arn:aws:sns:region:accountID:wooferTopic'
               };
               sns.publish(params, function(err, data) {
                   if (err) {
                       console.error("Unable to send message. Error JSON:", JSON.stringify(err, null, 2));
                   } else {
                       console.log("Results from sending message: ", JSON.stringify(data, null, 2));
                   }
               });
           }
       });
       callback(null, `Successfully processed ${event.Records.length} records.`);
   };
   ```

1. Créez un fichier zip pour `publishNewBark.js`. Si vous disposez de l’utilitaire de ligne de commande pour zipper, vous pouvez taper la commande suivante.

   ```
   zip publishNewBark.zip publishNewBark.js
   ```

1. Lorsque vous créez la fonction Lambda, vous spécifiez l’Amazon Resource Name (ARN) pour `WooferLambdaRole`, que vous avez créé dans [Étape 2 : créer un rôle d’exécution Lambda](#Streams.Lambda.Tutorial.CreateRole). Tapez la commande suivante pour extraire cet ARN.

   ```
   aws iam get-role --role-name WooferLambdaRole
   ```

   Dans la sortie, recherchez l’ARN pour `WooferLambdaRole`.

   ```
   ...
   "Arn": "arn:aws:iam::region:role/service-role/WooferLambdaRole"
   ...
   ```

   Utilisez la commande suivante pour créer la fonction Lambda. Remplacez *roleARN* par l'ARN pour`WooferLambdaRole`.

   ```
   aws lambda create-function \
       --region region \
       --function-name publishNewBark \
       --zip-file fileb://publishNewBark.zip \
       --role roleARN \
       --handler publishNewBark.handler \
       --timeout 5 \
       --runtime nodejs16.x
   ```

1. Maintenant, testez `publishNewBark` pour vérifier le bon fonctionnement. Pour cela, vous entrez des informations similaires à un enregistrement réel de DynamoDB Streams.

   Créez un fichier nommé `payload.json` avec les contenus suivants. Remplacez `region` et `accountID` par votre Région AWS et votre ID de compte.

   ```
   {
       "Records": [
           {
               "eventID": "7de3041dd709b024af6f29e4fa13d34c",
               "eventName": "INSERT",
               "eventVersion": "1.1",
               "eventSource": "aws:dynamodb",
               "awsRegion": "region",
               "dynamodb": {
                   "ApproximateCreationDateTime": 1479499740,
                   "Keys": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "NewImage": {
                       "Timestamp": {
                           "S": "2016-11-18:12:09:36"
                       },
                       "Message": {
                           "S": "This is a bark from the Woofer social network"
                       },
                       "Username": {
                           "S": "John Doe"
                       }
                   },
                   "SequenceNumber": "13021600000000001596893679",
                   "SizeBytes": 112,
                   "StreamViewType": "NEW_IMAGE"
               },
               "eventSourceARN": "arn:aws:dynamodb:region:account ID:table/BarkTable/stream/2016-11-16T20:42:48.104"
           }
       ]
   }
   ```

   Testez la fonction `publishNewBark` à l’aide de la commande suivante.

   ```
   aws lambda invoke --function-name publishNewBark --payload file://payload.json --cli-binary-format raw-in-base64-out output.txt
   ```

   Si le test est réussi, vous verrez la sortie suivante.

   ```
   {
       "StatusCode": 200,
       "ExecutedVersion": "$LATEST"
   }
   ```

   De plus, le fichier `output.txt` contiendra le texte suivant.

   ```
   "Successfully processed 1 records."
   ```

   Vous recevrez également un nouveau message électronique quelques minutes après.
**Note**  
AWS Lambda écrit des informations de diagnostic dans Amazon CloudWatch Logs. Si vous rencontrez des erreurs avec la fonction Lambda, vous pouvez utiliser ces diagnostics à des fins de dépannage :  
Ouvrez la CloudWatch console à l'adresse [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).
Dans le panneau de navigation, sélectionnez **Logs** (Journaux).
Choisissez le groupe de journal suivant : `/aws/lambda/publishNewBark`
Choisissez le dernier flux de journal pour consulter la sortie (et les erreurs) de la fonction.

## Étape 5 : créer et tester un déclencheur
<a name="Streams.Lambda.Tutorial.CreateTrigger"></a>

Dans [Étape 4 : créer et tester une fonction Lambda](#Streams.Lambda.Tutorial.LambdaFunction), vous avez testé la fonction Lambda pour vérifier qu’elle s’exécutait correctement. Au cours de cette étape, vous allez créer un *déclencheur* en associant la fonction Lambda (`publishNewBark`) à une source d’événement (le flux `BarkTable`).

1. Lorsque vous créez le déclencheur, vous devez spécifier l’ARN du flux `BarkTable`. Tapez la commande suivante pour extraire cet ARN.

   ```
   aws dynamodb describe-table --table-name BarkTable
   ```

   Dans la sortie, recherchez le `LatestStreamArn`.

   ```
   ...
    "LatestStreamArn": "arn:aws:dynamodb:region:accountID:table/BarkTable/stream/timestamp
   ...
   ```

1. Tapez la commande suivante pour créer le déclencheur. Remplacez `streamARN` par l’ARN du flux réel.

   ```
   aws lambda create-event-source-mapping \
       --region region \
       --function-name publishNewBark \
       --event-source streamARN  \
       --batch-size 1 \
       --starting-position TRIM_HORIZON
   ```

1. Testez le déclencheur. Tapez la commande suivante pour ajouter un élément à `BarkTable`.

   ```
   aws dynamodb put-item \
       --table-name BarkTable \
       --item Username={S="Jane Doe"},Timestamp={S="2016-11-18:14:32:17"},Message={S="Testing...1...2...3"}
   ```

   Vous devriez recevoir un nouveau message électronique quelques minutes après.

1. Ouvrez la console DynamoDB et ajoutez quelques éléments à `BarkTable`. Vous devez spécifier les valeurs des attributs `Username` et `Timestamp`. Vous devez également spécifier une valeur pour `Message`, bien que cela ne soit pas obligatoire. Vous devriez recevoir un nouveau message électronique pour chaque élément ajouté à `BarkTable`.

   La fonction Lambda traite uniquement les nouveaux éléments que vous ajoutez à `BarkTable`. Si vous mettez à jour ou supprimez un élément dans la table, la fonction ne fait rien.

**Note**  
AWS Lambda écrit des informations de diagnostic dans Amazon CloudWatch Logs. Si vous rencontrez des erreurs avec la fonction Lambda, vous pouvez utiliser ces diagnostics à des fins de dépannage.  
Ouvrez la CloudWatch console à l'adresse [https://console.aws.amazon.com/cloudwatch/](https://console.aws.amazon.com/cloudwatch/).
Dans le panneau de navigation, sélectionnez **Logs** (Journaux).
Choisissez le groupe de journal suivant : `/aws/lambda/publishNewBark`
Choisissez le dernier flux de journal pour consulter la sortie (et les erreurs) de la fonction.

# Tutoriel n° 2 : utilisation de filtres pour traiter certains événements avec DynamoDB et Lambda
<a name="Streams.Lambda.Tutorial2"></a>

Dans ce didacticiel, vous allez créer un AWS Lambda déclencheur pour traiter uniquement certains événements d'un flux à partir d'une table DynamoDB.

**Topics**
+ [Tout mettre en place - CloudFormation](#Streams.Lambda.Tutorial2.Cloudformation)
+ [Synthèse – CDK](#Streams.Lambda.Tutorial2.CDK)

Avec le [filtrage des événements Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html), vous pouvez utiliser des expressions de filtre pour contrôler les événements envoyés par Lambda à votre fonction pour traitement. Vous pouvez configurer jusqu’à 5 filtres différents par flux DynamoDB. Si vous utilisez des fenêtres de traitement par lots, Lambda applique les critères de filtre à chaque nouvel événement pour déterminer s’il doit être ajouté au lot actuel.

Les filtres sont appliqués via des structures nommées `FilterCriteria`. Les 3 principaux attributs de `FilterCriteria` sont `metadata properties`, `data properties` et `filter patterns`. 

Voici un exemple de structure d’un événement DynamoDB Streams :

```
{
  "eventID": "c9fbe7d0261a5163fcb6940593e41797",
  "eventName": "INSERT",
  "eventVersion": "1.1",
  "eventSource": "aws:dynamodb",
  "awsRegion": "us-east-2",
  "dynamodb": {
    "ApproximateCreationDateTime": 1664559083.0,
    "Keys": {
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" }
    },
    "NewImage": {
      "quantity": { "N": "50" },
      "company_id": { "S": "1000" },
      "fabric": { "S": "Florida Chocolates" },
      "price": { "N": "15" },
      "stores": { "N": "5" },
      "product_id": { "S": "1000" },
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" },
      "state": { "S": "FL" },
      "type": { "S": "" }
    },
    "SequenceNumber": "700000000000888747038",
    "SizeBytes": 174,
    "StreamViewType": "NEW_AND_OLD_IMAGES"
  },
  "eventSourceARN": "arn:aws:dynamodb:us-east-2:111122223333:table/chocolate-table-StreamsSampleDDBTable-LUOI6UXQY7J1/stream/2022-09-30T17:05:53.209"
}
```

Les `metadata properties` correspondent aux champs de l’objet d’événement. Dans le cas de DynamoDB Streams, les `metadata properties` correspondent à des champs tels que `dynamodb` ou `eventName`. 

Les `data properties` correspondent aux champs du corps de l’événement. Pour filtrer sur `data properties`, veillez à les contenir dans `FilterCriteria` à l’intérieur de la clé appropriée. Pour les sources d’événements DynamoDB, la clé de données est `NewImage` ou `OldImage`.

En dernier lieu, les règles de filtrage définissent l’expression de filtre que vous appliquez à une propriété spécifique. Voici quelques exemples :


| Opérateur de comparaison | Exemple | Syntaxe des règles (partielle) | 
| --- | --- | --- | 
|  Null  |  Type de produit null  |  `{ "product_type": { "S": null } } `  | 
|  Vide  |  Nom du produit vide  |  `{ "product_name": { "S": [ ""] } } `  | 
|  Égal à  |  État égal à Floride  |  `{ "state": { "S": ["FL"] } } `  | 
|  Et  |  État du produit égal à Floride et catégorie de produit Chocolat  |  `{ "state": { "S": ["FL"] } , "category": { "S": [ "CHOCOLATE"] } } `  | 
|  Or  |  L’État du produit est la Floride ou la Californie  |  `{ "state": { "S": ["FL","CA"] } } `  | 
|  Pas  |  L’État du produit n’est pas la Floride  |  `{"state": {"S": [{"anything-but": ["FL"]}]}}`  | 
|  Existe  |  Le produit fait maison existe  |  `{"homemade": {"S": [{"exists": true}]}}`  | 
|  N’existe pas  |  Le produit fait maison n’existe pas  |  `{"homemade": {"S": [{"exists": false}]}}`  | 
|  Commence par  |  PK commence par COMPANY  |  `{"PK": {"S": [{"prefix": "COMPANY"}]}}`  | 

Vous pouvez spécifier jusqu’à 5 modèles de filtrage des événements pour une fonction Lambda. Notez que chacun de ces 5 événements sera évalué comme un OR logique. Donc, si vous configurez deux filtres nommés `Filter_One` et `Filter_Two`, la fonction Lambda exécutera `Filter_One` OR `Filter_Two`.

**Note**  
La page de [filtrage des événements Lambda](https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html) propose certaines options permettant de filtrer et de comparer des valeurs numériques. Toutefois, dans le cas des événements de filtre DynamoDB, cela ne s’applique pas, car les nombres dans DynamoDB sont stockés sous forme de chaînes. Par exemple ` "quantity": { "N": "50" }`, nous savons que c’est un numéro grâce à la propriété `"N"`.

## Tout mettre en place - CloudFormation
<a name="Streams.Lambda.Tutorial2.Cloudformation"></a>

Pour illustrer la fonctionnalité de filtrage des événements dans la pratique, voici un exemple de CloudFormation modèle. Ce modèle va générer une table DynamoDB simple avec une clé de partition PK et une clé de tri SK avec Amazon DynamoDB Streams activé. Il créera une fonction Lambda et un rôle d’exécution Lambda simple qui permettront d’écrire des journaux dans Amazon Cloudwatch et de lire les événements depuis le flux Amazon DynamoDB. Il ajoutera également le mappage des sources d’événements entre les DynamoDB Streams et la fonction Lambda, afin que la fonction puisse être exécutée chaque fois qu’un événement se produit dans Amazon DynamoDB Stream.

```
AWSTemplateFormatVersion: "2010-09-09"

Description: Sample application that presents AWS Lambda event source filtering 
with Amazon DynamoDB Streams.

Resources:
  StreamsSampleDDBTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: "PK"
          AttributeType: "S"
        - AttributeName: "SK"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "PK"
          KeyType: "HASH"
        - AttributeName: "SK"
          KeyType: "RANGE"
      StreamSpecification:
        StreamViewType: "NEW_AND_OLD_IMAGES"
      ProvisionedThroughput:
        ReadCapacityUnits: 5
        WriteCapacityUnits: 5

  LambdaExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17",		 	 	 
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: "/"
      Policies:
        - PolicyName: root
          PolicyDocument:
            Version: "2012-10-17",		 	 	 
            Statement:
              - Effect: Allow
                Action:
                  - logs:CreateLogGroup
                  - logs:CreateLogStream
                  - logs:PutLogEvents
                Resource: arn:aws:logs:*:*:*
              - Effect: Allow
                Action:
                  - dynamodb:DescribeStream
                  - dynamodb:GetRecords
                  - dynamodb:GetShardIterator
                  - dynamodb:ListStreams
                Resource: !GetAtt StreamsSampleDDBTable.StreamArn

  EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST

  ProcessEventLambda:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.7
      Timeout: 300
      Handler: index.handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Code:
        ZipFile: |
          import logging

          LOGGER = logging.getLogger()
          LOGGER.setLevel(logging.INFO)

          def handler(event, context):
            LOGGER.info('Received Event: %s', event)
            for rec in event['Records']:
              LOGGER.info('Record: %s', rec)

Outputs:
  StreamsSampleDDBTable:
    Description: DynamoDB Table ARN created for this example
    Value: !GetAtt StreamsSampleDDBTable.Arn
  StreamARN:
    Description: DynamoDB Table ARN created for this example
    Value: !GetAtt StreamsSampleDDBTable.StreamArn
```

Après avoir déployé ce modèle CloudFormation, vous pouvez insérer l’élément Amazon DynamoDB suivant :

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK",
 "company_id": "1000",
 "type": "",
 "state": "FL",
 "stores": 5,
 "price": 15,
 "quantity": 50,
 "fabric": "Florida Chocolates"
}
```

Grâce à la fonction lambda simple incluse en ligne dans ce modèle de formation de cloud, vous verrez les événements relatifs à la fonction lambda dans les groupes de CloudWatch logs Amazon de la manière suivante :

```
{
  "eventID": "c9fbe7d0261a5163fcb6940593e41797",
  "eventName": "INSERT",
  "eventVersion": "1.1",
  "eventSource": "aws:dynamodb",
  "awsRegion": "us-east-2",
  "dynamodb": {
    "ApproximateCreationDateTime": 1664559083.0,
    "Keys": {
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" }
    },
    "NewImage": {
      "quantity": { "N": "50" },
      "company_id": { "S": "1000" },
      "fabric": { "S": "Florida Chocolates" },
      "price": { "N": "15" },
      "stores": { "N": "5" },
      "product_id": { "S": "1000" },
      "SK": { "S": "PRODUCT#CHOCOLATE#DARK#1000" },
      "PK": { "S": "COMPANY#1000" },
      "state": { "S": "FL" },
      "type": { "S": "" }
    },
    "SequenceNumber": "700000000000888747038",
    "SizeBytes": 174,
    "StreamViewType": "NEW_AND_OLD_IMAGES"
  },
  "eventSourceARN": "arn:aws:dynamodb:us-east-2:111122223333:table/chocolate-table-StreamsSampleDDBTable-LUOI6UXQY7J1/stream/2022-09-30T17:05:53.209"
}
```

**Exemples de filtrage**
+ **Uniquement les produits qui correspondent à un État donné**

Cet exemple modifie le CloudFormation modèle pour inclure un filtre correspondant à tous les produits provenant de Floride, avec l'abréviation « FL ».

```
EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{ "dynamodb": { "NewImage": { "state": { "S": ["FL"] } } } }'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Une fois que vous avez redéployé la pile, vous pouvez ajouter l’élément DynamoDB suivant à la table. Notez qu’il n’apparaîtra pas dans les journaux des fonctions Lambda, car le produit de cet exemple provient de Californie.

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK#1000",
 "company_id": "1000",
 "fabric": "Florida Chocolates",
 "price": 15,
 "product_id": "1000",
 "quantity": 50,
 "state": "CA",
 "stores": 5,
 "type": ""
}
```
+ **Uniquement les éléments qui commencent par certaines valeurs dans PK et SK**

Cet exemple modifie le CloudFormation modèle pour inclure la condition suivante :

```
EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{"dynamodb": {"Keys": {"PK": { "S": [{ "prefix": "COMPANY" }] },"SK": { "S": [{ "prefix": "PRODUCT" }] }}}}'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Notez que la condition AND exige que la condition se trouve à l’intérieur du modèle, où les clés PK et SK se trouvent dans la même expression, séparées par des virgules.

Soit vous commencez avec des valeurs sur PK et SK, soit le produit provient d’un État donné.

Cet exemple modifie le CloudFormation modèle pour inclure les conditions suivantes :

```
  EventSourceDDBTableStream:
    Type: AWS::Lambda::EventSourceMapping
    Properties:
      BatchSize: 1
      Enabled: True
      FilterCriteria:
        Filters:
          - Pattern: '{"dynamodb": {"Keys": {"PK": { "S": [{ "prefix": "COMPANY" }] },"SK": { "S": [{ "prefix": "PRODUCT" }] }}}}'
          - Pattern: '{ "dynamodb": { "NewImage": { "state": { "S": ["FL"] } } } }'
      EventSourceArn: !GetAtt StreamsSampleDDBTable.StreamArn
      FunctionName: !GetAtt ProcessEventLambda.Arn
      StartingPosition: LATEST
```

Notez que la condition OR est ajoutée en introduisant de nouveaux modèles dans la section des filtres.

## Synthèse – CDK
<a name="Streams.Lambda.Tutorial2.CDK"></a>

L’exemple de modèle de formation de projet CDK suivant décrit les fonctionnalités de filtrage des événements. Avant de travailler avec ce projet CDK, vous devez [installer les prérequis](https://docs.aws.amazon.com/cdk/v2/guide/work-with.html), y compris l’[exécution de scripts de préparation](https://docs.aws.amazon.com/cdk/v2/guide/work-with-cdk-python.html).

**Créer un projet CDK**

Créez d'abord un nouveau AWS CDK projet en l'invoquant `cdk init` dans un répertoire vide.

```
mkdir ddb_filters
cd ddb_filters
cdk init app --language python
```

La commande `cdk init` utilise le nom du dossier du projet pour nommer les différents éléments du projet, notamment les classes, les sous-dossiers et les fichiers. Tous les traits d’union figurant dans le nom du dossier sont convertis en traits de soulignement. Dans le cas contraire, le nom doit prendre la forme d’un identifiant Python. Par exemple, il ne doit pas commencer par un chiffre ni contenir d’espaces.

Pour travailler avec le nouveau projet, activez son environnement virtuel. Cela permet d’installer les dépendances du projet localement dans le dossier du projet, plutôt que globalement.

```
source .venv/bin/activate
python -m pip install -r requirements.txt
```

**Note**  
Il se peut que vous reconnaissiez qu'il s'agit de la Mac/Linux commande permettant d'activer un environnement virtuel. Les modèles Python incluent un fichier batch, `source.bat`, qui permet d’utiliser la même commande sous Windows. La commande Windows traditionnelle `.venv\Scripts\activate.bat` fonctionne également. Si vous avez initialisé votre AWS CDK projet à l'aide de AWS CDK Toolkit v1.70.0 ou d'une version antérieure, votre environnement virtuel se trouve dans le `.env` répertoire au lieu de. `.venv` 

**Infrastructure de base**

Ouvrez le fichier `./ddb_filters/ddb_filters_stack.py` dans l’éditeur de texte de votre choix. Ce fichier a été généré automatiquement lorsque vous avez créé le AWS CDK projet. 

Ensuite, ajoutez les fonctions `_create_ddb_table` et `_set_ddb_trigger_function`. Ces fonctions créeront une table DynamoDB avec la clé de partition PK et la clé de tri SK en mode provisionné et mode à la demande), avec Amazon DynamoDB Streams activé par défaut pour afficher les nouvelles et les anciennes images.

La fonction Lambda sera stockée dans le dossier `lambda` situé sous le fichier `app.py`. Ce fichier sera créé ultérieurement. Elle inclura une variable d’environnement `APP_TABLE_NAME`, qui sera le nom de la table Amazon DynamoDB créée par cette pile. Dans la même fonction, nous accorderons des autorisations de lecture de flux à la fonction Lambda. Enfin, elle s’abonnera aux DynamoDB Streams en tant que source d’événements pour la fonction Lambda. 

À la fin du fichier de la méthode `__init__`, vous appellerez les constructions respectives pour les initialiser dans la pile. Pour les projets plus importants qui nécessitent des composants et des services supplémentaires, il peut être préférable de définir ces constructions en dehors de la pile de base. 

```
import os
import json

import aws_cdk as cdk
from aws_cdk import (
    Stack,
    aws_lambda as _lambda,
    aws_dynamodb as dynamodb,
)
from constructs import Construct


class DdbFiltersStack(Stack):

    def _create_ddb_table(self):
        dynamodb_table = dynamodb.Table(
            self,
            "AppTable",
            partition_key=dynamodb.Attribute(
                name="PK", type=dynamodb.AttributeType.STRING
            ),
            sort_key=dynamodb.Attribute(
                name="SK", type=dynamodb.AttributeType.STRING),
            billing_mode=dynamodb.BillingMode.PAY_PER_REQUEST,
            stream=dynamodb.StreamViewType.NEW_AND_OLD_IMAGES,
            removal_policy=cdk.RemovalPolicy.DESTROY,
        )

        cdk.CfnOutput(self, "AppTableName", value=dynamodb_table.table_name)
        return dynamodb_table

    def _set_ddb_trigger_function(self, ddb_table):
        events_lambda = _lambda.Function(
            self,
            "LambdaHandler",
            runtime=_lambda.Runtime.PYTHON_3_9,
            code=_lambda.Code.from_asset("lambda"),
            handler="app.handler",
            environment={
                "APP_TABLE_NAME": ddb_table.table_name,
            },
        )

        ddb_table.grant_stream_read(events_lambda)

        event_subscription = _lambda.CfnEventSourceMapping(
            scope=self,
            id="companyInsertsOnlyEventSourceMapping",
            function_name=events_lambda.function_name,
            event_source_arn=ddb_table.table_stream_arn,
            maximum_batching_window_in_seconds=1,
            starting_position="LATEST",
            batch_size=1,
        )

    def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
        super().__init__(scope, construct_id, **kwargs)

        ddb_table = self._create_ddb_table()
        self._set_ddb_trigger_function(ddb_table)
```

Nous allons maintenant créer une fonction lambda très simple qui imprimera les journaux sur Amazon CloudWatch. Pour ce faire, créez un nouveau dossier appelé `lambda`.

```
mkdir lambda
touch app.py
```

À l’aide de votre éditeur de texte préféré, ajoutez le contenu suivant au fichier `app.py` :

```
import logging

LOGGER = logging.getLogger()
LOGGER.setLevel(logging.INFO)


def handler(event, context):
    LOGGER.info('Received Event: %s', event)
    for rec in event['Records']:
        LOGGER.info('Record: %s', rec)
```

Assurez-vous que vous vous trouvez dans le dossier `/ddb_filters/`, tapez la commande suivante pour créer l’exemple d’application :

```
cdk deploy
```

à un moment donné, il vous sera demandé de confirmer si vous souhaitez déployer la solution. Acceptez les modifications en saisissant `Y`.

```
├───┼──────────────────────────────┼────────────────────────────────────────────────────────────────────────────────┤
│ + │ ${LambdaHandler/ServiceRole} │ arn:${AWS::Partition}:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole │
└───┴──────────────────────────────┴────────────────────────────────────────────────────────────────────────────────┘

Do you wish to deploy these changes (y/n)? y

...

✨  Deployment time: 67.73s

Outputs:
DdbFiltersStack.AppTableName = DdbFiltersStack-AppTable815C50BC-1M1W7209V5YPP
Stack ARN:
arn:aws:cloudformation:us-east-2:111122223333:stack/DdbFiltersStack/66873140-40f3-11ed-8e93-0a74f296a8f6
```

Une fois les modifications déployées, ouvrez votre AWS console et ajoutez un élément à votre tableau. 

```
{
 "PK": "COMPANY#1000",
 "SK": "PRODUCT#CHOCOLATE#DARK",
 "company_id": "1000",
 "type": "",
 "state": "FL",
 "stores": 5,
 "price": 15,
 "quantity": 50,
 "fabric": "Florida Chocolates"
}
```

Les CloudWatch journaux devraient désormais contenir toutes les informations de cette entrée. 

**Exemples de filtrage**
+ **Uniquement les produits qui correspondent à un État donné**

Ouvrez le fichier `ddb_filters/ddb_filters/ddb_filters_stack.py` et modifiez-le pour inclure le filtre correspondant à tous les produits égaux à « FL ». Cela peut être révisé juste sous `event_subscription`, à la ligne 45.

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {"dynamodb": {"NewImage": {"state": {"S": ["FL"]}}}}
                )
            },
        ]
    },
)
```
+ **Uniquement les éléments qui commencent par certaines valeurs dans PK et SK**

Modifiez le script Python de façon à inclure la condition suivante :

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {
                        {
                            "dynamodb": {
                                "Keys": {
                                    "PK": {"S": [{"prefix": "COMPANY"}]},
                                    "SK": {"S": [{"prefix": "PRODUCT"}]},
                                }
                            }
                        }
                    }
                )
            },
        ]
    },
```
+ **Soit vous commencez avec des valeurs sur PK et SK, soit le produit provient d’un État donné.**

Modifiez le script Python de façon à inclure les conditions suivantes :

```
event_subscription.add_property_override(
    property_path="FilterCriteria",
    value={
        "Filters": [
            {
                "Pattern": json.dumps(
                    {
                        {
                            "dynamodb": {
                                "Keys": {
                                    "PK": {"S": [{"prefix": "COMPANY"}]},
                                    "SK": {"S": [{"prefix": "PRODUCT"}]},
                                }
                            }
                        }
                    }
                )
            },
            {
                "Pattern": json.dumps(
                    {"dynamodb": {"NewImage": {"state": {"S": ["FL"]}}}}
                )
            },
        ]
    },
)
```

Notez que la condition OR est ajoutée en ajoutant d’autres éléments au tableau de filtres.

**Nettoyage**

Localisez la pile de filtres dans la base de votre répertoire de travail et exécutez `cdk destroy`. Il vous sera demandé de confirmer la suppression de la ressource :

```
cdk destroy
Are you sure you want to delete: DdbFiltersStack (y/n)? y
```

# Bonnes pratiques relatives à l’utilisation de DynamoDB Streams avec Lambda
<a name="Streams.Lambda.BestPracticesWithDynamoDB"></a>

Une AWS Lambda fonction s'exécute dans un *conteneur*, c'est-à-dire un environnement d'exécution isolé des autres fonctions. Lorsque vous exécutez une fonction pour la première fois, AWS Lambda créez un nouveau conteneur et commencez à exécuter le code de la fonction.

Une fonction Lambda a un *gestionnaire* qui est exécuté une fois par appel. Le gestionnaire contient la logique métier principale de la fonction. Par exemple, la fonction Lambda illustrée dans [Étape 4 : créer et tester une fonction Lambda](Streams.Lambda.Tutorial.md#Streams.Lambda.Tutorial.LambdaFunction) comporte un gestionnaire qui peut traiter des enregistrements dans un flux DynamoDB. 

Vous pouvez également fournir un code d'initialisation qui ne s'exécute qu'une seule fois, après la création du conteneur, mais avant la première AWS Lambda exécution du gestionnaire. La fonction Lambda présentée dans [Étape 4 : créer et tester une fonction Lambda](Streams.Lambda.Tutorial.md#Streams.Lambda.Tutorial.LambdaFunction) contient un code d'initialisation qui importe le SDK JavaScript dans Node.js et crée un client pour Amazon SNS. Ces objets doivent être définis une seule fois, en dehors du gestionnaire.

Une fois la fonction exécutée, vous AWS Lambda pouvez choisir de réutiliser le conteneur pour les appels ultérieurs de la fonction. Dans ce cas, votre gestionnaire de fonction peut réutiliser les ressources que vous avez définies dans votre code d’initialisation. (Notez que vous ne pouvez pas contrôler la durée de conservation du conteneur par AWS Lambda , ni la réutilisation du conteneur.)

Pour AWS Lambda utiliser des déclencheurs DynamoDB, nous recommandons ce qui suit :
+ AWS les clients de service doivent être instanciés dans le code d'initialisation, et non dans le gestionnaire. Cela permet AWS Lambda de réutiliser les connexions existantes, pendant toute la durée de vie du conteneur.
+ En général, il n'est pas nécessaire de gérer explicitement les connexions ou d'implémenter un regroupement de connexions, car il AWS Lambda gère cela pour vous.

Un consommateur Lambda d’un flux DynamoDB ne garantit pas une livraison unique et peut entraîner des doublons occasionnels. Assurez-vous que le code de votre fonction Lambda est idempotent, afin d’éviter que des problèmes inattendus ne surviennent en raison d’un traitement dupliqué.

Pour plus d'informations, consultez la section [Bonnes pratiques relatives à l'utilisation AWS Lambda des fonctions](https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html) dans le *Guide du AWS Lambda développeur*.

# DynamoDB Streams et Apache Flink
<a name="StreamsApacheFlink.xml"></a>

Vous pouvez utiliser des enregistrements Amazon DynamoDB Streams avec Apache Flink. Grâce au [service géré Amazon pour Apache Flink](https://aws.amazon.com/managed-service-apache-flink/), vous pouvez transformer et analyser des données de streaming en temps réel à l’aide d’Apache Flink. Apache Flink est un cadre de traitement de flux open source dédié au traitement de données en temps réel. Le connecteur Amazon DynamoDB Streams pour Apache Flink simplifie la création et la gestion des charges de travail Apache Flink et vous permet d’intégrer des applications à d’autres Services AWS.

Amazon Managed Service pour Apache Flink vous aide à créer rapidement des applications de traitement de end-to-end flux pour l'analyse des journaux, l'analyse des flux de clics, l'Internet des objets (IoT), les technologies publicitaires, les jeux vidéo, etc. Les quatre cas d'utilisation les plus courants sont le streaming extract-transform-load (ETL), les applications pilotées par les événements, les analyses réactives en temps réel et les requêtes interactives des flux de données. Pour plus d’informations sur l’écriture dans Apache Flink à partir d’Amazon DynamoDB, consultez [Amazon DynamoDB Streams Connector](https://nightlies.apache.org/flink/flink-docs-master/docs/connectors/datastream/dynamodb/).