Clé primaire composite DynamoDB : partition key et sort key expliquées
Une clé primaire composite, c'est deux attributs : une clé de partition et une clé de tri. La clé de partition décide où vit un item ; la clé de tri ordonne les items à l'intérieur de cette partition.
En venant de SQL, pense-y moins comme une colonne id unique et plus comme un
GROUP BY partition, ORDER BY sort cuit dans la table elle-même.
Qu'est-ce qu'une clé primaire composite DynamoDB ?
Une clé primaire composite DynamoDB combine deux attributs : une clé de partition et une clé de tri. La clé de partition détermine dans quelle partition physique vit un item ; la clé de tri ordonne les items à l'intérieur de cette partition. Ensemble, elles forment l'identité unique de l'item et permettent à un seul Query de renvoyer une plage triée plutôt qu'un seul item.
- Deux parties, deux rôles. La clé de partition route l'item vers une partition physique ; la clé de tri ordonne chaque item qui partage cette clé de partition.
- L'unicité est la paire. Deux items peuvent partager une valeur de clé de partition tant que leurs clés de tri diffèrent — c'est ainsi qu'une partition contient plusieurs lignes.
- La clé de tri est tout l'intérêt. C'est ce qui permet à un
Queryde renvoyer une plage (>=,between,begins_with) plutôt qu'un seul item, sansScan. - Les clés doivent être des scalaires. Les clés de partition et de tri ne peuvent être que string, number ou binary — pas de maps, pas de lists (Docs AWS).
Clé simple vs clé composite
Une clé primaire simple n'est qu'une clé de partition. Elle identifie un item de
façon unique, et tu le relis avec GetItem. C'est tout — pas de lectures de plage, pas
de « donne-moi les N plus récents ».
Une clé composite ajoute la clé de tri, et cet unique ajout est ce qui fait que DynamoDB ressemble à une base de données plutôt qu'à une hash map.
| Clé simple | Clé composite | |
|---|---|---|
| Attributs | Clé de partition seule | Clé de partition + clé de tri |
| Unicité | Valeur de clé de partition | La paire de valeurs |
| Plusieurs items par partition | Non | Oui |
Query d'une plage | Non (GetItem seul) | Oui (begins_with, between, >) |
| Ajustement naturel | Lookup par id | Séries temporelles, un-à-plusieurs, historique |
Modéliser une table de relevés de capteurs
Disons que tu collectes des échantillons de température depuis une flotte de capteurs de terrain. Le mode d'accès est « obtenir les relevés d'un appareil, les plus récents d'abord, dans une fenêtre temporelle ». C'est une clé composite manuel.
Utilise l'id de l'appareil comme clé de partition et le timestamp du relevé comme clé de tri :
| deviceId | readingTs | tempC | humidity |
|---|---|---|---|
| DEV#a1b2 | 2026-06-23T08:00:00Z | 21.4 | 48 |
| DEV#a1b2 | 2026-06-23T08:05:00Z | 21.7 | 47 |
| DEV#a1b2 | 2026-06-23T08:10:00Z | 22.1 | 46 |
| DEV#c9d8 | 2026-06-23T08:00:00Z | 19.8 | 55 |
Les trois relevés DEV#a1b2 atterrissent dans la même partition, physiquement
stockés ensemble et triés par readingTs.
AWS appelle la clé de partition l'attribut de hash et la clé de tri l'attribut de plage — la clé de tri est une plage que tu peux scanner à l'intérieur (Docs AWS).
Voici comment les items s'effondrent en une seule collection d'items sous chaque clé de partition :
Un seul Query contre la clé de partition lit chaque relevé de cet appareil, déjà dans
l'ordre des timestamps — pas de tri côté client, pas de second aller-retour.
Ce que coûte cette fenêtre
Dix relevés de 2 Ko chacun dans la partition totalisent 20 Ko facturés. DynamoDB arrondit les lectures par bloc de 4 Ko, donc un Query à cohérence à terme sur cette fenêtre coûte 3 unités de requête de lecture (20 Ko → cinq blocs de 4 Ko × 0,5 RCU chacun). Une lecture fortement cohérente sur la même fenêtre coûte 5 unités (une RCU par bloc). Récupère les mêmes dix lignes avec dix GetItem séparés et la règle du minimum-un-bloc s'applique par item → 5 unités à cohérence à terme, 10 fortement cohérentes — avant de compter les allers-retours supplémentaires.
| Motif de lecture | Items | Données touchées | Unités lecture CT |
|---|---|---|---|
Un Query, readingTs entre début et fin | 10 | 20 Ko | 3 |
10 × GetItem sur la clé composite complète | 10 | 20 Ko | 5 |
Query partition seule, filtre humidité dans l'app | 10 | 20 Ko | 3 |
Scan table, filtre deviceId + fenêtre temporelle | tous | table entière | taille de table |
Passe ReturnConsumedCapacity: TOTAL pendant le prototypage ; le
calculateur de tarifs transforme ce compte d'unités en ligne mensuelle une fois que tu connais les requêtes par seconde.
Requête la plage, ne la scanne pas
Parce que readingTs est une chaîne ISO-8601, elle trie lexicographiquement de la même
façon qu'elle trie chronologiquement. Donc une lecture par fenêtre temporelle est une
plage de condition de clé, pas un filtre :
Query
deviceId = "DEV#a1b2"
readingTs BETWEEN "2026-06-23T08:00:00Z" AND "2026-06-23T08:10:00Z"
C'est un KeyConditionExpression — il restreint la lecture avant que DynamoDB ne
renvoie les données, donc tu paies seulement pour les items de la fenêtre. Une
FilterExpression s'exécute après la lecture et te facture pour tout ce qu'elle a
scanné ; c'est le footgun du Scan en miniature.
L'expression elle-même, avec les placeholders et les valeurs typées, est fastidieuse à
écrire à la main. Construis-la visuellement avec le
DynamoDB Expression Builder et copie le
KeyConditionExpression exact dans ton appel SDK.
Conçois la clé de tri exprès
La clé de tri n'est pas une métadonnée gratuite — c'est le seul levier pour les lectures de plage, alors façonne-la à tes requêtes.
- Utilise un timestamp triable. Les chaînes ISO-8601 ou les nombres epoch trient correctement ; les dates localisées brutes non.
- Préfixe-la pour le un-à-plusieurs. Une clé de tri comme
READING#2026-06-23T08:00:00Zte permet de mêler des types d'entités sous une seule partition et de les trancher avecbegins_with. C'est la couture vers le single-table design. - Mets la dimension à forte cardinalité dans la clé de partition. L'id de capteur
a des milliers de valeurs, donc il répartit les écritures équitablement. Une clé de
partition à faible cardinalité (disons
region) crée une .
Une clé de partition avec seulement cinquante valeurs distinctes sur un flux de 10 000 écritures par seconde concentre ~200 WCU par partition logique avant que DynamoDB ne split — correct à l'échelle prototype, douloureux à l'échelle production. Préfère des identifiants qui grandissent avec ta flotte (id appareil, id tenant, id session) plutôt que des regroupements grossiers, sauf si tu colocalises délibérément un dataset borné.
Quand une clé composite te mord
C'est un engagement, pas une commodité. Le piège : tu choisis une clé de partition, tu livres, puis tu découvres un mode d'accès qui a besoin d'un autre regroupement — « tous les relevés au-dessus de 30 °C dans toute la flotte ».
La table de base ne peut pas répondre à ça ; la clé de partition est fixée. Tes options sont un global secondary index avec une clé différente, ou une restructuration.
Énumère tes lectures avant de committer le schéma de clé. Changer une clé primaire
signifie une migration de table, pas un ALTER TABLE.
Dans DynoTable, ouvre le navigateur de table et inspecte une table à clé composite côte à côte avec ses GSI — l'ordre de tri sur la clé de tri est visible ligne par ligne, ce qui rend les formats de timestamp décalés d'un évidents avant qu'ils n'atteignent la production.
Étapes suivantes
Les clés composites sont la fondation sous les collections d'items, les relations un-à-plusieurs et la plupart des conceptions d'index utiles — lis ensuite single-table design et GSI vs LSI pour voir où elles mènent.
Esquisse ton KeyConditionExpression dans le
DynamoDB Expression Builder, émets le Query
paginé complet dans le query builder, puis
essaie DynoTable pour parcourir tes vraies partitions et observer l'ordre
de tri s'aligner sur tes propres tables.