Wie man in DynamoDB COUNT, SUM und aggregiert
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
Anzahl, die du bekommen kannst, liest (und berechnet) jedes Item, das sie gezählt
hat. Dieser Leitfaden behandelt, was tatsächlich unterstützt wird, zu welchen
Näherungen die Leute greifen und wie man echtes COUNT/SUM/AVG über eine
Tabelle ausführt, wenn man es braucht.
Kann DynamoDB SUM, COUNT und Aggregatfunktionen?
Größtenteils nein. DynamoDBs einziges eingebautes Aggregat ist Select=COUNT, das die
Anzahl passender Items zurückgibt, dabei aber trotzdem jedes Item liest (und in Rechnung
stellt). 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, nicht günstige „Zähl"-Kosten.- Es gibt kein natives
SUM,AVG,MINoderMAX. DynamoDBs Leseoperationen geben Items zurück; sie falten sie nicht zu einer Zahl zusammen. PartiQL fügt ebenfalls keine Aggregate hinzu. DescribeTable.ItemCountist kostenlos, aber näherungsweise und nur „ungefähr alle sechs Stunden" aktualisiert — okay für eine Dashboard-Kachel, falsch für alles Exakte.- Für exaktes
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 Anzahlen 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 gibt dir zwei Zahlen (AWS: Counting the items in the results):
Count— „die Anzahl der Items, die übrig bleiben, nachdem ein Filterausdruck (falls vorhanden) angewendet wurde."ScannedCount— „die Anzahl der Items, die ausgewertet wurden, bevor einScanFilterangewendet wird." Ohne Filter istScannedCountdasselbe wieCount.
Wenn du nur den Partition-Key hast und Duplikate darin zählen musst, sind die
Bedingung + der Filter, die du übergibst, genau das, was der
DynamoDB Expression Builder generiert — die
KeyConditionExpression, FilterExpression und ExpressionAttributeNames/Values-
Maps oben — ohne das JSON von Hand zu escapen.
Zwei weitere Stolperfallen, die Leuten beim Zählen großer Tabellen zusetzen:
- Das 1-MB-Seitenlimit gilt weiterhin. „Wenn die Größe der
Scan-Ergebnismenge größer als 1 MB ist, stellenScannedCountundCountnur eine Teilzählung der Gesamtanzahl der Items dar" (AWS Scan-Docs). Du musst mitLastEvaluatedKey→ExclusiveStartKeypaginieren und eine laufende Summe führen, um die echte Zahl zu bekommen — dieselbe Schleife, die in DynamoDB-Pagination behandelt wird. - Ein enger
Queryschlägt einenScan.Select=COUNTauf einemQuerymisst nur die Items in der anvisierten Partition ab, nicht die ganze Tabelle. Wenn du einen Partition-Key festnageln kannst (Basistabelle oder ein GSI), zähle dort — das ist das Query-vs-Scan-Kostengefälle, angewandt aufs Zählen.
Select=COUNT vs. ItemCount (und warum es veraltet ist)
DescribeTable gibt einen ItemCount (und TableSizeBytes) kostenlos zurück, ohne
Lesekosten. Der Haken steht in der
API-Referenz selbst:
„DynamoDB aktualisiert diesen Wert ungefähr alle sechs Stunden. Aktuelle Änderungen
spiegeln sich womöglich nicht in diesem Wert wider." Er kann also deutlich hinter dem
tatsächlichen Zustand deiner Tabelle zurückbleiben.
Select=COUNT | DescribeTable.ItemCount | |
|---|---|---|
| Genauigkeit | Exakt (für die passende Menge) | Näherungsweise |
| 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 |
Nutze ItemCount für einen groben „Wie groß ist diese Tabelle"-Bauchcheck oder eine
Dashboard-Kachel. Nutze Select=COUNT, wenn du eine exakte, gefilterte oder aktuelle
Zahl brauchst — und akzeptiere die Lesekosten. Für alles wirklich Live-und-Kostenlose
pflege 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 Abfrageplaner, der eine
Ergebnismenge zu einem Skalar zusammenfaltet, also gibt es nichts, womit man ein
SUM oder AVG berechnen könnte. Zählen ist die einzige Faltung, die die API
bietet, via 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, gebildet aus dem *-Wildcard oder einer
Projektionsliste aus einem oder mehreren Attributnamen oder Dokumentpfaden." Es gibt
keine Aggregatfunktion und keine GROUP BY-Klausel in dieser Grammatik — und
ORDER BY nimmt einen {{key}}, dokumentiert als „ein Hash-Key oder ein Sort-Key,
um zurückgegebene Ergebnisse zu ordnen." Jedes PartiQL-SELECT kompiliert weiterhin
zu einem GetItem, Query oder Scan, also ist SELECT SUM(total) FROM "Orders"
schlicht nicht ausdrückbar. (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 dediziertes Item (z. B.
PK = "STATS#orders") undADDe bei jedem Schreibvorgang mit einemUpdateItemzu einem numerischen Attribut. Das Lesen des Aggregats ist dann ein einzelnesGetItem— exakt und günstig, aber dir gehört die Inkrement-Logik, ihre Konsistenz und der Wettstreit, wenn ein Zähler stark beansprucht wird. - DynamoDB Streams → Aggregator. Aktiviere einen Stream und verdrahte ihn mit
einer Lambda, die laufende Summen (Counts, Sums) aktualisiert, während sich Items
ändern. Laut den
AWS Streams-Docs
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 aktuell zu halten, ohne neu zu scannen. Stream-Datensätze unterliegen einer Lebensdauer von 24 Stunden („die Stream-Datensätze innerhalb eines Shards werden nach 24 Stunden automatisch entfernt"), der Consumer muss also mithalten. - 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 Mal jedes Item — dasselbe Kostenprofil wieSelect=COUNT, plus die Datenübertragung. - Auslagern in Analytics. 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. Laut den AWS Export-nach-S3-Docs verbraucht der Export „keine Lesekapazitätseinheiten" und lässt dich „Analysen und komplexe Abfragen mit AWS-Services wie Athena durchführen" — der 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 — pro Schlüssel aggregieren statt über die ganze Tabelle — ist ihr
eigener Leitfaden: DynamoDB GROUP BY.
COUNT/SUM/AVG in DynoTables SQL Workbench ausführen
Wenn du einfach die Antwort brauchst — „wie viele OPEN-Bestellungen, und was ist deren Gesamtsumme" — ohne eine paginierende Scan-Schleife oder eine Lambda zu schreiben, führt DynoTables SQL Workbench echte Aggregate aus. Sie materialisiert deine Tabellen über DynamoDBs tatsächliche Query/Scan-Laufzeit und führt dann darüber dein vollständiges SQL aus: 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 sind COUNT, SUM, AVG, MIN, MAX, GROUP BY und ORDER BY — von denen
DynamoDB oder PartiQL keines ausdrücken kann — in einer einzigen Anweisung. Das ist
derselbe analytische Hebel wie SQL für DynamoDB; für die
vollständige Gruppierungsgeschichte siehe
DynamoDB GROUP BY.
Die Workbench ist ehrlich über das Zugriffsmodell darunter, kein Möchtegern-Postgres:
- Die Zeilen kommen weiterhin über DynamoDBs echten Query/Scan. Ein
GROUP BYüber eine ganze Tabelle ist darunter weiterhin 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 zählen, ohne zu scannen?
Nicht ganz. Für eine exakte, aktuelle Anzahl musst du die Items lesen —
Select=COUNT misst weiterhin jedes gezählte Item ab. Die einzigen Optionen ohne
Scan sind der näherungsweise 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. Das Zählen über
eine enge GSI-Partition ist weit günstiger als das Scannen der Basistabelle, weil du
nur die Items in dieser Index-Partition liest — modelliere den Index rund um die
Anzahl, die du brauchst.
Ist DescribeTable.ItemCount genau?
Es ist näherungsweise. Die
API-Referenz
gibt an, dass DynamoDB ItemCount und TableSizeBytes „ungefähr alle sechs Stunden"
aktualisiert und „aktuelle Änderungen sich womöglich nicht in diesem Wert
widerspiegeln." Nutze es 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 via 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 einen ineffizienten
Count.
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 Clients? Sieh, wo es gegen eine schlichte DynamoDB-GUI landet.