Performance-Tuning Ihres PrestaShop-Shops: Von Datenbankabfragen bis Full Page Cache
Jede Abfrage zählt: Warum die Datenbank-Performance der verborgene Engpass Ihres Shops ist
Ich habe in den letzten fünf Jahren über 200 PrestaShop-Shops geprüft. Jedes einzelne Mal — ohne Ausnahme — kam der größte Performance-Gewinn aus der Datenbankschicht. Nicht von einem CDN. Nicht von der Bildkomprimierung. Nicht von einem weiteren Caching-Plugin. Der Datenbank.

Ein typischer PrestaShop-Seitenaufruf führt zwischen 80 und 300 SQL-Abfragen aus. In einem Shop mit 10.000+ Produkten kann diese Zahl auf Kategorieseiten mit Facettennavigation über 500 steigen. Wenn auch nur eine Handvoll dieser Abfragen 200ms statt 2ms benötigt, bläht sich Ihre Time to First Byte (TTFB) auf, die Server-CPU schießt in die Höhe und Ihre Conversion-Rate sinkt. Googles eigene Forschung zeigt, dass ein Anstieg der Ladezeit um 100ms die Conversions um bis zu 7 % reduziert.
Dieser Artikel ist kein generischer „Mach PrestaShop schneller"-Überblick. Ich gehe tief in die Datenbank-Performance — langsame Abfragen identifizieren, Ausführungspläne verstehen, InnoDB tunen, die richtigen Indizes wählen und den Datenballast bereinigen, der Ihren Shop still und leise ausbremst. Wenn Sie bereits unseren allgemeinen Performance-Leitfaden gelesen haben, betrachten Sie dies als das nächste Kapitel.
Schritt 1: Aktivieren Sie das Slow Query Log — Ihr bestes einzelnes Diagnosetool
Bevor Sie irgendetwas optimieren, müssen Sie sehen, was tatsächlich langsam ist. Das Slow Query Log von MySQL zeichnet jede Abfrage auf, die einen von Ihnen definierten Zeitschwellenwert überschreitet. Ich kann nicht mehr zählen, wie viele Shop-Betreiber diesen Schritt überspringen und direkt zu „Redis hinzufügen" greifen — das ist wie Schmerzmittel zu nehmen, ohne die Verletzung zu diagnostizieren.
Aktivierung des Slow Query Logs
Fügen Sie diese Zeilen in Ihre MySQL- oder MariaDB-Konfigurationsdatei ein (typischerweise /etc/mysql/mysql.conf.d/mysqld.cnf oder /etc/mysql/mariadb.conf.d/50-server.cnf):
# Enable slow query logging
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow-query.log
long_query_time = 0.5
log_queries_not_using_indexes = 1
min_examined_row_count = 100
Die wichtigsten Einstellungen:
long_query_time = 0.5— Jede Abfrage protokollieren, die länger als 500ms dauert. Der Standardwert von 10 Sekunden ist absurd hoch für E-Commerce; wenn eine Abfrage 10 Sekunden braucht, hat Ihr Kunde schon vor 8 Sekunden die Seite verlassen.log_queries_not_using_indexes = 1— Fängt Abfragen ab, die volle Tabellen-Scans durchführen, selbst wenn sie bei kleinen Datenmengen schnell sind. Diese sind tickende Zeitbomben, die explodieren, wenn Ihr Katalog wächst.min_examined_row_count = 100— Filtert triviale Abfragen heraus, damit Ihr Log auf echte Probleme fokussiert bleibt.
Starten Sie nach der Aktivierung MySQL neu und lassen Sie es mindestens 24 Stunden lang Daten sammeln, die einen vollständigen Traffic-Zyklus abdecken. Dann analysieren:
# Summarize the worst offenders
mysqldumpslow -s t -t 20 /var/log/mysql/slow-query.log
# Or use pt-query-digest from Percona Toolkit for deeper analysis
pt-query-digest /var/log/mysql/slow-query.log > /tmp/query-report.txt
pt-query-digest aus dem Percona Toolkit ist hier der Goldstandard. Es gruppiert ähnliche Abfragen, ordnet sie nach Gesamtausführungszeit und zeigt Ihnen genau, wo Ihre Datenbank ihre Zeit verbringt. Installieren Sie es — es ist kostenlos und in den meisten Paketmanagern verfügbar.
Schritt 2: EXPLAIN-Pläne lesen — Die Fähigkeit, die Raten von Wissen trennt
Sobald Sie Ihre langsamen Abfragen identifiziert haben, ist der nächste Schritt zu verstehen, warum sie langsam sind. Der EXPLAIN-Befehl von MySQL zeigt Ihnen den Ausführungsplan — wie der Optimizer entscheidet, Ihre Daten abzurufen.
EXPLAIN SELECT p.id_product, pl.name, p.price
FROM ps_product p
LEFT JOIN ps_product_lang pl ON p.id_product = pl.id_product AND pl.id_lang = 1
LEFT JOIN ps_category_product cp ON p.id_product = cp.id_product
WHERE cp.id_category = 42 AND p.active = 1
ORDER BY p.date_add DESC;
Worauf Sie in der Ausgabe achten sollten
| Spalte | Warnsignal | Bedeutung |
|---|---|---|
type | ALL | Voller Tabellen-Scan — MySQL liest jede Zeile. Nur bei winzigen Tabellen akzeptabel. |
type | index | Voller Index-Scan — besser als ALL, liest aber trotzdem jeden Index-Eintrag. |
possible_keys | NULL | Keine Indizes verfügbar. Der Optimizer hat nichts zum Arbeiten. |
key | NULL | Kein Index gewählt, obwohl Optionen existieren. Bedeutet meist, dass die Index-Statistiken veraltet sind. |
rows | Hohe Zahl | Geschätzte geprüfte Zeilen. Vergleichen Sie mit der tatsächlichen Ergebnisanzahl — ein Verhältnis von 50.000:12 signalisiert einen fehlenden Index. |
Extra | Using temporary | MySQL erstellt eine temporäre Tabelle, die oft auf die Festplatte ausgelagert wird. |
Extra | Using filesort | Ergebnisse werden im Speicher oder auf der Festplatte sortiert statt über die Index-Reihenfolge. |
Die ideale EXPLAIN-Ausgabe zeigt type: ref oder type: eq_ref, einen bestimmten verwendeten key und eine niedrige rows-Schätzung. Wenn Sie type: ALL kombiniert mit Using temporary; Using filesort sehen, haben Sie eine Abfrage gefunden, die maximalen Aufwand für minimale Ergebnisse betreibt.
Ein reales PrestaShop-Beispiel
Eine der häufigsten langsamen Abfragen, die mir in PrestaShop-Shops begegnet, betrifft die Tabelle ps_specific_price. In Shops mit Tausenden von spezifischen Preisen (Mengenrabatte, Gruppenpreise, zeitgesteuerte Aktionen) erscheint dieses Abfragemuster ständig im Slow Log:
EXPLAIN SELECT * FROM ps_specific_price
WHERE id_product = 1542
AND id_shop IN (0, 1)
AND id_currency IN (0, 1)
AND id_country IN (0, 8)
AND id_group IN (0, 1, 3)
AND id_customer = 0
AND from_quantity >= 1
AND (from = '0000-00-00 00:00:00' OR from <= NOW())
AND (to = '0000-00-00 00:00:00' OR to >= NOW());
In einem Shop mit über 200.000 specific_price-Zeilen prüfte diese Abfrage 180.000 Zeilen, um 3 zurückzugeben. Die Lösung war ein zusammengesetzter Index:
ALTER TABLE ps_specific_price
ADD INDEX idx_product_shop_currency
(id_product, id_shop, id_currency, id_country);
Ergebnis: Die Abfragezeit sank von 340ms auf 0,8ms. Auf einer Kategorieseite mit 36 Produkten sparte dieser einzelne Index 12 Sekunden kumulative Abfragezeit pro Seitenaufruf.
Schritt 3: Die schlimmsten Problemtabellen von PrestaShop — und wie man sie behebt
Nach der Analyse von Slow Query Logs aus Dutzenden von Shops sind diese Tabellen für die Mehrheit der Datenbank-Performance-Probleme verantwortlich:
ps_connections und ps_connections_page
Diese Tabellen protokollieren jede Besucherverbindung und jede aufgerufene Seite. In einem Shop mit 5.000 täglichen Besuchern, die durchschnittlich 4 Seiten aufrufen, sind das 20.000 Zeilen pro Tag — 7,3 Millionen Zeilen pro Jahr. Ich habe Shops mit 50 Millionen Zeilen in ps_connections_page gesehen, die nie bereinigt wurden.
-- Check the damage
SELECT table_name, table_rows,
ROUND(data_length/1024/1024, 2) AS data_mb,
ROUND(index_length/1024/1024, 2) AS index_mb
FROM information_schema.tables
WHERE table_schema = 'prestashop'
AND table_name IN ('ps_connections', 'ps_connections_page',
'ps_log', 'ps_mail', 'ps_guest', 'ps_pagenotfound');
-- Clean old connection data (keep 90 days)
DELETE FROM ps_connections_page
WHERE id_connections IN (
SELECT id_connections FROM ps_connections
WHERE date_add < DATE_SUB(NOW(), INTERVAL 90 DAY)
);
DELETE FROM ps_connections WHERE date_add < DATE_SUB(NOW(), INTERVAL 90 DAY);
-- Clean old logs (keep 30 days)
DELETE FROM ps_log WHERE date_add < DATE_SUB(NOW(), INTERVAL 30 DAY);
-- Clean sent emails log (keep 60 days)
DELETE FROM ps_mail WHERE date_add < DATE_SUB(NOW(), INTERVAL 60 DAY);
-- Clean 404 tracking (keep 30 days)
DELETE FROM ps_pagenotfound WHERE date_add < DATE_SUB(NOW(), INTERVAL 30 DAY);
Wichtig: Nach großen Löschvorgängen den Speicherplatz zurückgewinnen:
OPTIMIZE TABLE ps_connections, ps_connections_page, ps_log, ps_mail, ps_guest;
ps_cart und ps_cart_product
Abgebrochene Warenkörbe sammeln sich endlos an. Ein 5 Jahre alter Shop könnte 2 Millionen Warenkorbdatensätze mit 8 Millionen cart_product-Zeilen haben, von denen 95 % nie konvertieren werden. Bereinigen Sie Warenkörbe, die älter als 6 Monate sind und keine zugehörige Bestellung haben:
-- Identify orphan carts (no order placed)
DELETE cp FROM ps_cart_product cp
INNER JOIN ps_cart c ON cp.id_cart = c.id_cart
LEFT JOIN ps_orders o ON c.id_cart = o.id_cart
WHERE o.id_cart IS NULL
AND c.date_add < DATE_SUB(NOW(), INTERVAL 180 DAY);
DELETE c FROM ps_cart c
LEFT JOIN ps_orders o ON c.id_cart = o.id_cart
WHERE o.id_cart IS NULL
AND c.date_add < DATE_SUB(NOW(), INTERVAL 180 DAY);
ps_search_index und ps_search_word
Der Produktsuchindex kann bei großen Katalogen enorm anwachsen. Nach dem Bereinigen von Produkten oder Massenaktualisierungen neu aufbauen:
-- Nuclear option: truncate and rebuild
TRUNCATE TABLE ps_search_index;
TRUNCATE TABLE ps_search_word;
-- Then trigger a full reindex via CLI:
php bin/console prestashop:search:reindex
Schritt 4: Index-Strategie für PrestaShop-Modultabellen
Wenn Sie Module entwickeln — oder Drittanbieter-Module verwenden, die benutzerdefinierte Tabellen erstellen — liegt die Indizierung in Ihrer Verantwortung. Die Kerntabellen von PrestaShop werden mit vernünftigen Indizes ausgeliefert, aber Modultabellen haben häufig gar keine.
Prinzipien für effektive Indizierung
- Indizieren Sie Spalten, die in WHERE-Klauseln verwendet werden — Wenn Ihr Modul abfragt
WHERE id_product = X AND id_shop = Y, erstellen Sie einen zusammengesetzten Index auf(id_product, id_shop). - Die Spaltenreihenfolge ist bei zusammengesetzten Indizes wichtig — Setzen Sie die selektivste Spalte an die erste Stelle. Eine Spalte mit 10.000 eindeutigen Werten sollte einer mit 3 eindeutigen Werten vorangehen.
- Decken Sie Ihr ORDER BY ab — Wenn Sie häufig nach
date_add DESCsortieren, nehmen Siedate_addin den Index auf, um Filesort-Operationen zu vermeiden. - Nicht überindizieren — Jeder Index verlangsamt INSERT- und UPDATE-Operationen. Für eine Tabelle mit vielen Schreibvorgängen (wie eine Logging-Tabelle) sollten Sie sorgfältig abwägen, bevor Sie Indizes hinzufügen.
-- Example: module review table with common query patterns
CREATE TABLE ps_mymodule_reviews (
id_review INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
id_product INT UNSIGNED NOT NULL,
id_customer INT UNSIGNED NOT NULL,
id_shop INT UNSIGNED NOT NULL DEFAULT 1,
rating TINYINT UNSIGNED NOT NULL,
status TINYINT NOT NULL DEFAULT 0,
date_add DATETIME NOT NULL,
-- Composite index for "show approved reviews for product X"
INDEX idx_product_status (id_product, status, date_add),
-- Index for "show all reviews by customer"
INDEX idx_customer (id_customer),
-- Index for admin list with shop filter
INDEX idx_shop_status (id_shop, status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
Fehlende Indizes auf bestehenden Tabellen finden
-- List all module tables without non-primary indexes
SELECT t.table_name, t.table_rows
FROM information_schema.tables t
LEFT JOIN information_schema.statistics s
ON t.table_name = s.table_name
AND t.table_schema = s.table_schema
AND s.index_name != 'PRIMARY'
WHERE t.table_schema = 'prestashop'
AND t.table_name LIKE 'ps_%'
AND t.table_rows > 1000
AND s.index_name IS NULL
ORDER BY t.table_rows DESC;
Diese Abfrage zeigt Tabellen mit über 1.000 Zeilen und ohne sekundäre Indizes — erstklassige Kandidaten für die Optimierung.
Schritt 5: InnoDB-Konfiguration — Die Einstellungen, die wirklich wichtig sind
InnoDB ist die Storage Engine von PrestaShop. Ihre Standardkonfiguration ist für eine generische Arbeitslast auf bescheidener Hardware ausgelegt. Für einen dedizierten E-Commerce-Datenbankserver müssen Sie sie tunen.

Die entscheidenden Einstellungen
[mysqld]
# === Buffer Pool: The Single Most Important Setting ===
# Set to 70-80% of available RAM on a dedicated DB server.
# For shared hosting: 50% of RAM, minimum 1GB.
innodb_buffer_pool_size = 4G
# Split the buffer pool into instances (1 per GB)
innodb_buffer_pool_instances = 4
# === Log Files: Larger = Fewer Disk Writes ===
# Default 48M is too small. Set to 25% of buffer pool, max 2G each.
innodb_log_file_size = 1G
innodb_log_buffer_size = 64M
# === Flush Behavior ===
# 1 = Full ACID (safest, slower)
# 2 = Flush to OS buffer each commit, disk write once/sec (good compromise)
# 0 = Flush once/sec (fastest, risks 1 sec of data on crash)
innodb_flush_log_at_trx_commit = 2
# Use O_DIRECT to avoid double-buffering with OS page cache
innodb_flush_method = O_DIRECT
# === I/O Capacity ===
# SSD: 2000-4000. HDD: 200-400. Cloud SSD: 1000-2000.
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000
# === Thread Concurrency ===
innodb_read_io_threads = 4
innodb_write_io_threads = 4
innodb_purge_threads = 4
# === Per-Table Tablespace (default in MySQL 5.7+, verify it's on) ===
innodb_file_per_table = 1
# === Temp Tables ===
tmp_table_size = 64M
max_heap_table_size = 64M
# === Sort and Join Buffers (per-connection, don't over-allocate) ===
sort_buffer_size = 2M
join_buffer_size = 4M
read_buffer_size = 2M
read_rnd_buffer_size = 1M
# === Connection Pool ===
max_connections = 200
thread_cache_size = 100
# === Table Cache ===
table_open_cache = 4000
table_definition_cache = 2000
# === Disable Performance Schema in Production (saves ~400MB RAM) ===
performance_schema = OFF
innodb_buffer_pool_size verstehen
Dies ist die einzelne wirkungsvollste MySQL-Einstellung für PrestaShop. Der Buffer Pool ist der Bereich, in dem InnoDB Tabellendaten und Indizes im Speicher zwischenspeichert. Wenn eine Abfrage Daten benötigt, die bereits im Buffer Pool sind, werden sie aus dem RAM statt von der Festplatte geliefert — um Größenordnungen schneller.
Wie man ihn dimensioniert:
-- Check your total database size
SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS total_gb
FROM information_schema.tables
WHERE table_schema = 'prestashop';
-- Check buffer pool hit ratio (should be > 99%)
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
-- Calculate: hit_ratio = 1 - (reads / read_requests) * 100
-- If below 99%, increase buffer_pool_size
Ein realer Benchmark aus Releems Tests mit MariaDB 10.5 und einem PrestaShop-Shop zeigte, dass korrektes InnoDB-Tuning (Buffer Pool auf 3,2 GB für eine 1-GB-Datenbank dimensioniert) die Antwortzeit um 39 % reduzierte — von 610ms auf 370ms — und die Abfragen pro Sekunde um 53 % steigerte.
Query Cache: MariaDB vs. MySQL 8
Dies ist ein häufig missverstandenes Thema. MySQL 8.0 hat den Query Cache vollständig entfernt. Oracle stellte fest, dass die Mutex-Konflikte des Caches bei Skalierung mehr Probleme verursachten als lösten. MariaDB unterstützt ihn jedoch weiterhin, und er kann PrestaShop-Shops mit leselastigen Workloads helfen.
Für MariaDB (10.5+):
query_cache_type = 1
query_cache_size = 64M
query_cache_limit = 2M
Für MySQL 8.0+: Versuchen Sie nicht, ihn zu aktivieren — er existiert nicht. Verlassen Sie sich stattdessen auf einen korrekt dimensionierten Buffer Pool und ziehen Sie Application-Level-Caching mit Redis in Betracht.
Wenn Sie MySQL 8 verwenden und einen Wechsel in Betracht ziehen: MariaDB 10.11 ist vollständig kompatibel mit PrestaShop, und viele Hosting-Anbieter bieten es als Drop-in-Ersatz an.
Schritt 6: PrestaShop-spezifische Abfragemuster, die Sie beachten sollten
Über das allgemeine MySQL-Tuning hinaus hat PrestaShop spezifische Abfragemuster, die bei Skalierung Performance-Probleme verursachen. Hier sind diejenigen, denen ich am häufigsten begegne:
Das Produktzähler-Problem
Die Facettennavigation (Layered Navigation) von PrestaShop führt COUNT-Abfragen für jede Filterkombination aus. In einer Kategorie mit 15 Attributgruppen und 200 Attributen können pro Seitenaufruf über 200 einzelne COUNT-Abfragen generiert werden. Jede einzelne Abfrage sieht harmlos aus:
SELECT COUNT(DISTINCT p.id_product)
FROM ps_product p
INNER JOIN ps_product_attribute_combination pac ...
WHERE ... AND pac.id_attribute = 47;
Aber 200 davon mit je 10ms ergibt 2 Sekunden reine Abfragezeit. Die Lösung ist entweder die Verwendung einer vorberechneten Index-Tabelle (die Module wie unsere SEO- und Performance-Module bereitstellen können) oder die Reduzierung sichtbarer Filter über die Kategoriekonfiguration.
Das N+1-Abfrageproblem in Modul-Hooks
Ein Modul, das auf displayProductListReviews registriert ist und pro Produkt eine Abfrage ausführt, erzeugt ein N+1-Problem. Wenn Ihre Kategorieseite 36 Produkte anzeigt, sind das 36 zusätzliche Abfragen — pro Modul:
// Bad: query per product in a list hook
public function hookDisplayProductListReviews($params) {
$id_product = (int)$params['product']['id_product'];
$result = Db::getInstance()->getRow(
'SELECT AVG(rating) as avg_rating
FROM ps_mymodule_reviews
WHERE id_product = ' . $id_product
);
// ...
}
// Good: batch query all products at once, cache the result
public function hookActionProductSearchAfter($params) {
$products = $params['result']->getProducts();
$ids = array_column($products, 'id_product');
$ratings = Db::getInstance()->executeS(
'SELECT id_product, AVG(rating) as avg_rating
FROM ps_mymodule_reviews
WHERE id_product IN (' . implode(',', array_map('intval', $ids)) . ')
GROUP BY id_product'
);
// Store in static cache for use in display hook
}
Warenkorbregeln-Auswertung
Shops mit Hunderten aktiver Warenkorbregeln leiden bei jedem Aufruf der Warenkorbseite. Die Bedingungen jeder Warenkorbregel (Produkteinschränkungen, Kategorieeinschränkungen, Kundengruppen) lösen separate Abfragen aus. Wenn Sie mehr als 50 aktive Warenkorbregeln haben, sollten Sie Folgendes in Betracht ziehen:
- Abgelaufene Regeln archivieren (setzen Sie deren
activeauf 0 unddate_toauf ein vergangenes Datum) - Überlappende Regeln konsolidieren, wo möglich
- Einen Index auf
ps_cart_rule.active, ps_cart_rule.date_from, ps_cart_rule.date_tohinzufügen
Schritt 7: Monitoring in der Produktion — Nicht einrichten und vergessen
Datenbank-Tuning ist keine einmalige Aufgabe. Die Daten Ihres Shops wachsen, Traffic-Muster ändern sich und Modul-Updates können neue Abfragemuster einführen. Richten Sie ein laufendes Monitoring ein:
Wesentliche Metriken zum Verfolgen
-- Buffer pool efficiency (check weekly)
SELECT
FORMAT(VARIABLE_VALUE, 0) AS buffer_pool_read_requests
FROM performance_schema.global_status
WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests';
-- Slow queries per hour (should trend downward)
SHOW GLOBAL STATUS LIKE 'Slow_queries';
-- Table lock waits (should be near zero for InnoDB)
SHOW GLOBAL STATUS LIKE 'Table_locks_waited';
-- Temporary tables created on disk (high = increase tmp_table_size)
SHOW GLOBAL STATUS LIKE 'Created_tmp_disk_tables';
SHOW GLOBAL STATUS LIKE 'Created_tmp_tables';
-- Thread connection usage
SHOW GLOBAL STATUS LIKE 'Threads_connected';
SHOW GLOBAL STATUS LIKE 'Max_used_connections';
Automatisiertes Monitoring
Für Shops, in denen Ausfallzeiten echten Umsatzverlust bedeuten, ziehen Sie diese Monitoring-Lösungen in Betracht:
- Percona Monitoring and Management (PMM) — Kostenlos, Open Source, umfassende MySQL-/MariaDB-Dashboards mit Abfrageanalyse. Dies verwende ich für alle Kundenshops.
- Releem — Automatisiertes MySQL-Tuning, das Parameter basierend auf Ihrer tatsächlichen Arbeitslast anpasst. Nützlich, wenn Sie
my.cnfnicht manuell tunen möchten. - MySQLTuner — Ein Perl-Skript, das schnelle Empfehlungen liefert:
perl mysqltuner.pl --host 127.0.0.1
Schritt 8: Wann Redis hinzufügen — und was es tatsächlich löst
Redis ist kein Ersatz für Datenbankoptimierung. Es ist eine Schicht darüber. Wenn Ihre zugrundeliegenden Abfragen langsam sind, maskiert Redis das Problem für zwischengespeicherte Anfragen und verschlimmert es, wenn der Cache abläuft (Thundering Herd).
Nachdem Sie Ihre Indizes optimiert, Ihre Tabellen bereinigt und InnoDB getunt haben — dann fügen Sie Redis hinzu für:
- Session-Speicherung — Eliminiert File-Locking bei gleichzeitigen Anfragen. Konfigurieren Sie in
config/defines.inc.phpoder verwenden Sie den Symfony-Session-Handler. - Smarty-Cache — Verhindert, dass Smarty Tausende kompilierter Template-Dateien auf die Festplatte schreibt.
- Symfony-Cache — Doctrine-Metadaten, Routing und Service-Container-Caches werden aus dem Speicher bedient.
- Modul-Level-Caching — Alle Moduldaten, die aufwendig zu berechnen sind, sich aber selten ändern.
Das Ergebnis: In einem korrekt getunten Shop reduziert das Hinzufügen von Redis die TTFB typischerweise um weitere 30–50 %. Unser Performance-Leitfaden behandelt die Redis-Konfiguration im Detail.
Schritt 9: Full Page Cache — Die letzte Schicht
Sobald Ihre Datenbank schlank und Ihr Application Cache in Redis ist, besteht die ultimative Optimierung darin, die PHP-Ausführung für anonyme Besucher vollständig zu eliminieren. Varnish oder nginx FastCGI Cache können eine vollständig gerenderte Seite in unter 10ms ausliefern — verglichen mit 200–500ms für eine PHP-gerenderte Seite.
Die Herausforderung bei PrestaShop ist die Cache-Invalidierung. Preisänderungen, Bestandsaktualisierungen, Aktionsstarts/-enden und Warenkorbänderungen erfordern entweder:
- Tag-basierte Invalidierung — Das
xkey-Modul von Varnish ermöglicht es, zwischengespeicherte Seiten nach Produkt, Kategorie oder CMS-Seite zu taggen und selektiv zu invalidieren. - TTL-basierter Ansatz — Seiten 5–15 Minuten zwischenspeichern und kurze Veralterung akzeptieren. Geeignet für die meisten Shops, in denen sekundengenaue Bestandsgenauigkeit nicht kritisch ist.
- Hybrid-Ansatz — Die Seitenhülle zwischenspeichern, ESI (Edge Side Includes) oder JavaScript für dynamische Fragmente wie das Warenkorb-Widget und den Login-Status verwenden.
Für Hochverkehrs-Shops erreicht die Kombination aus optimierter Datenbank + Redis Application Cache + Varnish FPC routinemäßig eine TTFB unter 50ms. Einer unserer Kunden mit einem 15.000-Produkte-Katalog ging von 800ms TTFB auf 120ms mit genau diesem Stack.
Die Prioritätsreihenfolge: Maximale Wirkung, minimales Risiko
Wenn Sie eine Sache aus diesem Artikel mitnehmen, dann diese Prioritätsliste:
- Slow Query Log aktivieren und die Top-10-Abfragen beheben — Sofortige Wirkung, keine Kosten, kein Risiko.
- Aufgeblähte Tabellen bereinigen —
ps_connections,ps_log,ps_mail, abgebrochene Warenkörbe. Sofortige Speicher- und Performance-Rückgewinnung. - InnoDB Buffer Pool tunen — Eine Einstellungsänderung in
my.cnf, massive Wirkung. - Fehlende Indizes auf Modultabellen hinzufügen — Hohe Wirkung, wenn Sie datenintensive Module verwenden.
- Redis für Sessions und Cache hinzufügen — Zuverlässiger Performance-Boden, eliminiert den Datei-I/O-Engpass.
- Full Page Cache implementieren — Der finale Multiplikator für Hochverkehrs-Shops.
Jeder Schritt baut auf dem vorherigen auf. Zu Schritt 6 zu springen, ohne die Schritte 1–4 erledigt zu haben, bedeutet auf wackeligem Fundament zu bauen.
Wenn Sie unsicher sind, wo Ihr Shop steht, beginnen Sie mit dem Slow Query Log. 24 Stunden Daten sagen Ihnen mehr als jedes Performance-Plugin jemals könnte. Und wenn Sie Hilfe bei der Interpretation brauchen, melden Sie sich — Datenbank-Performance-Analyse ist eines der Dinge, die wir am besten können.
David Miller entwickelt PrestaShop-Performance-Tools und optimiert E-Commerce-Datenbanken seit 2017. Seine Module sind verfügbar auf mypresta.rocks.
Kommentare (3)
Einen Kommentar hinterlassen