Einsteiger7 Min. Lesezeit

DynamoDB Composite Primary Key: Partition Key + Sort Key erklärt

Ein zusammengesetzter Primärschlüssel besteht aus zwei Attributen: einem Partitionsschlüssel und einem Sortierschlüssel. Der Partitionsschlüssel bestimmt, wo ein Item liegt; der Sortierschlüssel ordnet die Items innerhalb dieser Partition.

Wenn du von SQL kommst, denk weniger an eine eindeutige id-Spalte und mehr an ein GROUP BY partition, ORDER BY sort, das fest in der Tabelle verdrahtet ist.

Was ist ein zusammengesetzter Primärschlüssel in DynamoDB?

Ein zusammengesetzter Primärschlüssel in DynamoDB kombiniert zwei Attribute: einen Partitionsschlüssel und einen Sortierschlüssel. Der Partitionsschlüssel bestimmt, in welcher physischen Partition ein Item liegt; der Sortierschlüssel ordnet die Items innerhalb dieser Partition. Zusammen bilden sie die eindeutige Identität des Items und lassen ein einzelnes Query einen sortierten Bereich statt eines einzelnen Items zurückgeben.

  • Zwei Teile, zwei Aufgaben. Der Partitionsschlüssel leitet das Item auf eine physische Partition; der Sortierschlüssel ordnet jedes Item, das diesen Partitionsschlüssel teilt.
  • Eindeutig ist das Paar. Zwei Items dürfen denselben Partitionsschlüsselwert haben, solange sich ihre Sortierschlüssel unterscheiden — so hält eine Partition viele Zeilen.
  • Der Sortierschlüssel ist der springende Punkt. Er ist es, der ein Query einen Bereich (>=, between, begins_with) zurückgeben lässt statt eines Items, ganz ohne Scan.
  • Schlüssel müssen Skalare sein. Partitions- und Sortierschlüssel können nur String, Zahl oder Binary sein — keine Maps, keine Listen (AWS docs).

Einfacher Schlüssel vs. zusammengesetzter Schlüssel

Ein einfacher Primärschlüssel ist nur ein Partitionsschlüssel. Er identifiziert ein Item eindeutig, und du liest es mit GetItem zurück. Mehr nicht — keine Bereichs-Reads, kein „gib mir die neuesten N".

Ein zusammengesetzter Schlüssel ergänzt den Sortierschlüssel, und genau dieser eine Zusatz macht, dass sich DynamoDB wie eine Datenbank anfühlt und nicht wie eine Hash-Map.

Einfacher SchlüsselZusammengesetzter Schlüssel
AttributeNur PartitionsschlüsselPartitionsschlüssel + Sortierschlüssel
EindeutigkeitPartitionsschlüsselwertDas Wertepaar
Mehrere Items pro PartitionNeinJa
Bereich per QueryNein (nur GetItem)Ja (begins_with, between, >)
Passt natürlich zuSuche per IDZeitreihen, Eins-zu-viele, Historie

Eine Tabelle mit Sensormesswerten modellieren

Sagen wir, du sammelst Temperaturmesswerte von einer Flotte von Feldsensoren. Das Zugriffsmuster lautet „hol mir die Messwerte eines Geräts, neueste zuerst, innerhalb eines Zeitfensters". Das ist ein zusammengesetzter Schlüssel wie aus dem Lehrbuch.

Nimm die Geräte-ID als Partitionsschlüssel und den Zeitstempel des Messwerts als Sortierschlüssel:

deviceIdreadingTstempChumidity
DEV#a1b22026-06-23T08:00:00Z21.448
DEV#a1b22026-06-23T08:05:00Z21.747
DEV#a1b22026-06-23T08:10:00Z22.146
DEV#c9d82026-06-23T08:00:00Z19.855

Alle drei DEV#a1b2-Messwerte landen in derselben Partition, physisch zusammen abgelegt und nach readingTs sortiert.

AWS nennt den Partitionsschlüssel das Hash-Attribut und den Sortierschlüssel das Range-Attribut — der Sortierschlüssel ist ein Bereich, innerhalb dessen du lesen kannst (AWS docs).

Unter jedem Partitionsschlüssel fallen die Items zu einer zusammen:

Partition: DEV#a1b2readingTs 08:00readingTs 08:05readingTs 08:10Query deviceId = DEV#a1b2

Ein einziges Query auf den Partitionsschlüssel liest jeden Messwert dieses Geräts, bereits in Zeitstempel-Reihenfolge — kein Sortieren im Client, kein zweiter Roundtrip.

Was dieses Fenster kostet

Zehn Messwerte à 2 KB in der Partition ergeben 20 KB abgerechnetes Volumen. DynamoDB rundet Reads pro 4-KB-Block auf, ein eventually consistent Query auf dieses Fenster kostet also 3 Read-Request-Einheiten (20 KB → fünf 4-KB-Blöcke × je 0,5 RCU). Ein stark konsistenter Read auf dasselbe Fenster kostet 5 Einheiten (eine RCU pro Block). Holst du dieselben zehn Zeilen mit zehn einzelnen GetItem-Aufrufen, greift die Mindestens-ein-Block-Regel pro Item → 5 Einheiten eventually consistent, 10 stark konsistent — die zusätzlichen Roundtrips noch gar nicht gerechnet.

LesemusterItemsBerührte DatenEC-Leseeinheiten
Ein Query, readingTs zwischen Start und Ende1020 KB3
10 × GetItem auf den vollen zusammengesetzten Key1020 KB5
Nur Query auf die Partition, Feuchte in der App filtern1020 KB3
Scan der Tabelle, Filter deviceId + Zeitfensteralleganze Tabelletabellengroß

Gib beim Prototyping ReturnConsumedCapacity: TOTAL mit; der Preisrechner macht aus dieser Einheitenzahl einen monatlichen Posten, sobald du deine Requests pro Sekunde kennst.

Frag den Bereich ab, scanne ihn nicht

Weil readingTs ein ISO-8601-String ist, sortiert er lexikografisch genauso wie chronologisch. Ein Zeitfenster-Read ist damit ein Bereich in der Key Condition und kein Filter:

Query
deviceId  = "DEV#a1b2"
readingTs BETWEEN "2026-06-23T08:00:00Z" AND "2026-06-23T08:10:00Z"

Das ist eine KeyConditionExpression — sie schränkt den Read ein, bevor DynamoDB Daten zurückgibt, du zahlst also nur für die Items im Fenster. Eine FilterExpression läuft nach dem Read und stellt dir alles in Rechnung, was sie durchlaufen hat; das ist der Scan-Fallstrick im Kleinen.

Die Expression selbst ist mit Platzhaltern und typisierten Werten von Hand fummelig zu schreiben. Bau sie dir visuell im DynamoDB Expression Builder und kopier die exakte KeyConditionExpression in deinen SDK-Aufruf.

Entwirf den Sortierschlüssel mit Absicht

Der Sortierschlüssel ist der einzige Hebel für Bereichs-Reads, also forme ihn entlang deiner Abfragen.

  • Nimm einen sortierbaren Zeitstempel. ISO-8601-Strings oder Epoch-Zahlen sortieren korrekt; rohe lokalisierte Datumsangaben nicht.
  • Gib ihm ein Präfix für Eins-zu-viele-. Ein Sortierschlüssel wie READING#2026-06-23T08:00:00Z lässt dich Entitätstypen unter einer Partition mischen und mit begins_with wieder auseinanderschneiden. Das ist die Naht hin zum Single-Table Design.
  • Steck die Dimension mit hoher Kardinalität in den Partitionsschlüssel. Eine Sensor-ID hat Tausende Werte und verteilt Writes damit gleichmäßig. Ein Partitionsschlüssel mit niedriger Kardinalität (etwa region) erzeugt eine .

Ein Partitionsschlüssel mit nur fünfzig unterschiedlichen Werten bündelt bei 10.000 Writes pro Sekunde ~200 WCU je logischer Partition, bevor DynamoDB splittet — im Prototyp in Ordnung, in Produktion schmerzhaft. Bevorzuge Bezeichner, die mit deiner Flotte mitwachsen (Geräte-ID, Mandanten-ID, Session-ID), gegenüber groben Gruppierungen — es sei denn, du platzierst absichtlich einen begrenzten Datensatz zusammen.

Wann dich ein zusammengesetzter Schlüssel beißt

Zusammengesetzte Schlüssel sind eine Festlegung. Du wählst einen Partitionsschlüssel, gehst live und entdeckst dann ein Zugriffsmuster, das eine andere Gruppierung braucht — „alle Messwerte über 30 °C über die ganze Flotte".

Die Basistabelle kann das nicht beantworten; der Partitionsschlüssel steht fest. Deine Optionen sind ein Global Secondary Index mit anderem Schlüssel oder ein Umbau.

Zähl deine Reads auf, bevor du dich auf das Schlüsselschema festlegst. Einen Primärschlüssel zu ändern heißt Tabellenmigration, nicht ALTER TABLE.

Öffne in DynoTable den Tabellenbrowser und sieh dir eine Tabelle mit zusammengesetztem Schlüssel neben ihren GSIs an — die Sortierreihenfolge auf dem Sortierschlüssel ist Zeile für Zeile sichtbar, was um eins verschobene Zeitstempelformate auffliegen lässt, bevor sie in Produktion gehen.

Nächste Schritte

Zusammengesetzte Schlüssel sind das Fundament unter Item Collections, Eins-zu-viele-Beziehungen und den meisten brauchbaren Index-Designs — lies als Nächstes Single-Table Design und GSI vs. LSI, um zu sehen, wohin sie führen.

Skizzier deine KeyConditionExpression im DynamoDB Expression Builder, lass dir das vollständige paginierte Query im Query Builder ausgeben und probier DynoTable aus, um deine echten Partitionen zu durchsuchen und die Sortierreihenfolge gegen deine eigenen Tabellen zu prüfen.

Aktualisiert