Optimierung der SQL-Last
Große E-Commerce-Plattform
Einleitung
Ein Kunde wandte sich mit der Anforderung an uns, die Ladezeit einer der wichtigsten Seiten seiner Website deutlich zu verbessern. Die Seite wies Ladeverzögerungen von mehreren Sekunden auf. Bereits bei der ersten Analyse zeigte sich, dass die Ursache in einer übermäßigen Datenbanklast lag: Beim Aufruf der Seite wurden mehr als 16.000 SQL-Abfragen ausgeführt.
Diese Last führte nicht nur zu Performanceproblemen, sondern gefährdete auch die Stabilität der Seite bei steigendem Traffic. Ziel war es, die Optimierung in kürzester Zeit durchzuführen – ohne die Geschäftslogik zu verändern oder andere Bereiche der Website zu beeinflussen.
Unser Team führte eine gezielte Optimierung der Datenladearchitektur durch und erzielte ein bemerkenswertes Ergebnis: nur noch 24 Abfragen statt 16.685 – und das innerhalb von lediglich 1,5 Stunden.
Systembeschreibung
Das Projekt umfasst eine umfangreiche E-Commerce-Plattform, entwickelt mit dem Laravel-10-Framework und dem Eloquent-ORM. Als Datenbank wird MySQL verwendet. Die Frontend-Darstellung basiert auf Blade und wird teilweise durch Vue.js ergänzt.
Die betroffene Seite stellte einen Produktkatalog dar. Jedes Produkt beinhaltete Bilder, technische Daten, Filterparameter, Markeninformationen, Verfügbarkeiten sowie personalisierte Nutzerdaten (z. B. Favoriten).
Aufgrund der hohen Datenverknüpfung und des Fehlens geeigneter Optimierungsmechanismen kam es zu einer explosionsartigen Zunahme der SQL-Abfragen.
Die Ursache lag jedoch nicht in der Datenmenge, sondern in der Art der Datenabfrage: Es wurde kein Eager Loading eingesetzt, was zum klassischen N+1-Problem führte – für jeden Datensatz wurden zusätzliche Abfragen an verbundene Tabellen ausgelöst.
Herausforderung: Zu viele SQL-Abfragen auf einer einzigen Seite
Mit Hilfe von Profiling-Tools (Laravel Debugbar, SQL-Logging) wurden beim Laden einer einzelnen Seite 16.685 Abfragen festgestellt. Die Hauptursachen waren:
- Abfragen zu verbundenen Modellen wurden innerhalb von Schleifen ausgeführt.
- Modellbeziehungen waren nicht definiert oder wurden nicht genutzt.
- In den Templates wurden Beziehungen ohne vorheriges Laden aufgerufen.
Der Kunde stellte dabei folgende Anforderungen:
- Keine Änderungen an der Geschäftslogik oder der API.
- Die Lösung muss skalierbar sein.
- Strikte Einhaltung der Laravel-Standards – keine „Tricks“ oder manuelle Datenaggregation.
Lösung: Einsatz von Eager Loading und Optimierung der Modelle
Die Optimierung erfolgte in mehreren Schritten:
Analyse der Engpässe
Alle beteiligten Modelle, Controller-Logiken und Templates wurden überprüft.
Korrektur der Modellbeziehungen
Beziehungen wie hasMany, belongsTo, hasOne, morphMany usw. wurden korrekt definiert. Dadurch konnten die zugehörigen Datensätze sauber und explizit geladen werden.
Implementierung von Eager Loading
Überall dort, wo zuvor Lazy Loading verwendet wurde, kamen nun with() und load() zum Einsatz, um die benötigten Daten in möglichst wenigen Abfragen zu laden.
Beispiel:
Product::with(['images', 'brand', 'filters', 'favorites'])->get();
Optimierung der Templates und Darstellung
Die Blade-Templates wurden überarbeitet: Verweise auf Links innerhalb von Schleifen entfernt, die Darstellung vereinfacht und doppelte Abfragen beseitigt.
Tests und Messungen
Nach der Umsetzung wurden Lasttests sowie ein erneutes SQL-Logging durchgeführt.
Ergebnis: Für die vollständige Seitenladung werden nun nur noch 24 Abfragen benötigt.