Come fare COUNT, SUM e aggregare in DynamoDB
DynamoDB ha esattamente un aggregato integrato: contare gli item corrispondenti con
Select=COUNT. Non c'è alcun SUM, AVG, MIN o MAX nativo. E persino il
conteggio che puoi ottenere legge (e fattura) ogni item che ha contato. Questa
guida copre cosa è effettivamente supportato, le approssimazioni a cui le persone
ricorrono, e come eseguire veri COUNT/SUM/AVG su una tabella quando ti
servono.
DynamoDB può fare SUM, COUNT e funzioni di aggregazione?
Per lo più no. L'unico aggregato integrato di DynamoDB è Select=COUNT, che restituisce il numero di item corrispondenti ma legge comunque (e fattura) ogni item. Non esiste alcun SUM, AVG, MIN o MAX nativo, e nemmeno PartiQL ne aggiunge. Per veri aggregati con GROUP BY, aggregali nella tua app, mantieni un contatore, o esegui SQL nel Workbench di DynoTable.
Select=COUNTrestituisce il numero di item corrispondenti, ma DynamoDB legge comunque ogni item per produrlo — paghi l'intero costo di letturaScan/Query, non un costo "count" economico.- Non c'è alcun
SUM,AVG,MINoMAXnativo. Le operazioni di lettura di DynamoDB restituiscono item; non li riducono in un numero. Nemmeno PartiQL aggiunge gli aggregati. DescribeTable.ItemCountè gratuito ma approssimato e aggiornato solo "approssimativamente ogni sei ore" — va bene per un riquadro di dashboard, sbagliato per qualunque cosa esatta.- Per
COUNT/SUM/AVG/MIN/MAXesatti (conGROUP BY), aggrega nella tua app, mantieni un contatore, o eseguilo nel Workbench SQL di DynoTable (sotto).
Contare gli item: Select=COUNT
Sia Query che Scan accettano un parametro Select. Impostalo a COUNT e la
risposta porta i conteggi invece degli item:
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'La risposta ti dà due numeri (AWS: Counting the items in the results):
Count— "il numero di item che rimangono, dopo che è stata applicata un'espressione di filtro (se presente)."ScannedCount— "il numero di item valutati, prima che venga applicato qualunqueScanFilter." Senza filtro,ScannedCountè uguale aCount.
Se hai solo la partition key e devi contare i duplicati al suo interno, la
condizione + il filtro che passi sono esattamente ciò che il
DynamoDB Expression Builder genera — le mappe
KeyConditionExpression, FilterExpression ed ExpressionAttributeNames/Values
qui sopra — senza dover fare l'escape manuale del JSON.
Altri due tranelli che colpiscono chi conta tabelle grandi:
- Il limite di pagina da 1 MB si applica comunque. "Se la dimensione del set di
risultati dello
Scanè maggiore di 1 MB,ScannedCounteCountrappresentano solo un conteggio parziale del totale degli item" (documentazione Scan di AWS). Devi paginare conLastEvaluatedKey→ExclusiveStartKeye tenere un totale progressivo per ottenere il numero reale — lo stesso ciclo trattato in paginazione DynamoDB. - Una
Queryristretta batte unoScan.Select=COUNTsu unaQuerycontabilizza solo gli item nella partizione mirata, non l'intera tabella. Se puoi fissare una partition key (tabella base o un GSI), conta lì — è il divario di costo Query-vs-Scan applicato al conteggio.
Select=COUNT vs ItemCount (e perché è obsoleto)
DescribeTable restituisce un ItemCount (e TableSizeBytes) gratuitamente, senza
costo di lettura. Il problema è nello
stesso riferimento API:
"DynamoDB aggiorna questo valore approssimativamente ogni sei ore. Le modifiche
recenti potrebbero non essere riflesse in questo valore." Quindi può rimanere molto
indietro rispetto allo stato effettivo della tua tabella.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Esattezza | Esatto (per l'insieme corrispondente) | Approssimato |
| Freschezza | Live | Aggiornato ~ogni 6 ore |
| Costo | Legge + fattura ogni item contato | Gratuito (metadati) |
| Può filtrare / contare un sottoinsieme | Sì (espressione di filtro) | No — solo intera tabella |
Usa ItemCount per una stima approssimativa di "quanto è grande questa tabella" o
un riquadro di dashboard. Usa Select=COUNT quando ti serve un numero esatto,
filtrato o attuale — e accetta il costo di lettura. Per qualcosa di davvero live e
gratuito, traccia tu stesso un contatore (vedi Pattern di aggregazione sotto).
Perché non c'è alcun SUM/AVG/MIN/MAX nativo
Le operazioni di lettura di DynamoDB restituiscono item. Non c'è alcun query planner
per ridurre un insieme di risultati in uno scalare, quindi non c'è nulla con cui
calcolare un SUM o un AVG. Il conteggio è l'unica riduzione che l'API offre,
tramite Select=COUNT.
PartiQL non cambia questo. La
grammatica SELECT di PartiQL
è SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …],
dove l'espressione è "una proiezione formata dal carattere jolly * o un elenco di
proiezione di uno o più nomi di attributo o percorsi di documento." Non c'è alcuna
funzione di aggregazione e nessuna clausola GROUP BY in quella grammatica — e
ORDER BY accetta una {{key}}, documentata come "una hash key o una sort key da
usare per ordinare i risultati restituiti." Ogni SELECT PartiQL si compila comunque
in un GetItem,
Query o Scan, quindi SELECT SUM(total) FROM "Orders" semplicemente non è
esprimibile. (Altro sul limite di PartiQL in PartiQL vs SQL.)
Pattern di aggregazione (contatori, stream, lato app)
Dato che DynamoDB non aggrega per te, i pattern consolidati spingono il lavoro altrove:
- Item contatore mantenuto. Tieni un item dedicato (ad es.
PK = "STATS#orders") e faiADDa un attributo numerico a ogni scrittura con unUpdateItem. Leggere l'aggregato è poi un singoloGetItem— esatto ed economico, ma sei tu a possedere la logica di incremento, la sua consistenza e la contesa se un contatore viene martellato. - DynamoDB Streams → aggregatore. Abilita uno stream e collegalo a una Lambda che
aggiorna i totali progressivi (conteggi, somme) mentre gli item cambiano. Secondo
la
documentazione Streams di AWS,
puoi configurare lo
StreamViewTypedello stream in modo che ogni record porti ilNEW_AND_OLD_IMAGES— "sia la nuova sia la vecchia immagine dell'item" — abbastanza da mantenere aggiornati gli aggregati in stileSUMsenza ri-scansionare. I record di stream sono soggetti a una durata di 24 ore ("i record di stream all'interno di uno shard vengono rimossi automaticamente dopo 24 ore"), quindi il consumatore deve stare al passo. - Riduzione lato app. Pagina attraverso gli item corrispondenti e accumula il
SUM/AVG/MIN/MAXnel tuo codice. Corretto, ma legge (e fattura) ogni item ogni volta — lo stesso profilo di costo diSelect=COUNT, più il trasferimento dei dati. - Scaricare sull'analisi. Per aggregazioni analitiche pesanti o ad hoc, esporta la tabella su S3 e interrogala con Athena, oppure trasmettila in un warehouse. Secondo la documentazione export-to-S3 di AWS, l'esportazione "non consuma read capacity unit" e ti permette di "eseguire analisi e query complesse usando servizi AWS come Athena" — il percorso raccomandato da AWS una volta superata l'aggregazione per richiesta.
Ognuno scambia la semplicità con la contabilità a tempo di scrittura (contatori,
stream) o con il costo a tempo di lettura (scan lato app). Nessun pattern fa sì che
DynamoDB stesso calcoli un SUM gratuitamente. La versione con raggruppamento di
questo compromesso — aggregare per chiave anziché sull'intera tabella — ha la sua
guida dedicata: DynamoDB GROUP BY.
Eseguire COUNT/SUM/AVG nel Workbench SQL di DynoTable
Quando ti serve solo la risposta — "quanti ordini OPEN, e qual è il loro totale" — senza scrivere un ciclo di scan con paginazione o una Lambda, il Workbench SQL di DynoTable esegue veri aggregati. Materializza le tue tabelle attraverso l'effettivo runtime Query/Scan di DynamoDB, poi esegue il tuo SQL completo sopra: SQL all'interno delle regole di access pattern di 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 DESCQuelli sono COUNT, SUM, AVG, MIN, MAX, GROUP BY e ORDER BY — nessuno
dei quali DynamoDB o PartiQL può esprimere — in una sola istruzione. Questo è lo
stesso cuneo analitico di SQL per DynamoDB; per la storia
completa sul raggruppamento vedi DynamoDB GROUP BY.
Il Workbench è onesto sul modello di accesso sottostante, non finge di essere Postgres:
- Le righe arrivano comunque attraverso il vero Query/Scan di DynamoDB. Un
GROUP BYsu un'intera tabella è comunque unoScansotto — il Workbench fa emergere quel costo invece di nasconderlo, lo stesso compromesso Query-vs-Scan. - Gli aggregati vengono eseguiti sugli attributi scalari materializzati dopo che le righe sono arrivate.
FAQ
Posso contare gli item in DynamoDB senza scansionare?
Non proprio. Per un conteggio esatto e attuale devi leggere gli item —
Select=COUNT contabilizza comunque ogni item contato. Le uniche opzioni senza scan
sono l'approssimato DescribeTable.ItemCount (aggiornato ~ogni 6 ore) o un item
contatore che mantieni tu stesso a ogni scrittura.
Come conto gli item per un GSI?
Esegui una Query (o uno Scan) sull'indice con Select=COUNT. Contare tramite
una partizione GSI ristretta è molto più economico che scansionare la tabella base,
perché leggi solo gli item in quella partizione dell'indice — modella l'indice
attorno al conteggio che ti serve.
DescribeTable.ItemCount è accurato?
È approssimato. Il
riferimento API
afferma che DynamoDB aggiorna ItemCount e TableSizeBytes "approssimativamente ogni
sei ore", e "le modifiche recenti potrebbero non essere riflesse in questo valore."
Non usarlo dove conta un numero esatto o live.
DynamoDB può fare SUM o AVG?
Non nativamente, e non in PartiQL — la
grammatica SELECT di PartiQL
non ha funzioni di aggregazione. Aggrega nella tua applicazione, mantieni un
contatore (opzionalmente tramite DynamoDB Streams), o esegui il SUM/AVG nel
Workbench SQL di DynoTable.
Qual è la differenza tra Count e ScannedCount?
ScannedCount è quanti item DynamoDB ha valutato prima del tuo filtro; Count è
quanti ne rimangono dopo. Sono uguali quando non c'è alcuna espressione di filtro. Un
grande divario tra loro significa un conteggio inefficiente.
Hai bisogno di sommare, fare la media o raggruppare i tuoi dati DynamoDB senza scrivere un ciclo di scan? Scarica DynoTable ed eseguilo in una scheda Workbench. Stai confrontando i client prima? Vedi come si colloca rispetto a una GUI DynamoDB semplice.