Le Blog Amazon Web Services

Choisir la bonne clé de partition pour Amazon DynamoDB

Cet article traite des considérations et des stratégies importantes pour choisir la bonne clé de partition pour votre schéma Amazon DynamoDB. Le choix de la bonne clé de partition est une étape importante dans la conception et la construction d’applications évolutives et fiables sur Amazon DynamoDB.

Qu’est-ce qu’une clé de partition ?

Amazon DynamoDB supporte deux types de clés primaires :

  • La clé de partition : Une simple clé primaire, composée d’un attribut connu sous le nom de clé de partition. Les attributs d’ Amazon DynamoDB sont similaires à bien des égards aux champs ou colonnes d’autres systèmes de bases de données,
  • Clé de partition et clé de tri : Appelée clé primaire composite, ce type de clé est composé de deux attributs. Le premier attribut est la clé de partition, et le second attribut est la clé de tri. Voici un exemple :

Amazon DynamoDB stocke les données sous forme de groupes d’attributs, appelés “items”. Les items sont similaires aux lignes ou aux enregistrements d’autres systèmes de base de données. DynamoDB stocke et récupère chaque élément en fonction de la valeur de la clé primaire, qui doit être unique. Les items sont répartis sur des unités de stockage de 10 Go, appelées partitions (stockage physique interne à Amazon DynamoDB). Chaque table possède une ou plusieurs partitions, comme le montre l’illustration ci-dessous. Pour plus d’informations, voir la section Partitions et distribution des données dans le Guide du développeur de DynamoDB.

Amazon DynamoDB utilise la valeur de la clé de partition comme entrée dans une fonction de hachage interne. La sortie de la fonction de hachage détermine la partition dans laquelle l’élément est stocké. L’emplacement de chaque élément est déterminé par la valeur de hachage de sa clé de partition.

Tous les éléments ayant la même clé de partition sont stockés ensemble, et pour les clés de partition composites, sont classés par la valeur de la clé de tri. Amazon DynamoDB divise les partitions par clé de tri si la taille de la collection dépasse 10 Go.

Clés de répartition et limitations des requêtes (Request Throttling)

Amazon DynamoDB distribue uniformément les unités de capacité de lecture (RCU) et d’écriture (WCU) fournies entre les partitions et supporte automatiquement vos modèles d’accès en utilisant le débit que vous avez fourni. Toutefois, si votre modèle d’accès dépasse 3000 RCU ou 1000 WCU pour une seule valeur de clé de partition, vos demandes peuvent être bloquées par une erreur ProvisionedThroughputExceededException.

La lecture ou l’écriture au-delà de la limite peut être causée par les problèmes suivant :

  • Distribution inégale des données due à un mauvais choix de clé de partition,
  • Accès fréquent à la même clé dans une partition (l’élément le plus populaire, également appelé “hot key”),
  • Un taux de demande supérieur au débit provisionné

Pour éviter la limitation de vos requêtes, concevez votre table Amazon DynamoDB avec la bonne clé de partition pour répondre à vos besoins d’accès et assurer une distribution uniforme des données.

Recommandations pour les clés de répartition

Utiliser des attributs de haute cardinalité. Ce sont des attributs qui ont des valeurs distinctes pour chaque élément, comme e-mailid, employee_no, customerid, sessionidorderid, etc.

Utiliser des attributs composites. Essayez de combiner plus d’un attribut pour former une clé unique, si cela correspond à votre modèle d’accès. Par exemple, considérez une table de commandes avec customerid+productid+countrycode comme clé de partition et order_date comme clé de tri.

Mettez en cache les éléments les plus populaires lorsqu’il y a un grand volume de trafic de lecture en utilisant Amazon DynamoDB Accelerator (DAX). Le cache agit comme un filtre passe-bas, empêchant les lectures d’éléments inhabituellement populaires d’inonder les partitions. Prenons par exemple un tableau qui contient des informations sur des produits. Certaines offres devraient être plus populaires que d’autres lors des grandes soldes comme le Cyber Monday. DAX est un cache en mémoire entièrement géré pour Amazon DynamoDB qui ne demande pas aux développeurs de gérer l’invalidation du cache eux-mêmes, la population de données ou la gestion des clusters. DAX est également compatible avec les appels d’API d’Amazon DynamoDB, ce qui permet aux développeurs de l’intégrer plus facilement dans les applications existantes.

Ajoutez des nombres aléatoires ou des chiffres d’une plage prédéterminée pour les cas d’utilisation intensive en écriture. Supposons que vous vous attendiez à un grand volume d’écritures pour une clé de partition (par exemple, plus de 1000 écritures de 1K par seconde). Dans ce cas, utilisez un préfixe ou un suffixe supplémentaire (un nombre fixe dans une plage prédéterminée, par exemple 1-10) et ajoutez-le à la clé de partition.

Prenons par exemple un tableau de transactions de factures. Une seule facture peut contenir des milliers de transactions par client. Comment renforcer l’unicité et la possibilité d’interroger et de mettre à jour les détails des factures pour les clients à fort volume ?

Voici la présentation recommandée du tableau pour ce scénario :

  • Clé de partition : Ajoutez un suffixe aléatoire (1-10 ou 1-100) au NumeroFacture, en fonction du nombre de transactions par NumeroFacture. Par exemple, supposons qu’un seul NumeroFacture contienne jusqu’à 50 000 articles de 1K et que vous prévoyez 5 000 écritures par seconde. Dans ce cas, vous pouvez utiliser la formule suivante pour estimer la plage de suffixes : (Nombre d’écritures par seconde * (arrondi(taille du poste en Ko),0)* 1KB) /1000). L’utilisation de cette formule nécessite un minimum de cinq partitions pour distribuer les écritures, et vous pouvez donc définir la plage comme étant de 1 à 5,
  • Clé de tri : ClientTransactionid
Clé de partition Clé de tri Attribut1
NumeroFacture+SuffixAleatoire ClientTransactionid Date_Facture
121212-1 Client1_trans1 2016-05-17 01.36.45
121212-1 Client1-trans2 2016-05-18 01.36.30
121212-2 Client2_trans1 2016-06-15 01.36.20
121212-2 Client2_trans2 2016-07-1 01.36.15
  • Cette combinaison nous donne une bonne répartition au travers des partitions. Vous pouvez utiliser la clé de tri pour filtrer un client spécifique (par exemple, où NumeroFacture=121212-1 et ClientTransactionid commence par Client1).
  • Comme nous avons un nombre aléatoire ajouté à notre clé de partition (1-5), nous devons interroger la table cinq fois pour un NumeroFacture donné. Notre clé de partition pourrait être 121212-[1-5], nous devons donc requêter la clé de partition 121212-1 et un ClientTransactionid qui commence par Client1. Nous devons répéter cette opération pour 121212-2, jusqu’à 121212-5, puis fusionner les résultats.

Note :

Une fois que la plage de suffixes est déterminée, il n’y a pas de moyen facile de répartir les données car les modifications de suffixes nécessitent également des modifications au niveau du code applicatif. Par conséquent, il convient de tenir compte de l’importance de chaque clé de partition et d’ajouter un suffixe aléatoire (avec tampon) suffisant pour tenir compte de la croissance future prévue.

Cette option induit une latence supplémentaire pour les lectures en raison d’un nombre X de demandes de lecture par requête.

Pour faciliter la lecture des éléments individuels, envisagez d’utiliser le sharding en utilisant des suffixes calculés, comme expliqué dans la section Utilisation du partitionnement d’écriture pour une répartition équitable des charges de travail dans le Guide du développeur de DynamoDB. Par exemple, supposons qu’un grand nombre de transactions de factures soient traitées mais que le schéma de lecture consiste à récupérer un petit nombre d’éléments pour une sourceid particulière par plage de dates. Dans ce cas, il est plus efficace de répartir les éléments sur une série de partitions en utilisant un attribut particulier, dans ce cas le sourceid. Vous pouvez hacher le sourceId pour annoter la clé de la partition plutôt que d’utiliser la stratégie des nombres aléatoires. De cette façon, vous savez quelle partition interroger et récupérer les résultats.

Comme pour les tableaux, nous vous recommandons d’envisager une approche de hachage pour les index secondaires globaux si vous prévoyez un scénario de hot key avec une clé de partition d’indexes secondaires globaux.

Par exemple, considérez le schéma suivant d’une table FactureTransaction. Il comporte une ligne d’en-tête pour chaque facture et contient des attributs tels que le montant total dû et le pays de la transaction, qui sont uniques pour chaque facture. En supposant que nous devons trouver la liste des factures émises pour chaque pays de transaction, nous pouvons créer un index secondaire global avec une clé de partition trans_pays. Cependant, cette approche conduit à un scénario d’écriture hot key, car le nombre de factures par pays est inégalement réparti.

Le tableau suivant montre la structuration recommandée avec une approche par partition :

Clé de Partition de la Table Clé de Tri de la Table Attribut1 Attribut2 GSI Clé de Partition Attribut3 GSI Clé de Tri Attribut4 Attribut5
NumeroFacture Attribut Clé de Tri Date_Facture Plage de préfixes aléatoires Trans_pays Montant_Du Devise
121212 head 2018-05-17 T1 Random (1-N) USA 10000 USD
121213 head 2018-04-1 T2 Random (1-N) USA 500000 USD
121214 head 2018-04-1 T2 Random (1-N) FRA 500000 EUR

Voici l’index secondaire global (GSI) pour le scénario précédent.

GSI Clé de Partition GSI Clé de Tri Trans_pays Attributs projetés
(Plage aléatoire) Trans_pays

NumeroFacture

 

Autres attributs de données
1-N USA 121212
1-N USA 121213
1-N FRA 121214

Dans l’exemple précédent, vous voudriez peut-être identifier la liste des numéros de facture associés aux États-Unis. Dans ce cas, vous pouvez lancer une requête vers l’index secondaire global avec partition_key = (1-N) et trans_pays = USA.

Antipatterns pour les clés de partitions

1. Utilisez des séquences ou des identifiants uniques générés par le moteur de la BD comme clé de partition, en particulier lorsque vous migrez les données depuis une bases de données relationnelles. Il est courant d’utiliser des séquences (schema.sequence.NEXTVAL) comme clé primaire pour renforcer l’unicité dans les tables Oracle. Les séquences ne sont généralement pas utilisées pour accéder aux données.

Voici un exemple de schéma pour une table de commande qui a été migrée d’Oracle vers Amazon DynamoDB. La clé de partition de la table principale (NumeroTransaction) est complétée par un UID. Un GSI est créé sur NumeroCommande et DateCommande afin de faciliter son requêtage.

 

Clé de Partition Attribut1 Attribut2
NumeroTransaction NumeroCommande DateCommande
1111111 Customer1-1 2016-05-17 01.36.45
1111112 Customer1-2 2016-05-18 01.36.30
1111113 Customer2-1 2016-05-18 01.36.30

Les problèmes potentiels liés à cette approche sont les suivants :

  • Vous ne pouvez pas utiliser le NumeroTransaction pour une quelconque requête, vous perdez donc la possibilité d’utiliser la clé de partition pour effectuer une recherche rapide des données,
  • Les GSI ne prennent en charge que la cohérence éventuelle, avec des coûts supplémentaires en lecture et en écriture.

Remarque : vous pouvez utiliser la fonction d’écriture conditionnelle au lieu de séquences pour renforcer l’unicité et empêcher l’écrasement d’un élément.

2. L’utilisation d’attributs à faible cardinalité tels que code_produit comme clé de partition et DateCommande comme clé de tri augmente considérablement la probabilité de problèmes de partition. Par exemple, si un produit est plus populaire, alors le nombre de lectures et d’écritures pour cette clé est élevé, ce qui entraîne des problèmes d’étranglement.

Sauf pour le scan, les opérations de l’API Amazon DynamoDB nécessitent un opérateur égal (EQ) sur la clé de partition pour les tables et les GSI. Par conséquent, la clé de partition doit être une valeur qui est facilement interrogé par votre application avec une simple recherche. Un exemple est l’utilisation de key=value, qui renvoie soit un élément unique, soit moins d’éléments. Il y a une limite de 1 Mo pour les éléments que vous pouvez récupérer par une seule opération de recherche, ce qui signifie que vous devez paginer en utilisant LastEvaluatedKey, ce qui n’est pas optimal.

En bref : ne faites pas de lift and shift des clés primaires de la base de données source sans analyser le modèle de données et les modèles d’accès de la table Amazon DynamoDB cible.

Conclusion

En ce qui concerne les stratégies de partitionnement d’Amazon DynamoDB, il n’existe pas de solution unique pour tous les cas d’utilisation. Vous devez évaluer différentes approches en fonction de votre modèle d’ingestion et d’accès aux données, puis choisir la clé la plus appropriée avec la plus faible probabilité de rencontrer des problèmes d’étranglement. En plus de la meilleure conception de clé de partition, la fonction de capacité adaptative de DynamoDB peut protéger votre application contre les problèmes de limitation de requêtes pour un modèle d’accès aux données inégal.

Pour plus d’informations sur la conception de schémas sur différents scénarios, voir Conception NoSQL pour DynamoDB dans le Guide du développeur DynamoDB.

Article adapté par Steve Houël, Solutions Architect, LinkedinArticle d’origine en anglais