MySQL Performance Schema für tiefe Query-Analyse nutzen
AI generated
InnoDB
SQL
MySQL · Performance Schema · Diagnose
Performance Schema
Statement-, Wait- und Stage-Instrumentierung für tiefe Query-Analyse

Die Performance Schema misst, was in einer laufenden MySQL-Instanz tatsächlich passiert: welche Statements wie oft und wie lange laufen, an welchen Waits sie hängen und in welcher Stage sie ihre Zeit verbringen. Wer teure Query-Muster in einem Magento-Shop systematisch statt zufällig finden will, kommt an dieser Instrumentierung nicht vorbei.

11 Min. Lesezeit events_statements_summary_by_digest Statement Digests

1. Wie die Performance Schema MySQL instrumentiert

Die performance_schema-Datenbank wird zur Laufzeit von Messpunkten befüllt, die direkt im Server-Code eingebaut sind, nicht von einem extern angehängten Profiler. Jede dieser Messstellen heißt Instrument und deckt eine klar abgegrenzte Aktivität ab: ein Statement, ein Warten auf einen Mutex, einen Dateizugriff oder eine Speicherzuweisung. Instrumente sind hierarchisch benannt, etwa statement/sql/select oder wait/synch/mutex/innodb/buf_pool_mutex, sodass sich ganze Gruppen über Wildcards gezielt ein- oder ausschalten lassen.

Getrennt von den Instrumenten steuern Consumer, welche der gemessenen Rohdaten überhaupt in eine Tabelle geschrieben werden. Ein aktiviertes Instrument ohne aktivierten Consumer erzeugt zwar ein Ereignis, dieses wird aber nirgendwo gespeichert und verursacht kaum Kosten. Diese Zweiteilung erlaubt es, Messung und Speicherung unabhängig voneinander fein zu dosieren, statt pauschal alles mitzuschreiben oder alles abzuschalten.

2. Instrumente, Konsumenten und Akteure gezielt konfigurieren

Die Tabellen setup_instruments und setup_consumers steuern beide Ebenen über einfache Updates. In MySQL 8.0 sind Statement-Instrumente und deren Digest-Zusammenfassung standardmäßig aktiv, während viele Wait- und Stage-Instrumente bewusst deaktiviert bleiben, um die Grundlast niedrig zu halten. Wer tiefer diagnostizieren will, aktiviert gezielt die passenden Gruppen für die Dauer der Untersuchung und schaltet sie danach wieder ab.

Zusätzlich lässt sich über setup_actors festlegen, für welche Nutzer und Hosts überhaupt instrumentiert wird. In einem Magento-Setup mit mehreren Datenbankbenutzern, etwa einem Anwendungsuser und einem separaten Reporting-User, reduziert eine gezielte Filterung die Menge der erzeugten Ereignisse spürbar, ohne dass die eigentlich interessanten Verbindungen aus dem Blick geraten.


-- Statement-Digest bleibt aktiv (Standard), Wait-Instrumente
-- nur für die Dauer einer Diagnose-Session einschalten
UPDATE performance_schema.setup_instruments
SET ENABLED = 'YES', TIMED = 'YES'
WHERE NAME LIKE 'wait/synch/mutex/innodb/%';

UPDATE performance_schema.setup_consumers
SET ENABLED = 'YES'
WHERE NAME LIKE 'events_waits_%';

-- Nur den Anwendungsuser der Storefront instrumentieren
UPDATE performance_schema.setup_actors
SET ENABLED = 'YES', HISTORY = 'YES'
WHERE HOST = '%' AND USER = 'magento_app';

3. Das Digest-Modell hinter events_statements_summary_by_digest

Der Digest-Mechanismus normalisiert jedes ausgeführte Statement, indem er Literale durch Platzhalter ersetzt und Whitespace vereinheitlicht. Zwei Abfragen, die sich nur in der konkreten Produkt-ID oder dem Store-Code unterscheiden, landen dadurch unter demselben DIGEST-Hash und derselben DIGEST_TEXT. Genau das braucht man bei einer ORM-lastigen Anwendung wie Magento, die dieselbe logische Abfrage in unzähligen Parametervarianten ausführt, ohne dass jede einzelne davon als separater Eintrag erscheint.

Die Tabelle events_statements_summary_by_digest aggregiert pro Digest unter anderem COUNT_STAR, SUM_TIMER_WAIT, AVG_TIMER_WAIT, SUM_ROWS_EXAMINED, SUM_ROWS_SENT, SUM_NO_INDEX_USED und SUM_SELECT_FULL_JOIN. Aus diesen Spalten lässt sich ableiten, ob ein Query-Muster teuer ist, weil es oft läuft, weil eine einzelne Ausführung lange dauert, oder weil es unnötig viele Zeilen durchsucht, um am Ende nur wenige zurückzugeben.

4. Teure Query-Muster mit einer gezielten Abfrage identifizieren

Für die tägliche Diagnose reicht eine einzige Abfrage, die nach der aufsummierten Ausführungszeit sortiert. Die TIMER-Spalten liegen in Picosekunden vor und müssen für lesbare Werte umgerechnet werden. Wichtig ist, nicht nur nach der reinen Summe zu sortieren, sondern auch COUNT_STAR im Blick zu behalten: ein Muster mit moderater Einzeldauer, das aber hunderttausendfach pro Stunde läuft, verursacht in Summe oft mehr Serverlast als eine einzelne, seltene Report-Abfrage.

Ein zweiter, oft aufschlussreicherer Blick gilt dem Verhältnis von SUM_ROWS_EXAMINED zu SUM_ROWS_SENT. Weicht dieses Verhältnis stark voneinander ab und ist zusätzlich SUM_NO_INDEX_USED größer als null, deutet das fast immer auf einen fehlenden oder falsch entworfenen Index hin, den man gezielt mit EXPLAIN gegen genau diesen Digest-Text nachvollziehen kann.


SELECT
  DIGEST_TEXT,
  COUNT_STAR AS exec_count,
  ROUND(SUM_TIMER_WAIT / 1000000000000, 2) AS total_seconds,
  ROUND(AVG_TIMER_WAIT / 1000000000, 2) AS avg_ms,
  SUM_ROWS_EXAMINED,
  SUM_ROWS_SENT,
  SUM_NO_INDEX_USED
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 20;

5. Wait-Events: Contention auf Mutex- und I/O-Ebene sichtbar machen

Während Statement-Digests zeigen, welche Abfrage teuer ist, zeigen Wait-Events, warum sie wartet. Instrumente wie wait/synch/mutex/innodb/buf_pool_mutex oder wait/io/file/innodb/innodb_data_file messen interne Wartezeiten auf Locks, Mutexe und Dateizugriffe, aggregiert in events_waits_summary_global_by_event_name. Erst diese Ebene erklärt, ob eine langsame Abfrage tatsächlich an einer fehlenden Optimierung liegt oder an Contention auf einer gemeinsam genutzten internen Struktur, an der viele Threads gleichzeitig hängen.

Wait-Instrumente sind deutlich zahlreicher und feingranularer als Statement-Instrumente, weshalb sie im Regelfall deaktiviert bleiben. Sie gezielt für ein begrenztes Diagnosefenster einzuschalten und danach wieder abzuschalten, liefert die nötige Tiefe, ohne dass die Instrumentierung selbst zu einem dauerhaften Kostenfaktor auf einem stark ausgelasteten Produktivsystem wird.

6. Stage-Events: den Lebenszyklus eines Statements nachvollziehen

Stage-Events übernehmen die Rolle des inzwischen entfernten SHOW PROFILE und zeigen, in welcher Phase ein Statement seine Zeit verbringt, etwa starting, checking permissions, Sending data oder closing tables. Die Tabelle events_stages_history_long hält diese Phasen pro Thread vor und macht sichtbar, ob die gemessene Laufzeit tatsächlich in der Serverausführung liegt oder überwiegend im Versand großer Ergebnismengen an den Client.

Für Magento ist das besonders bei Export- und Report-Abfragen relevant, die große Datenmengen zurückgeben. Zeigt die Stage-Analyse, dass der Großteil der Zeit in Sending data verbracht wird, hilft eine schnellere Netzwerkverbindung oder ein schlankerer Result-Set mehr als eine weitere Index-Optimierung, die an der eigentlichen Ursache vorbeigeht.

7. Overhead-Abwägung: was volle Instrumentierung im Produktivbetrieb kostet

Die reine Statement-Digest-Instrumentierung ist in MySQL 8.0 standardmäßig aktiv und dank eines weitgehend sperrenfreien Designs mit einem einstelligen Prozentbereich an zusätzlicher CPU-Last verbunden, was für praktisch jeden Magento-Shop vertretbar ist. Anders sieht es aus, sobald zusätzlich events_statements_history_long sowie feingranulare Wait- und Stage-Instrumente vollständig aktiviert werden: Bei sehr hoher Query-Rate summiert sich der Overhead pro Ereignis spürbar auf und kann bei ohnehin CPU-gebundenen Systemen messbar ins Gewicht fallen.

Die pragmatische Empfehlung lautet deshalb, Digest-Aggregation dauerhaft laufen zu lassen, aber Wait- und Stage-Instrumentierung nur für begrenzte Diagnosefenster einzuschalten. Wer regelmäßig tief instrumentieren muss, sollte die zusätzliche Last vorher auf einem Staging-System mit realistischer Last messen, statt sich auf pauschale Prozentangaben aus der Dokumentation zu verlassen, da der tatsächliche Effekt stark von Hardware und Query-Mix abhängt.

8. Sizing, Persistenz und der richtige Umgang mit einem Digest-Reset

Die Digest-Tabelle ist über performance_schema_digest_size in ihrer Größe begrenzt. Ist sie voll, werden neue, bisher unbekannte Digests unter einem generischen Overflow-Eintrag zusammengefasst, wodurch genau die Granularität verloren geht, die man für eine saubere Analyse braucht. Auf einem Shop mit vielen unterschiedlichen Query-Formen, etwa durch dynamische Layered-Navigation-Filter, lohnt sich ein bewusst höher gesetzter Wert statt der automatischen Server-Standardgröße.

Alle Performance-Schema-Daten sind rein speicherresident und überstehen keinen Neustart. Für einen sauberen Vorher-Nachher-Vergleich, etwa vor und nach einem Deployment oder einem Lasttest, empfiehlt sich ein expliziter TRUNCATE TABLE auf die relevanten Summary-Tabellen unmittelbar vor dem Testlauf, damit alte Messwerte die neue Auswertung nicht verwässern.


-- Digest-Statistiken vor einem gezielten Lasttest zuruecksetzen
TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;

-- Größe der Digest-Tabelle dauerhaft über die Konfigurationsdatei
-- anheben (wirkt erst nach einem Neustart):
-- performance_schema_digest_size = 20000

9. Praxisbeispiel: teuerste Kategorie- und Produktabfragen in Magento finden

In der Praxis filtert man den Digest-Report zusätzlich auf Tabellennamen, die typische Magento-Hotspots betreffen, etwa catalog_product_entity, catalog_category_product oder sales_order_grid. So lassen sich während eines Lastspitzen-Fensters, etwa an einem Aktionstag, gezielt jene Query-Muster herausfiltern, die für den größten Anteil der aufsummierten Datenbankzeit verantwortlich sind, statt sich durch tausende irrelevante Einzeleinträge zu arbeiten.

Kombiniert man diese Filterung mit dem Verhältnis von untersuchten zu zurückgegebenen Zeilen, entsteht eine klare Priorisierung: Muster mit hohem SUM_NO_INDEX_USED-Wert und schlechtem Zeilenverhältnis sind fast immer echte Indexlücken und lassen sich schnell beheben, während Muster mit gutem Verhältnis, aber hoher Ausführungshäufigkeit eher Kandidaten für Caching oder eine Reduktion der Aufrufhäufigkeit im Anwendungscode sind.


SELECT DIGEST_TEXT, COUNT_STAR, SUM_NO_INDEX_USED,
       ROUND(AVG_TIMER_WAIT / 1000000000, 2) AS avg_ms
FROM performance_schema.events_statements_summary_by_digest
WHERE DIGEST_TEXT LIKE '%catalog_product_entity%'
   OR DIGEST_TEXT LIKE '%catalog_category_product%'
ORDER BY AVG_TIMER_WAIT DESC
LIMIT 15;
Ebene Beispiel-Instrument Consumer-Tabelle Typischer Einsatz
Statement statement/sql/select events_statements_summary_by_digest Teure Query-Muster über Zeit aggregieren
Wait wait/synch/mutex/innodb/... events_waits_summary_global_by_event_name Interne Lock- und Mutex-Contention finden
Stage stage/sql/Sending data events_stages_history_long Nachvollziehen, wohin Ausführungszeit fließt
Memory memory/innodb/buf_buf_pool memory_summary_global_by_event_name Speicherverbrauch einzelner Subsysteme prüfen

Mironsoft

Datenbank-Performance, Index-Tuning und Magento-DB-Optimierung

Magento-Shop, der an langsamen Datenbankabfragen leidet?

Wir analysieren MySQL-Datenbanken auf Performance-Bremsen, optimieren Indizes und Abfragen gezielt und richten Backup- und Replikationsstrategien ein, die im Ernstfall wirklich funktionieren.

Performance-Audit

Slow Query Log und Explain-Pläne systematisch auf Engpässe untersuchen.

Index-Optimierung

Indizes gezielt für die tatsächliche Abfragelast des Shops aufbauen.

Backup-Strategie

Zuverlässige Backup- und Restore-Prozesse für produktive Magento-Datenbanken einrichten.

10. Zusammenfassung

Performance Schema für Query-Analyse: Das Wichtigste auf einen Blick

Zwei-Ebenen-Modell

Instrumente messen Rohereignisse, Consumer entscheiden, ob und wo diese Daten gespeichert werden, beides getrennt konfigurierbar.

Digest-Aggregation

events_statements_summary_by_digest normalisiert Literale und fasst gleichartige Abfragen zu einem auswertbaren Muster zusammen.

Overhead

Statement-Digests sind dauerhaft günstig, Wait- und Stage-Instrumentierung gehören in ein begrenztes Diagnosefenster.

Sizing

Digest-Tabellengröße bewusst dimensionieren und vor gezielten Tests mit TRUNCATE einen sauberen Nullpunkt schaffen.

11. FAQ: Performance Schema für Query-Analyse: Das Wichtigste auf einen Blick

1Was ist der Unterschied zwischen einem Instrument und einem Consumer?
Ein Instrument misst eine bestimmte Aktivität wie ein Statement oder einen Mutex-Wait. Ein Consumer entscheidet, ob diese Messung tatsächlich in eine Tabelle geschrieben wird. Beide lassen sich unabhängig voneinander aktivieren.
2Warum sind Literale in DIGEST_TEXT durch Platzhalter ersetzt?
Damit strukturell identische Abfragen mit unterschiedlichen Parametern, wie verschiedenen Produkt-IDs, unter demselben Digest aggregiert werden, statt als separate Einträge zu erscheinen.
3In welcher Einheit liegen die TIMER-Spalten vor?
In Picosekunden. Für lesbare Sekunden- oder Millisekundenwerte muss durch 1000000000000 beziehungsweise 1000000000 geteilt werden.
4Ist die Performance Schema standardmäßig aktiv?
Statement-Digests sind in MySQL 8.0 standardmäßig aktiv. Viele Wait- und Stage-Instrumente sind dagegen standardmäßig deaktiviert und müssen gezielt eingeschaltet werden.
5Wie hoch ist der Overhead der vollen Instrumentierung?
Statement-Digests liegen im einstelligen Prozentbereich. Volle Wait- und Stage-Instrumentierung bei sehr hoher Query-Rate kann spürbar mehr kosten und sollte nur zeitlich begrenzt aktiv sein.
6Was passiert, wenn die Digest-Tabelle voll ist?
Neue, unbekannte Digests werden unter einem generischen Overflow-Eintrag zusammengefasst, wodurch die Granularität für neue Query-Muster verloren geht. performance_schema_digest_size sollte entsprechend dimensioniert werden.
7Überstehen Performance-Schema-Daten einen Neustart?
Nein, alle Daten liegen ausschließlich im Speicher und gehen bei einem Neustart verloren. Für Vorher-Nachher-Vergleiche eignet sich stattdessen ein gezielter TRUNCATE vor dem Testlauf.
8Wie finde ich Queries mit fehlendem Index?
Über die Spalte SUM_NO_INDEX_USED in events_statements_summary_by_digest, kombiniert mit einem ungünstigen Verhältnis von SUM_ROWS_EXAMINED zu SUM_ROWS_SENT.
9Ersetzt die Performance Schema EXPLAIN?
Nein, sie ergänzt EXPLAIN. Die Performance Schema zeigt, welche Query-Muster über Zeit am teuersten sind, EXPLAIN erklärt dann, warum ein konkreter Ausführungsplan so aussieht.
10Kann ich die Instrumentierung auf einen einzelnen Datenbankuser begrenzen?
Ja, über die Tabelle setup_actors lässt sich festlegen, für welche Nutzer und Hosts überhaupt Ereignisse erzeugt werden, was den Overhead in Multi-User-Umgebungen reduziert.