COUNT, SUM und Aggregate in DynamoDB
DynamoDB hat genau ein eingebautes Aggregat: das Zählen passender Items mit
Select=COUNT. Es gibt kein natives SUM, AVG, MIN oder MAX. Und selbst die
Zählung, die du bekommen kannst, liest (und berechnet) jedes Item, das sie gezählt
hat. Dieser Guide behandelt, was tatsächlich unterstützt wird, die Annäherungen, nach
denen Leute greifen, und wie du echte COUNT/SUM/AVG über eine Tabelle laufen
lässt, wenn du sie brauchst.
Kann DynamoDB SUM, COUNT und Aggregatfunktionen?
Größtenteils nein. DynamoDBs einziges eingebautes Aggregat ist Select=COUNT, das Zählungen passender Items zurückgibt, aber trotzdem jedes Item liest (und berechnet). Es gibt kein natives SUM, AVG, MIN oder MAX, und PartiQL fügt ebenfalls keines hinzu. Für echte Aggregate mit GROUP BY falte sie in deiner App, pflege einen Zähler oder führe SQL in DynoTables Workbench aus.
Select=COUNTgibt die Anzahl passender Items zurück, aber DynamoDB liest trotzdem jedes Item, um sie zu erzeugen — du zahlst die vollenScan/Query-Lesekosten, keine günstigen „Zähl“-Kosten.- Es gibt kein natives
SUM,AVG,MINoderMAX. DynamoDBs Leseoperationen geben Items zurück; sie falten sie nicht in eine Zahl. PartiQL fügt ebenfalls keine Aggregate hinzu. DescribeTable.ItemCountist kostenlos, aber ungefähr und nur „ungefähr alle sechs Stunden“ aktualisiert — in Ordnung für eine Dashboard-Kachel, falsch für alles Exakte.- Für exakte
COUNT/SUM/AVG/MIN/MAX(mitGROUP BY) aggregiere in deiner App, pflege einen Zähler oder führe es in DynoTables SQL Workbench aus (unten).
Items zählen: Select=COUNT
Sowohl Query als auch Scan akzeptieren einen Select-Parameter. Setze ihn auf
COUNT, und die Antwort trägt die Zählungen statt der Items:
aws dynamodb scan \
--table-name Orders \
--select COUNT \
--filter-expression "#s = :open" \
--expression-attribute-names '{"#s":"status"}' \
--expression-attribute-values '{":open":{"S":"OPEN"}}'Die Antwort liefert dir zwei Zahlen (AWS: Counting the items in the results):
Count— „die Anzahl der Items, die nach Anwendung eines Filterausdrucks (falls vorhanden) übrig bleiben.“ScannedCount— „die Anzahl der ausgewerteten Items, bevor irgendeinScanFilterangewendet wird.“ Ohne Filter istScannedCountdasselbe wieCount.
Wenn du nur den hast und Duplikate darin zählen musst, ist die
Condition + der Filter, den du übergibst, genau das, was der
DynamoDB Expression Builder generiert — die
FilterExpression- und ExpressionAttributeNames/Values-Maps oben, plus die
KeyConditionExpression, wenn du innerhalb einer Partition per Query zählst — ohne
das JSON von Hand zu escapen.
Zwei weitere Stolperfallen, die Leute beim Zählen großer Tabellen beißen:
- Das 1-MB-Seitenlimit gilt weiterhin. „Wenn die Größe der
Scan-Ergebnismenge größer als 1 MB ist, stellenScannedCountundCountnur eine teilweise Zählung der Gesamt-Items dar“ (AWS-Scan-Dokumentation). Du musst paginieren, indem du denLastEvaluatedKeyjeder Antwort alsExclusiveStartKeyder nächsten Anfrage zurückspeist und eine laufende Summe führst, um die echte Zahl zu erhalten — dieselbe Schleife wie in DynamoDB-Pagination. - Ein enger
Queryschlägt einenScan.Select=COUNTauf einemQueryvermisst nur die Items in der anvisierten Partition, nicht die ganze Tabelle. Wenn du einen Partition Key festnageln kannst (Basistabelle oder ein GSI), zähle dort — es ist die Query-vs-Scan-Kostenlücke, angewendet aufs Zählen.
Select=COUNT vs ItemCount (und warum es veraltet ist)
DescribeTable gibt kostenlos einen ItemCount (und TableSizeBytes) zurück, ohne
Lesekosten. Der Haken steht in der
API-Referenz selbst:
„DynamoDB aktualisiert diesen Wert ungefähr alle sechs Stunden. Jüngste Änderungen
sind möglicherweise nicht in diesem Wert widergespiegelt.“ Er kann also weit hinter
dem tatsächlichen Zustand deiner Tabelle herhinken.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Exaktheit | Exakt (für die passende Menge) | Ungefähr |
| Aktualität | Live | Alle ~6 Stunden aktualisiert |
| Kosten | Liest + berechnet jedes gezählte Item | Kostenlos (Metadaten) |
| Kann filtern / Teilmenge zählen | Ja (Filterausdruck) | Nein — nur ganze Tabelle |
Verwende ItemCount für eine grobe „Wie groß ist diese Tabelle“-Bauchprüfung oder
eine Dashboard-Kachel. Verwende Select=COUNT, wenn du eine exakte, gefilterte oder
aktuelle Zahl brauchst — und akzeptiere die Lesekosten. Für alles wirklich Live und
Kostenlose führe selbst einen Zähler (siehe Aggregationsmuster unten).
Warum es kein natives SUM/AVG/MIN/MAX gibt
DynamoDBs Leseoperationen geben Items zurück. Es gibt keinen Query-Planer, der eine
Ergebnismenge in einen Skalar faltet, also gibt es nichts, womit man ein SUM oder
AVG berechnen könnte. Zählen ist die einzige Faltung, die die API anbietet, über
Select=COUNT.
PartiQL ändert das nicht. Die
PartiQL-SELECT-Grammatik
ist SELECT {{expression}} [, …] FROM {{table}}[.{{index}}] [WHERE …] [ORDER BY {{key}} …],
wobei der Ausdruck „eine Projektion ist, die aus dem *-Platzhalter oder einer
Projektionsliste eines oder mehrerer Attributnamen oder Dokumentpfade gebildet wird.“
Es gibt keine Aggregatfunktion und keine GROUP BY-Klausel in dieser Grammatik — und
ORDER BY nimmt einen {{key}}, dokumentiert als „einen Hash-Key oder einen
Sort-Key, um zurückgegebene Ergebnisse zu ordnen.“ Jedes PartiQL-SELECT kompiliert
immer noch zu einem GetItem, Query oder Scan, sodass
SELECT SUM(total) FROM "Orders" schlicht nicht ausdrückbar ist. (Mehr zur
PartiQL-Obergrenze in PartiQL vs SQL.)
Aggregationsmuster (Zähler, Streams, App-seitig)
Da DynamoDB nicht für dich aggregiert, schieben die etablierten Muster die Arbeit woanders hin:
- Gepflegtes Zähler-Item. Halte ein eigenes Item (z. B.
PK = "STATS#orders") undADDe bei jedem Schreibvorgang mit einemUpdateItemzu einem numerischen Attribut. Das Lesen des Aggregats ist dann ein einzigesGetItem— exakt und günstig, aber du besitzt die Inkrement-Logik, ihre Konsistenz und die Contention, wenn ein Zähler malträtiert wird. - , die einen Aggregator speisen. Aktiviere einen Stream und verdrahte ihn
mit einer Lambda, die laufende Summen (Zählungen, Summen) aktualisiert, während sich
Items ändern. Gemäß der
AWS-Streams-Dokumentation
kannst du den
StreamViewTypedes Streams so konfigurieren, dass jeder Datensatz dieNEW_AND_OLD_IMAGESträgt — „sowohl das neue als auch das alte Abbild des Items“ — genug, umSUM-artige Aggregate ohne erneuten Scan aktuell zu halten. Stream-Datensätze unterliegen einer 24-Stunden-Lebensdauer („die Stream-Datensätze innerhalb eines Shards werden automatisch nach 24 Stunden entfernt“), also muss der Consumer Schritt halten. - App-seitige Faltung. Blättere durch die passenden Items und akkumuliere das
SUM/AVG/MIN/MAXin deinem eigenen Code. Korrekt, aber es liest (und berechnet) jedes Item jedes Mal — dasselbe Kostenprofil wieSelect=COUNT, plus die Datenübertragung. - An Analytik auslagern. Für schwere oder Ad-hoc-analytische Aggregation exportiere die Tabelle nach S3 und frage sie mit Athena ab, oder streame sie in ein Warehouse. Gemäß der AWS-Export-nach-S3-Dokumentation „verbraucht der Export keine Read Capacity Units“ und lässt dich „Analytik und komplexe Abfragen mit AWS-Diensten wie Athena durchführen“ — der von AWS empfohlene Weg, sobald du der Aggregation pro Anfrage entwachsen bist.
Jedes tauscht Einfachheit gegen entweder Buchhaltung zur Schreibzeit (Zähler,
Streams) oder Kosten zur Lesezeit (App-seitige Scans). Kein Muster bringt DynamoDB
selbst dazu, ein SUM kostenlos zu berechnen. Die Gruppierungsvariante dieses
Kompromisses — das Aggregieren pro Key statt über die ganze Tabelle — ist ein
eigener Guide: DynamoDB GROUP BY.
COUNT/SUM/AVG in DynoTables SQL Workbench ausführen
Wenn du einfach die Antwort brauchst — „wie viele OFFENE Bestellungen, und was ist
ihre Gesamtsumme“ — ohne eine paginierende Scan-Schleife oder eine Lambda zu
schreiben, führt DynoTables SQL Workbench echte Aggregate aus. Sie materialisiert
deine Tabellen durch DynamoDBs tatsächliche Query/Scan-Laufzeit und führt dann ein
einziges SELECT darüber aus — Aggregate, GROUP BY, HAVING, DISTINCT:
SQL innerhalb von DynamoDBs Zugriffsmuster-Regeln.
-- 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 DESCDas ist COUNT, SUM, AVG, MIN, MAX, GROUP BY und ORDER BY auf einem
berechneten Aggregat — nichts davon kann DynamoDB oder PartiQL ausdrücken (PartiQLs
ORDER BY ist auf Key-Attribute beschränkt) — in einer Anweisung. Das ist derselbe
analytische Keil wie SQL für DynamoDB; für die vollständige
Gruppierungsgeschichte siehe DynamoDB GROUP BY.
Die Workbench ist ehrlich über das darunterliegende Zugriffsmodell, kein Möchtegern-Postgres:
- Die Zeilen kommen weiterhin durch DynamoDBs echtes Query/Scan. Ein
GROUP BYüber eine ganze Tabelle ist darunter immer noch einScan— die Workbench legt diese Kosten offen, statt sie zu verbergen, derselbe Query-vs-Scan-Kompromiss. - Aggregate laufen auf den materialisierten skalaren Attributen, nachdem die Zeilen gelandet sind.
FAQ
Kann ich Items in DynamoDB ohne Scan zählen?
Nicht ganz. Für eine exakte, aktuelle Zählung musst du die Items lesen —
Select=COUNT vermisst weiterhin jedes gezählte Item. Die einzigen scan-losen
Optionen sind der ungefähre DescribeTable.ItemCount (alle ~6 Stunden aktualisiert)
oder ein Zähler-Item, das du bei jedem Schreibvorgang selbst pflegst.
Wie zähle ich Items über einen GSI?
Führe Query (oder Scan) gegen den Index mit Select=COUNT aus. Über eine enge
GSI-Partition zu zählen ist weit günstiger als die Basistabelle zu scannen, weil du
nur die Items in dieser Index-Partition liest — modelliere den Index um die Zählung,
die du brauchst.
Ist DescribeTable.ItemCount genau?
Er ist ungefähr. Die
API-Referenz
besagt, dass DynamoDB ItemCount und TableSizeBytes „ungefähr alle sechs Stunden“
aktualisiert und „jüngste Änderungen möglicherweise nicht in diesem Wert
widergespiegelt sind.“ Verwende ihn nicht, wo eine exakte oder Live-Zahl zählt.
Kann DynamoDB SUM oder AVG?
Nicht nativ, und nicht in PartiQL — die
PartiQL-SELECT-Grammatik
hat keine Aggregatfunktionen. Aggregiere in deiner Anwendung, pflege einen Zähler
(optional über DynamoDB Streams) oder führe das SUM/AVG in DynoTables SQL
Workbench aus.
Was ist der Unterschied zwischen Count und ScannedCount?
ScannedCount ist, wie viele Items DynamoDB vor deinem Filter ausgewertet hat;
Count ist, wie viele danach übrig bleiben. Sie sind gleich, wenn es keinen
Filterausdruck gibt. Eine große Lücke zwischen ihnen bedeutet eine ineffiziente
Zählung.
Musst du deine DynamoDB-Daten summieren, mitteln oder gruppieren, ohne eine Scan-Schleife zu schreiben? Lade DynoTable herunter und führe es in einem Workbench-Tab aus. Vergleichst du erst die Clients? Sieh, wo es gegen eine reine DynamoDB-GUI landet.