Global vs. Local Secondary Indexes in DynamoDB: Ein umfassender Vergleich für optimale Datenbank-Performance

Global Secondary Indexes und Local Secondary Indexes in Amazon DynamoDB bieten unterschiedliche Wege, um auf Daten effizient zuzugreifen. Dieser Beitrag beleuchtet, wie diese beiden Abfrage-Mechanismen eingesetzt werden können – abhängig von Skalierungsanforderungen, Konsistenzbedürfnissen und Anwendungslogik – für optimale Performance mit DynamoDB Indexes.

Zentrale Punkte

  • GSIs ermöglichen flexible Abfragen unabhängig vom Primärschlüssel
  • LSIs bieten konsistente Daten und eignen sich für Sortierlogik innerhalb von Partitionen
  • Durchsatz von GSIs ist separat skalierbar, bei LSIs geteilt mit der Haupttabelle
  • GSIs lassen sich jederzeit hinzufügen – LSIs nur bei Erstellung
  • Größenbeschränkungen bei LSIs: 10 GB pro Partition Key
Global vs. Local Secondary Indexes in DynamoDB

Was sind Secondary Indexes in DynamoDB?

Ein Secondary Index in DynamoDB bietet zusätzliche Zugriffsmöglichkeiten auf Daten, ohne die Haupttabelle scannen zu müssen. Er basiert auf anderen Attributen als der primäre Partition Key oder Sort Key. DynamoDB aktualisiert diese Indizes automatisch und repliziert die relevanten Daten inkrementell. Der Lesedurchsatz verbessert sich erheblich, da gezielte Abfragen mit optimierter Speicherstruktur möglich sind. Vor allem bei wachsenden Datenstrukturen leisten Secondary Indexes entscheidende Performancevorteile.

Global vs. Local Secondary Indexes – der technische Vergleich

Die grundlegenden Unterschiede zwischen GSIs und LSIs liegen in ihrer Beziehung zur Basistabelle. GSIs nutzen unabhängige Partition Keys und sind dadurch vielseitiger einsetzbar. LSIs dagegen behalten denselben Partition Key wie die Originaltabelle und erweitern lediglich die Sortierlogik. Diese Unterschiede beeinflussen maßgeblich Skalierung, Konsistenz und Datenarchitektur.

Merkmal Global Secondary Index (GSI) Local Secondary Index (LSI)
Partition Key Frei definierbar Gleich wie Haupttabelle
Sort Key Optional Unterschiedlich zur Basistabelle
Konsistenz Nur eventual consistency Auch strong consistency
Durchsatz Separat skalierbar Geteilt mit Haupttabelle
Größenlimit Unbegrenzt 10 GB je Partition Key
Anzahl pro Tabelle Bis zu 20 Maximal 5
Erstellungszeitpunkt Jederzeit möglich Nur bei Tabellenerstellung

Global Secondary Indexes (GSI) im Einsatz

Ein GSI erlaubt es, eine ganz neue Sicht auf die Daten einer DynamoDB-Tabelle zu schaffen. Angenommen, eine Tabelle ordnet Anfragen nach Benutzer-ID: Ein GSI kann ermöglichen, dieselben Anfragen nach E-Mail-Adresse zu sortieren – ganz unabhängig vom ursprünglichen Primärschlüssel. Damit entstehen vielseitige Zugriffsmöglichkeiten, besonders in datenreichen Applikationen wie Ticketing-Systemen oder CRM-Tools.

Darüber hinaus entfällt das 10-GB-Limit, das bei LSIs relevant ist. So lassen sich GSIs auch bei millionenfachen Partition-Kombinationen zuverlässig betreiben. Die Indexstruktur wird automatisch verwaltet und lässt sich bei Bedarf löschen oder aktualisieren – ein Vorteil bei iterativer Entwicklung. Entwickler können daher neue Anforderungen flexibel umsetzen, ohne die ursprüngliche Tabelle zu verändern.

Local Secondary Indexes (LSI) verstehen

Local Secondary Indexes ergänzen eine Tabelle mit zusätzlichen Sortiermöglichkeiten – jedoch immer innerhalb eines festen Partition Keys. Das bedeutet: Der Zugriff bleibt auf eine bestimmte User-ID oder Session-ID begrenzt, die alternative Logik greift erst beim Sort Key. Das kann hilfreich sein, wenn man beispielsweise sämtliche Transaktionen eines Nutzers nach Datum oder Status filtern möchte.

Die Möglichkeit, strongly consistent zu lesen, ist der stärkste Vorteil von LSIs. Wenn absolute Datenaktualität im Moment der Abfrage erforderlich ist – wie etwa bei Finanztransaktionen oder medizinischen Datensätzen – ist ein LSI oft die einzige Option. Die Schattenseite: Der Speicher pro Partition darf dennoch nicht die 10-GB-Marke überschreiten. Bei sehr aktiven Systemen kann diese Grenze schnell erreicht werden.

Anwendungsfälle im Vergleich

Je nach Zugriffsmuster empfiehlt sich der Einsatz eines GSI oder LSI. GSIs sind optimal, wenn sich die Datenstruktur ändern kann oder wenn mehrere Abfragen auf verschiedene Attribute erfolgen. Ein gängiges Beispiel ist ein E-Commerce-Produktkatalog, bei dem Produkte nach SKU (Primärschlüssel), aber auch nach Kategorie, Verfügbarkeit oder Marke gefiltert werden sollen – genau hier bietet ein GSI Klarheit.

LSIs entfalten hingegen ihren Vorteil in strikt strukturierten Nutzungsfällen. In Messaging-Plattformen kann ein LSI das Sortieren von Nachrichten nach Sendezeit ermöglichen – aber nur für je eine Konversation. Das sorgt für konsistente Darstellung und schnelle lokale Abfragen. Bei ≤5 LSIs pro Tabelle bleibt dabei der Wartungsaufwand überschaubar.

Kosten- und Skalierungsaspekte

Bei provisioniertem Durchsatz werden GSIs separat berechnet – sowohl bei Lese- als auch Schreibzugriffen. Das kann teurer sein, bietet aber gleichzeitig eine klare Trennung von Verarbeitungslasten. Entwickler können die Ressourcen für GSI-Abfragen unabhängig von der Basistabelle definieren. Das reduziert das Risiko von throttling bei hoher Last.

LSIs hingegen teilen die für die Tabelle bereitgestellten Kapazitäten. Das senkt zwar die Kosten, aber auch die Flexibilität. Wer viele gleichzeitige Abfragen plant – etwa aus interaktiven Dashboards oder mobilen Apps – kann hier an Grenzen stoßen. Ebenso relevant ist das Speicherlimit pro Partition bei LSIs. Für Anwendungen mit hoher Datenrate oder Revisionshistorie braucht es entweder vorsichtige Planung – oder einen Umstieg auf GSIs.

Best Practices zur Nutzung von Indexes

Ich analysiere im Vorfeld die typischen Zugriffsmuster, bevor ich einen Index anlege. Denn jeder GSI kostet zusätzlichen Speicher und Durchsatz – beides schlägt sich direkt in der Abrechnung nieder. In produktiven Anwendungen lohnt es sich, nur tatsächlich genutzte GSIs zu definieren, statt „präventiv“ alles zu indizieren.

Für LSIs wähle ich nur die Attribute aus, von denen ich sicher weiß, dass sie bei Abfragen innerhalb einer Partition zum Einsatz kommen. Ein übermäßiger Einsatz von LSIs kann sonst Schreibvorgänge verlangsamen. Ein weiterer wichtiger Punkt: Sobald eine LSI-Struktur definiert wurde, ist sie nicht mehr änderbar. Bei agilen Projekten mit sich änderndem Datenmodell kann das ein Nachteil sein.

Erweiterte Strategien für Indexing

In komplexen Anwendungen greife ich oft auf eine Kombination aus GSI und LSI zurück, um sowohl eine flexible Abfrage als auch konsistente Daten zu erhalten. Eine verbreitete Strategie ist das sogenannte „Index Overloading“, bei dem mehrere Zugriffsmuster in einem einzigen GSI abgebildet werden. Statt für jedes Abfrageszenario einen eigenen GSI anzulegen, definiere ich einen Partition Key, der entweder dynamisch die Art der Abfrage widerspiegelt oder ein gemeinsames Attribut enthält, das sich für unterschiedliche Suchen eignet. So kann ich unnötige Indizes reduzieren und spare sowohl Kosten als auch Verwaltungsaufwand.

Darüber hinaus ist es wichtig, die sogenannten Projection Types zu verstehen. Damit kann ich steuern, welche Attribute einer Tabelle im Index gespeichert werden. Bei „Keys only“ werden nur Partition und Sort Key im Index vorgehalten. Das reduziert den Speicherbedarf und die Schreiblast, wenn für die Anwendung lediglich der Schlüssel benötigt wird. „Include“ ermöglicht, gezielt zusätzliche Attribute zu indexieren, während „All“ sämtliche Attribute der Basistabelle dupliziert. Letzteres erspare ich mir meist, da damit schnell die Speicherkapazität ansteigt.

Gerade in Multi-Tenant-Szenarien mit mandantenfähiger Architektur wird das Index-Design besonders relevant. Ein häufiger Ansatz ist, den Mandanten (z. B. tenant_id) als Partition Key zu verwenden. Dabei lässt sich ein GSI nutzen, um Mandantenserver-übergreifende Suchen zuzulassen. An anderer Stelle kann ein LSI greifen, wenn die Daten nach bestimmten Statuswerten oder Zeitstempeln getrennt werden sollen – jedoch eben nur innerhalb desselben Mandanten. So behalte ich die Übersicht pro Tenant, ohne ungewollt Daten vermischen zu müssen.

Umgang mit Schreibmustern und Konsistenz

Prinzipiell gilt bei DynamoDB: Schreibvorgänge können durch die Indexierung teurer werden, da Änderungen an Datensätzen nicht nur in der Basistabelle, sondern auch in den Indizes nachvollzogen werden müssen. Bei hochfrequenten Schreiblasten plane ich deshalb ausreichend Kapazitäten für alle betroffenen GSIs ein. Für LSIs sind dieselben Kapazitäten wie für die Basistabelle maßgeblich, was den Vorteil der Kosteneffizienz hat, sofern sich die Schreiblast in Grenzen hält. Ebenso beachte ich die Konsistenzanforderungen: GSIs unterstützen nur eventual consistency, was in vielen Fällen völlig ausreichend ist, aber in bestimmten Bereichen wie Echtzeit-Analysen oder Live-Dashboards zu Verzögerungen führen könnte.

Wenn eine Transaktion zwingend in Echtzeit verarbeitet werden muss, bevor ich das Ergebnis in einem Abfrage-Frontend oder einer API zurückliefern kann, nutze ich in der Regel die strongly consistent Reads der Basistabelle oder – falls das Zugriffsmuster passend ist – eines LSI. Auch in audit- oder compliance-relevanten Szenarien kann sich die strong consistency eines LSI als entscheidender Vorteil erweisen. In der Praxis kombiniere ich für kritische Datensätze gern LSI-Abfragen mit einem GSI für die flexiblen Suchanfragen weniger zeitkritischer Art.

Indexierung und Datenmodellierung

Viele NoSQL-Entwürfe basieren auf dem Prinzip „Beginne beim Abfrageverhalten“. Wer früh weiß, welche Fragen an die Daten gestellt werden, vermeidet spätere Umstrukturierungen. In DynamoDB plane ich daher Partition Keys und Sort Keys so, dass ich weiß, wie ich später filtern und sortieren muss. Indizes bilden dann die Abfragen ab, die ich in der Basistabelle nicht effizient erledigen kann. Dabei hilft es, die Entitäten in Access Patterns zu gliedern – eine Art Mapping zwischen Use Cases und Datenlayout. So erkenne ich schon vor der Implementierung, ob ich GSI oder LSI benötige.

Gerne nutze ich auch Composite Keys, bei denen der Sort Key mehrere Datenpunkte enthält, etwa „#STATUS#TIMESTAMP“. Damit kann ich in LSIs nicht nur nach Status, sondern auch Zyklen oder anderen Unterkategorien sortieren. Gleichzeitig spare ich Platz, weil ich weniger einzelne Attribute anlegen muss. Für GSIs lassen sich ähnliche Konstruktionen nutzen, um flexiblere Anfragen zu ermöglichen, beispielsweise „#COUNTRY#CITY“ für regionale Filterung.

Performance-Tuning und Fehlervermeidung

Eine häufige Fehlerquelle ist das Hot Partitioning – wenn zu viele Lese- oder Schreibanfragen auf einen einzigen Partition Key treffen. Das kann sowohl bei GSIs als auch LSIs die Performance drosseln. Deshalb verteile ich besonders stark genutzte Attribute oft auf unterschiedliche Partition Keys oder nutze Strategien wie Hash-Suffixe, um eine gleichmäßigere Lastverteilung zu erreichen. Beim GSI ist es einfacher, später einen neuen Index mit einem angepassten Partition Key hinzuzufügen, während bei LSI diese Entscheidung bereits bei der Tabellenerstellung getroffen werden muss.

Um nachhaltig Performance zu sichern, behalte ich regelmäßig die metrischen Daten aus Amazon CloudWatch im Blick. Dort sehe ich, ob einzelne Partition Keys häufiger Anfragen empfangen als andere. Nimmt ein bestimmter Key extrem viel Volumen ein, lohnt es sich, das Datenmodell anzupassen. Bei starker Wachstumsprognose plane ich außerdem von Beginn an, dass ein LSI möglicherweise die 10-GB-Grenze sprengt. Dann muss ich mich auf ein GSI-Design oder auf eine Sharding-Strategie verlegen, um die Daten gleichmäßig zu verteilen.

Migration und Evolution des Datenmodells

Gerade bei agilen Projekten oder Start-ups wächst das Datenmodell oft in Etappen. Hier habe ich den Nutzen eines GSIs bereits mehrfach erlebt: Neue Queries ergeben sich, wenn das Produkt wächst und Nutzer neue Features fordern. Ein GSI kann ich jederzeit anlegen, ohne die Basistabelle zu beeinträchtigen oder neu anzulegen. Ist hingegen ein LSI nicht mehr passend, bleibt häufig nur die Neuanlage der gesamten Tabelle, was besonders in produktiven Umgebungen mit großem Datenvolumen entsprechende Aufwände verursacht.

Zur Migration kann eine Zwischenschicht dienen, die Daten aus der alten Tabelle ausliest, transformiert und in die neue Tabelle mit neuer LSI- oder GSI-Struktur einspielt. Alternativ können Streams eingesetzt werden, um in Echtzeit Daten zu einer neuen Tabelle oder einem neuen Index zu replizieren. Dabei vermeide ich jedoch Ladezyklen unter hoher Last, wenn möglich, um Write Throttling zu verhindern.

Resümee: Welcher Index passt am besten?

Wer auf stark strukturierte Abfragepfade mit garantierter Konsistenz Wert legt, ist mit einem Local Secondary Index bestens bedient. Dagegen liefert ein Global Secondary Index deutlich mehr Spielraum für dynamische Abfragen und ist unverzichtbar bei wachsender Datenvielfalt. In der Praxis arbeite ich oft mit einer Kombination beider Indexarten, um sensitive Daten konsistent zu halten und zugleich flexibel in Reports oder Filtern reagieren zu können.

Beide Index-Typen machen DynamoDB Indexes zu einem leistungsstarken Werkzeug. Wer das Datenmodell von Anfang an plant und Abfragen hinterfragt, erreicht eine ausgewogene Balance aus Performance, Skalierung und Kosten. Die richtige Entscheidung für einen Index wirkt sich dabei oft deutlich auf Latenzzeiten, Entwicklungsfreiheit und Stabilität aus. So wird aus einer NoSQL-Datenbank ein strategischer Baustein skalierbarer Anwendungen.

Nach oben scrollen