Comment faire COUNT, SUM et agréger dans DynamoDB
DynamoDB possède exactement un agrégat intégré : compter les items correspondants
avec Select=COUNT. Il n'y a pas de SUM, AVG, MIN ni MAX natif. Et même le
compte que tu peux obtenir lit (et facture) chaque item qu'il a compté. Ce guide
couvre ce qui est réellement pris en charge, les approximations vers lesquelles les
gens se tournent, et comment exécuter un vrai COUNT/SUM/AVG sur une table
quand tu en as besoin.
DynamoDB peut-il faire SUM, COUNT et des fonctions d'agrégat ?
Le plus souvent, non. Le seul agrégat intégré de DynamoDB est Select=COUNT, qui
renvoie le nombre d'items correspondants mais lit (et facture) quand même chaque
item. Il n'y a pas de SUM, AVG, MIN ni MAX natif, et PartiQL n'en ajoute
aucun non plus. Pour de vrais agrégats avec GROUP BY, agrège-les dans ton
application, maintiens un compteur, ou exécute du SQL dans le
Workbench de DynoTable.
Select=COUNTrenvoie le nombre d'items correspondants, mais DynamoDB lit quand même chaque item pour le produire — tu paies le coût de lecture complet duScan/Query, pas un coût de « comptage » bon marché.- Il n'y a pas de
SUM,AVG,MINniMAXnatif. Les opérations de lecture de DynamoDB renvoient des items ; elles ne les replient pas en un nombre. PartiQL n'ajoute pas non plus d'agrégats. DescribeTable.ItemCountest gratuit mais approximatif et mis à jour uniquement « approximativement toutes les six heures » — parfait pour une tuile de tableau de bord, faux pour quoi que ce soit d'exact.- Pour un
COUNT/SUM/AVG/MIN/MAXexact (avecGROUP BY), agrège dans ton application, maintiens un compteur, ou exécute-le dans le Workbench SQL de DynoTable (ci-dessous).
Compter des items : Select=COUNT
Query et Scan acceptent tous deux un paramètre Select. Mets-le à COUNT et la
réponse porte les comptes au lieu des items :
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'La réponse te donne deux nombres (AWS : Counting the items in the results) :
Count— « le nombre d'items qui restent, après l'application d'une expression de filtre (le cas échéant). »ScannedCount— « le nombre d'items évalués, avant l'application de toutScanFilter. » Sans filtre,ScannedCountest identique àCount.
Si tu n'as que la clé de partition et que tu dois compter les doublons qu'elle
contient, la condition + le filtre que tu transmets sont exactement ce que génère
le DynamoDB Expression Builder — les maps
KeyConditionExpression, FilterExpression et
ExpressionAttributeNames/Values ci-dessus — sans échapper le JSON à la main.
Deux autres pièges qui mordent les gens qui comptent de grandes tables :
- La limite de page de 1 Mo s'applique toujours. « Si la taille de l'ensemble
de résultats du
Scandépasse 1 Mo,ScannedCountetCountne représentent qu'un comptage partiel du total des items » (doc AWS Scan). Tu dois paginer avecLastEvaluatedKey→ExclusiveStartKeyet tenir un total courant pour obtenir le vrai nombre — la même boucle couverte dans la pagination DynamoDB. - Un
Queryétroit bat unScan.Select=COUNTsur unQueryne mesure que les items de la partition ciblée, pas la table entière. Si tu peux fixer une clé de partition (table de base ou un GSI), compte là — c'est l'écart de coût Query vs Scan appliqué au comptage.
Select=COUNT vs ItemCount (et pourquoi il est périmé)
DescribeTable renvoie un ItemCount (et TableSizeBytes) gratuitement, sans coût
de lecture. Le hic est dans la
référence de l'API elle-même :
« DynamoDB met à jour cette valeur environ toutes les six heures. Les changements
récents peuvent ne pas être reflétés dans cette valeur. » Il peut donc être très en retard sur l'état réel
de ta table.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Exactitude | Exact (pour l'ensemble correspondant) | Approximatif |
| Fraîcheur | En direct | Mis à jour ~toutes les 6 heures |
| Coût | Lit + facture chaque item compté | Gratuit (métadonnées) |
| Peut filtrer / compter un sous-ensemble | Oui (expression de filtre) | Non — table entière uniquement |
Utilise ItemCount pour une vérification approximative du genre « quelle est la
taille de cette table » ou une tuile de tableau de bord. Utilise Select=COUNT
quand tu as besoin d'un nombre exact, filtré ou actuel — et accepte le coût de
lecture. Pour quelque chose de vraiment en direct et gratuit, suis un compteur
toi-même (voir Schémas d'agrégation ci-dessous).
Pourquoi il n'y a pas de SUM/AVG/MIN/MAX natif
Les opérations de lecture de DynamoDB renvoient des items. Il n'y a pas de
planificateur de requêtes pour replier un ensemble de résultats en un scalaire, donc
il n'y a rien pour calculer un SUM ou un AVG. Compter est le seul repliement
que l'API propose, via Select=COUNT.
PartiQL ne change rien à cela. La
grammaire SELECT de PartiQL
est SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …],
où l'expression est « une projection formée à partir du joker * ou une liste de
projection d'un ou plusieurs noms d'attribut ou chemins de document. » Il n'y a aucune fonction
d'agrégat et aucune clause GROUP BY dans cette grammaire — et ORDER BY prend une
{{key}}, documentée comme « une clé de hachage ou une clé de tri à utiliser pour
ordonner les résultats renvoyés. » Chaque SELECT PartiQL se compile encore en un GetItem, Query ou
Scan, donc SELECT SUM(total) FROM "Orders" n'est tout simplement pas
exprimable. (Plus de détails sur le plafond de PartiQL dans
PartiQL vs SQL.)
Schémas d'agrégation (compteurs, streams, côté application)
Comme DynamoDB n'agrège pas à ta place, les schémas établis poussent le travail ailleurs :
- Item compteur maintenu. Garde un item dédié (par ex.
PK = "STATS#orders") et utiliseADDsur un attribut numérique à chaque écriture avec unUpdateItem. Lire l'agrégat n'est alors qu'un seulGetItem— exact et bon marché, mais tu es responsable de la logique d'incrémentation, de sa cohérence et de la contention si un compteur est martelé. - DynamoDB Streams → agrégateur. Active un stream et relie-le à une Lambda qui
met à jour les totaux courants (comptes, sommes) au fil des changements d'items.
Selon la
doc AWS Streams,
tu peux configurer le
StreamViewTypedu stream pour que chaque enregistrement porteNEW_AND_OLD_IMAGES— « à la fois la nouvelle et l'ancienne image de l'item » — suffisant pour garder à jour des agrégats de typeSUMsans re-scanner. Les enregistrements de stream sont soumis à une durée de vie de 24 heures (« les enregistrements de stream d'un shard sont supprimés automatiquement après 24 heures »), donc le consommateur doit suivre le rythme. - Repliement côté application. Parcours les items correspondants et accumule le
SUM/AVG/MIN/MAXdans ton propre code. Correct, mais il lit (et facture) chaque item à chaque fois — le même profil de coût queSelect=COUNT, plus le transfert de données. - Déporter vers l'analytique. Pour une agrégation analytique lourde ou ad hoc, exporte la table vers S3 et interroge-la avec Athena, ou diffuse-la dans un entrepôt. Selon la doc AWS export-to-S3, l'export « ne consomme pas d'unités de capacité de lecture » et te permet d'« effectuer des analyses et des requêtes complexes en utilisant des services AWS tels qu'Athena » — le chemin recommandé par AWS une fois que tu as dépassé l'agrégation par requête.
Chacun échange la simplicité contre soit de la comptabilité au moment de l'écriture
(compteurs, streams), soit un coût au moment de la lecture (scans côté
application). Aucun schéma ne fait calculer un SUM à DynamoDB lui-même
gratuitement. La version groupée de ce compromis — agréger par clé plutôt que sur
la table entière — fait l'objet de son propre guide :
DynamoDB GROUP BY.
Exécuter COUNT/SUM/AVG dans le Workbench SQL de DynoTable
Quand tu as juste besoin de la réponse — « combien de commandes OPEN, et quel est leur total » — sans écrire une boucle de scan paginée ni une Lambda, le Workbench SQL de DynoTable exécute de vrais agrégats. Il matérialise tes tables à travers le véritable moteur Query/Scan de DynamoDB, puis exécute ton SQL complet par-dessus : du SQL dans les règles d'accès de DynamoDB.
-- Runs in the DynoTable Workbench (NOT in PartiQL):
SELECT status,
COUNT(*) AS orders,
SUM(total) AS revenue,
AVG(total) AS avg_order,
MIN(total) AS smallest,
MAX(total) AS largest
FROM orders
GROUP BY status
ORDER BY revenue DESCVoilà COUNT, SUM, AVG, MIN, MAX, GROUP BY et ORDER BY — aucun de ces
éléments que DynamoDB ou PartiQL ne peut exprimer — en une seule instruction.
C'est le même levier analytique que SQL pour DynamoDB ;
pour l'histoire complète du groupement, vois
DynamoDB GROUP BY.
Le Workbench est honnête à propos du modèle d'accès sous-jacent, ce n'est pas un faux-Postgres :
- Les lignes passent toujours par le véritable Query/Scan de DynamoDB. Un
GROUP BYsur une table entière reste unScanen dessous — le Workbench fait apparaître ce coût plutôt que de le cacher, le même compromis Query vs Scan. - Les agrégats s'exécutent sur les attributs scalaires matérialisés une fois que les lignes ont atterri.
FAQ
Puis-je compter des items dans DynamoDB sans scanner ?
Pas exactement. Pour un compte exact et actuel, tu dois lire les items —
Select=COUNT mesure quand même chaque item compté. Les seules options sans scan
sont l'approximatif DescribeTable.ItemCount (mis à jour ~toutes les 6 heures) ou
un item compteur que tu maintiens toi-même à chaque écriture.
Comment compter des items par un GSI ?
Exécute Query (ou Scan) contre l'index avec Select=COUNT. Compter via une
partition de GSI étroite est bien moins coûteux que scanner la table de base, parce
que tu ne lis que les items de cette partition d'index — modélise l'index autour du
comptage dont tu as besoin.
DescribeTable.ItemCount est-il exact ?
Il est approximatif. La
référence de l'API
indique que DynamoDB met à jour ItemCount et TableSizeBytes « environ toutes
les six heures », et que « les changements récents peuvent ne pas être reflétés dans cette valeur. »
Ne l'utilise pas là où un nombre exact ou en direct compte.
DynamoDB peut-il faire SUM ou AVG ?
Pas nativement, et pas en PartiQL — la
grammaire SELECT de PartiQL
n'a aucune fonction d'agrégat. Agrège dans ton application, maintiens un compteur
(éventuellement via DynamoDB Streams), ou exécute le SUM/AVG dans le Workbench
SQL de DynoTable.
Quelle est la différence entre Count et ScannedCount ?
ScannedCount est le nombre d'items que DynamoDB a évalués avant ton filtre ;
Count est le nombre qui reste après. Ils sont égaux quand il n'y a pas
d'expression de filtre. Un grand écart entre eux signifie un comptage inefficace.
Besoin de sommer, moyenner ou grouper tes données DynamoDB sans écrire une boucle de scan ? Télécharge DynoTable et exécute-le dans un onglet Workbench. Tu compares d'abord les clients ? Vois comment il se positionne face à une GUI DynamoDB classique.