Einsteiger8 Min. Lesezeit

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=COUNT gibt die Anzahl passender Items zurück, aber DynamoDB liest trotzdem jedes Item, um sie zu erzeugen — du zahlst die vollen Scan/Query-Lesekosten, nicht günstige „Zähl"-Kosten.
  • Es gibt kein natives SUM, AVG, MIN oder MAX. DynamoDBs Leseoperationen geben Items zurück; sie falten sie nicht zu einer Zahl zusammen. PartiQL fügt ebenfalls keine Aggregate hinzu.
  • DescribeTable.ItemCount ist 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 (mit GROUP 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 ein ScanFilter angewendet wird." Ohne Filter ist ScannedCount dasselbe wie Count.

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, stellen ScannedCount und Count nur eine Teilzählung der Gesamtanzahl der Items dar" (AWS Scan-Docs). Du musst mit LastEvaluatedKeyExclusiveStartKey paginieren und eine laufende Summe führen, um die echte Zahl zu bekommen — dieselbe Schleife, die in DynamoDB-Pagination behandelt wird.
  • Ein enger Query schlägt einen Scan. Select=COUNT auf einem Query misst 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=COUNTDescribeTable.ItemCount
GenauigkeitExakt (für die passende Menge)Näherungsweise
AktualitätLiveAlle ~6 Stunden aktualisiert
KostenLiest + berechnet jedes gezählte ItemKostenlos (Metadaten)
Kann filtern / Teilmenge zählenJa (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") und ADDe bei jedem Schreibvorgang mit einem UpdateItem zu einem numerischen Attribut. Das Lesen des Aggregats ist dann ein einzelnes GetItem — 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 StreamViewType des Streams so konfigurieren, dass jeder Datensatz die NEW_AND_OLD_IMAGES trägt — „sowohl das neue als auch das alte Abbild des Items" — genug, um SUM-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/MAX in deinem eigenen Code. Korrekt, aber es liest (und berechnet) jedes Mal jedes Item — dasselbe Kostenprofil wie Select=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 DESC

Das 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 ein Scan — 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.

Aktualisiert