Fortgeschritten7 Min. Lesezeit

DynamoDB-Index-Projektionen

Wenn du einen Secondary Index anlegst, kopiert DynamoDB das ganze Item nicht automatisch hinein. Du wählst was kopiert wird — die Projektion des Index. Zu wenig, und deine Queries zahlen einen zweiten Read für den Rest; alles, und du zahlst extra Storage und Write-Kosten bei jedem Update. Es ist ein Tradeoff, den du einmal bei der Index-Erstellung setzt und mit dem du lebst.

(Verwechsle das nicht mit einer Projection Expression, die die Attribute trimmt, die ein einzelner Read zurückgibt. Diese Seite geht um das, was ein Index physisch speichert — siehe Projection Expressions für das andere.)

Was ist eine DynamoDB-Index-Projektion?

Eine Projektion ist die Menge von Attributen, die DynamoDB aus der Base Table in einen Secondary Index kopiert. Du wählst einen von drei Typen: KEYS_ONLY (nur die Keys), INCLUDE (Keys plus eine benannte Attributliste) oder ALL (das ganze Item). Mehr Projektion heißt weniger Base-Table-Fetches, aber höhere Storage- und Write-Kosten.

  • Eine Projektion ist die Menge von Attributen, die in einen Secondary Index kopiert werden.
  • KEYS_ONLY — nur die Table- und Index-Keys. Am kleinsten, am günstigsten.
  • INCLUDE — die Keys plus eine benannte Liste zusätzlicher Attribute, die du wählst.
  • ALL — jedes Attribut des Items. Am größten; Queries brauchen nie die Base Table.
  • Ein Attribut, das nicht projeziert ist, ist von einem GSI schlicht nicht verfügbar — deine App muss eigene Base-Table-Reads ausführen. (Nur ein LSI holt nicht-projezierte Attribute für dich nach, zu extra Read-Kosten.)
  • Mehr Projektion = mehr Storage + mehr Write-Kosten, weil jeder Base-Table-Write in den Index propagiert.

Das Problem: der Index, der dich zweimal lesen lässt

Angenommen, du betreibst einen Support-Desk mit einem GSI, der offene Tickets nach Priority listet. Du projezierst KEYS_ONLY, um ihn schlank zu halten. Die Query kommt schnell zurück — aber sie liefert nur Ticket-IDs, und dein Queue- Screen braucht Subject, Assignee und Age jedes Tickets.

Also macht dein Code jetzt eine zweite Runde Reads gegen die Base Table, um jedes Ergebnis zu hydratisieren. Die „eine Query“, die du designed hast, ist eigentlich eine Query plus N Gets, und Latenz und Kosten, die du sparen wolltest, sind zurück. Die Projektion war zu dünn für das Access Pattern.

Was jeder Projektionstyp kopiert

Basis-Item: Schlüssel + subject +assignee + age + bodyKEYS_ONLY: nur SchlüsselINCLUDE: Schlüssel + subject,assignee, ageALL: jedes Attribut
  • KEYS_ONLY speichert nur den Base-Table-Key und den Index-Key. Nutze ihn, wenn die Query nur wissen muss, welche Items matchen, und du Details woanders holst — oder gar nicht.
  • INCLUDE speichert die Keys plus eine feste Liste benannter Attribute. Der Sweet Spot: projeziere genau die Felder, die deine Query rendern muss, und nichts mehr.
  • ALL kopiert das gesamte Item. Queries bedienen sich vollständig aus dem Index, auf Kosten der Duplizierung von Storage und Write-Throughput des ganzen Items.

Für die Support-Desk-Queue ist INCLUDE mit subject, assignee und age der richtige Call — die Queue rendert allein aus dem Index, ohne zweiten Fetch und ohne den großen body des Tickets in den Index zu duplizieren.

Die Kosten, die du handelst

Jedes Attribut, das du projezierst, wird ein zweites Mal gespeichert und im Index neu geschrieben, wann immer das Base-Item sich ändert. Eine großzügige ALL-Projektion auf einer häufig aktualisierten Tabelle multipliziert also Storage und Write Capacity. Projeziere, was die Query liest, nicht „alles, nur für den Fall“.

Eine Nuance: bei einem sparse Index hält die Projektion trotzdem nur die Items, die den Index-Key tragen — also bleibt INCLUDE/ALL auf einem Sparse Index klein, weil der Index selbst klein ist. Wäge Storage- und Write-Multiplikator für deine Projektion mit dem DynamoDB Pricing Calculator, und baue die Index-Queries selbst mit dem DynamoDB Expression Builder.

Eine Projektion in DynoTable sehen

DynoTable listet jeden Secondary Index einer Tabelle und lässt dich direkt durch einen querien. Fahre dasselbe Access Pattern gegen die Base Table und gegen einen GSI und vergleiche die Ergebnisse — die Attribute, die im Index-Ergebnis fehlen, sind genau die, die er nicht projeziert. So siehst du den Effekt einer Projektion, ohne die Table-Definition neu zu lesen.

Wahl des DynamoDB-Index, durch den eine Query läuft, im Index-Picker von DynoTable.
Wahl des DynamoDB-Index, durch den eine Query läuft, im Index-Picker von DynoTable.

Fallstricke + nächste Schritte

  • Ein nicht-projeziertes Attribut auf einem GSI bedeutet einen Base-Table-Fetch — designe die Projektion um das, was die Query rendert.
  • ALL ist selten gratis — es dupliziert Storage und Write-Kosten; default zu INCLUDE, außer der Index braucht wirklich jedes Feld.
  • Projektionen sind weitgehend fix. Du kannst die Projektion eines GSI später nicht frei editieren, ohne den Index neu anzulegen — wähle vorne bewusst.
  • Verwandt: GSI vs LSI und Sparse Indexes prägen, wie viel eine Projektion tatsächlich speichert.

Willst du sehen, was jeder deiner Indexes wirklich zurückgibt, bevor du sie umdesignst? Lade DynoTable herunter und query deine Tabellen direkt.

Hydrationskosten: KEYS_ONLY + N Gets

Zurück zum Support-Desk-Queue-Beispiel: 50 offene Tickets mit Subject, Assignee und Age angezeigt.

ProjektionIndex-QueryFollow-up-ReadsEC-RCU-Skizze (2-KB-Base-Items)
KEYS_ONLY50 Keys zurück50 × GetItem~50 Index-RCU + ~50 Base-RCU
INCLUDE subject, assignee, age50 selbstständige Rowskeine~50 Index-RCU only
ALL50 volle Kopienkeine~50 Index-RCU; höherer Storage + Write-Amp

Exakte Zahlen hängen von den Größen der projezierten Attribute ab — paste ein Sample-Ticket in den Item-Size Calculator und multipliziere mit der Queue-Tiefe. INCLUDE, das nur UI-Felder listet, schlägt oft ALL, wenn das body-Attribut groß ist und in der Listenansicht selten gezeigt wird.

LSI-Projektion und Fetch-Verhalten

Nur LSIs können optional nicht-projezierte Attribute während einer Query von der Base Table nachholen (mit zusätzlichen Read-Kosten). GSIs tun das nie — fehlende Attribute erfordern, dass deine App GetItem auf der Base Table aufruft. Dieser Unterschied schiebt viele GSI-Designs zu etwas breiteren INCLUDE- Projektionen von Anfang an.

Projektionen später ändern

GSI-Projektionen sind bei Creation fix. KEYS_ONLY zu INCLUDE zu erweitern erfordert einen neuen Index, Backfill, Traffic-Cutover und Löschen des alten Index — plane Felder vor dem Launch. LSIs teilen dieselbe Einschränkung.

Wenn du ein neues Access Pattern bewertest, query den Kandidaten-Index in DynoTable und liste, welche Attribute erscheinen — Lücken mapen 1:1 auf fehlende Projektionseinträge.

Mit Sparse Indexes koppeln

Ein sparse GSI, der nur Tickets mit status = open indexiert, speichert Projektionen nur für offene Rows. INCLUDE auf diesem Index bleibt günstig, auch wenn die Base Table Millionen geschlossener Tickets hält — der Index hat sie nie kopiert.

Kombiniere mit Sparse-Index-Mustern, wenn die gefilterte Teilmenge relativ zur Tabelle klein ist.

Baue zuerst das Access Pattern

Nutze den Query Builder, um die GSI-Query zu prototypen — Key Condition, Projection Expression und Filter — bevor du CloudFormation änderst. Wechsle Projektionstypen in der Design-Diskussion, indem du fragst, welche Spalten die UI rendert; alles andere bleibt auf der Base Table.

Aktualisiert