{"id":18593,"date":"2026-03-31T18:23:38","date_gmt":"2026-03-31T16:23:38","guid":{"rendered":"https:\/\/webhosting.de\/mysql-slow-query-log-hosting-analysieren-queryperf\/"},"modified":"2026-03-31T18:23:38","modified_gmt":"2026-03-31T16:23:38","slug":"mysql-langsom-foresporgselslog-hosting-analyse-queryperf","status":"publish","type":"post","link":"https:\/\/webhosting.de\/da\/mysql-slow-query-log-hosting-analysieren-queryperf\/","title":{"rendered":"Analyser MySQL's log over langsomme foresp\u00f8rgsler i hosting: Tips til optimering"},"content":{"rendered":"<p><strong>MySQL Slow Query Log<\/strong> zeigt mir im Hosting, welche Abfragen Zeit fressen, wie oft sie auftreten und warum sie ausbremsen. Ich zeige dir konkrete Schritte, wie du den Log aktivierst, auswertest und Queries so umbaust, dass Seiten schneller laden und Serverressourcen effizienter arbeiten.<\/p>\n\n<h2>Zentrale Punkte<\/h2>\n<ul>\n  <li><strong>Aktivierung<\/strong> und Schwellenwerte sinnvoll setzen<\/li>\n  <li><strong>Auswertung<\/strong> mit pt-query-digest und mysqldumpslow<\/li>\n  <li><strong>Metriken<\/strong> interpretieren: Query_time, Lock_time, Rows_examined<\/li>\n  <li><strong>Tuning<\/strong> durch Indizes, EXPLAIN und Rewrites<\/li>\n  <li><strong>Automatisierung<\/strong> und Monitoring im Hosting<\/li>\n<\/ul>\n\n<h2>Was leistet das Slow Query Log im Hosting?<\/h2>\n<p><strong>Hosting<\/strong> bedeutet geteilte Ressourcen, deshalb z\u00e4hlt jede Millisekunde pro Query. Ich nutze den Log, um Abfragen zu finden, die l\u00e4nger als einen definierten Grenzwert laufen, und sehe zu jeder Query Kennzahlen wie Query_time, Lock_time, Rows_sent und Rows_examined. Diese Zahlen zeigen mir, ob ein fehlender Index, ein ung\u00fcnstiger Join oder ein Full Table Scan dahinter steckt. Gerade auf Servern mit mehreren Sites kann eine einzige schlechte Abfrage CPU und I\/O stark beanspruchen. Ich priorisiere dann die Queries mit der h\u00f6chsten Gesamtzeit, weil dort die gr\u00f6\u00dfte Hebelwirkung auf Ladezeit und Serverlast liegt.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql-query-analysieren-4623.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Aktivierung und sinnvolle Schwellenwerte<\/h2>\n<p><strong>Start<\/strong>en kann ich runtime oder dauerhaft \u00fcber my.cnf, je nach Zugriff im Hosting. F\u00fcr schnelle Tests schalte ich den Log tempor\u00e4r ein und setze long_query_time auf einen Wert, der zu Traffic und Hardware passt. Ich gehe f\u00fcr stark genutzte Sites oft auf 0.1 Sekunden, beobachte aber die Loggr\u00f6\u00dfe, damit I\/O nicht unn\u00f6tig w\u00e4chst. Wenn direkte Dateizugriffe limitiert sind, verwende ich die Performance Schema Optionen der MySQL Shell, um Berichte zu erzeugen. Nach dem Feintuning schreibe ich die finalen Einstellungen in die Konfigurationsdatei und starte den Dienst neu.<\/p>\n<pre><code>SET GLOBAL slow_query_log = 'ON';\nSET GLOBAL long_query_time = 1;\nSET GLOBAL slow_query_log_file = '\/var\/log\/mysql\/slow-query.log';\nSET GLOBAL log_queries_not_using_indexes = 'ON';\n\nSHOW VARIABLES LIKE 'slow_query%';\nSHOW VARIABLES LIKE 'long_query_time';\n<\/code><\/pre>\n<p><strong>Dauerhaft<\/strong> setze ich Optionen wie log_throttle_queries_not_using_indexes und log_slow_admin_statements, damit der Log n\u00fctzlich bleibt und nicht explodiert. Ich dokumentiere jeden Wert, zum Beispiel warum long_query_time 0.5 oder 0.1 Sekunden betr\u00e4gt. So kann ich sp\u00e4ter fundiert nachsch\u00e4rfen. In Shared-Umgebungen spreche ich die Freischaltung oft mit dem Anbieter ab oder nutze dessen Panel. Jede Aktivierung verkn\u00fcpfe ich mit einem Startdatum, um Effekte in Monitoring und Metriken sauber vergleichen zu k\u00f6nnen.<\/p>\n<pre><code>[mysqld]\nslow_query_log = 1\nslow_query_log_file = \/var\/log\/mysql\/slow-query.log\nlong_query_time = 1\nlog_queries_not_using_indexes = 1\nlog_throttle_queries_not_using_indexes = 10\nlog_slow_admin_statements = 1\n<\/code><\/pre>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql_besprechung_log_9537.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Slow-Log effektiv auswerten<\/h2>\n<p><strong>Rohdaten<\/strong> sind laut, deshalb fasse ich sie mit pt-query-digest zusammen und sortiere nach Gesamtzeit \u00fcber einen sinnvollen Zeitraum. So erkenne ich Muster, hoch variable Abfragen und Query-Familien, die nur durch Parameter variieren. Ich pr\u00fcfe die Verteilung, nicht nur den Durchschnitt, denn Ausrei\u00dfer erzeugen echte Nutzerprobleme. F\u00fcr einen schnellen \u00dcberblick hilft mir mysqldumpslow, um die zehn langsamsten Gruppen zu sehen. Mehr Tiefe hole ich mir \u00fcber Zeitfenster, Datenbank-Filter und einen Export in eine Textanalyse.<\/p>\n<pre><code>pt-query-digest \/var\/log\/mysql\/slow-query.log\npt-query-digest --since '24h' \/var\/log\/mysql\/slow-query.log\nmysqldumpslow -s t -t 10 \/var\/log\/mysql\/slow-query.log\n<\/code><\/pre>\n<p><strong>N\u00fctzlich<\/strong> ist zus\u00e4tzlich ein Blick in andere Protokolle, wenn Anwendungs- oder PHP-Funktionen ins Spiel kommen. Daf\u00fcr greife ich auf bestehende Log-Workflows zur\u00fcck und b\u00fcndele die Ergebnisse. Einen Einstieg bietet mir oft dieser Leitfaden: <a href=\"https:\/\/webhosting.de\/hosting-logs-analyse-fehleranalyse-performance-insights\/\">Logs analysieren<\/a>. Ich synchronisiere die Zeitstempel, damit ich Spitzen im Traffic mit Query-Spitzen abgleiche. So sehe ich, ob Cache-Misses, Cronjobs oder Import-Jobs die Datenbank zur gleichen Zeit beanspruchen.<\/p>\n\n<h2>Metriken richtig interpretieren<\/h2>\n<p><strong>Query_time<\/strong> zeigt mir die reine Laufzeit; ich priorisiere Queries \u00fcber einer Sekunde zuerst. Lock_time weist auf Wartezeiten durch Sperren hin, die oft aus unn\u00f6tig langen Transaktionen oder gro\u00dfen Batches stammen. Das Verh\u00e4ltnis Rows_examined zu Rows_sent verr\u00e4t mir, ob Abfragen zu viele Zeilen sichten und Indizes fehlen. Wenn der Log viele &#8222;No index use&#8220;-Eintr\u00e4ge enth\u00e4lt, setze ich das Throttling und schaue mir die betroffenen Tabellen genauer an. Wichtig bleibt, stets Ursache statt Symptom anzugehen: Ein Index auf die richtige Spalte schl\u00e4gt jedes Hardware-Upgrade.<\/p>\n<table>\n  <thead>\n    <tr>\n      <th><strong>Metrik<\/strong><\/th>\n      <th><strong>Was ich sehe<\/strong><\/th>\n      <th><strong>Ma\u00dfnahme<\/strong><\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>Query_time hoch<\/td>\n      <td>Lange Laufzeit pro Ausf\u00fchrung<\/td>\n      <td>EXPLAIN pr\u00fcfen, Abfrage umschreiben, Index erg\u00e4nzen<\/td>\n    <\/tr>\n    <tr>\n      <td>Lock_time hoch<\/td>\n      <td>Wartezeit auf Sperren<\/td>\n      <td>Transaktionen k\u00fcrzen, Batch-Gr\u00f6\u00dfe reduzieren, passende Isolation<\/td>\n    <\/tr>\n    <tr>\n      <td>Rows_examined \u226b Rows_sent<\/td>\n      <td>Zu viel gescannt, wenig zur\u00fcckgegeben<\/td>\n      <td>Filterspalten indexieren, Sargability herstellen<\/td>\n    <\/tr>\n    <tr>\n      <td>Kein Index genutzt<\/td>\n      <td>Full Table Scan<\/td>\n      <td>Index erstellen, Ausdruck in WHERE vermeiden<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n<p><strong>Grenzwerte<\/strong> passe ich nach der ersten Woche an, damit ich nicht im Rauschen versinke. Ich senke long_query_time in Stufen, bis ich genug Treffer f\u00fcr systematische Verbesserungen habe. Jede Anpassung dokumentiere ich mit Datum und Grund. So bleibt die Auswertung fokussiert. Werthaltige Treffer ersparen mir sp\u00e4ter doppelte Arbeit.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql-query-optimization-tips-2478.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Praxis: Query Tuning Schritt f\u00fcr Schritt<\/h2>\n<p><strong>EXPLAIN<\/strong> ist mein Start, bevor ich Code \u00e4ndere. Ich suche nach &#8222;type: ALL&#8220;, &#8222;rows&#8220; mit gro\u00dfen Zahlen und &#8222;Using filesort&#8220; oder &#8222;Using temporary&#8220;. Funktionen auf Spalten in WHERE oder JOIN verhindern oft Index-Nutzung. Stattdessen formuliere ich sargable Bedingungen und pr\u00fcfe dann den neuen Plan. Jeder Schritt muss die Zeilenreduktion fr\u00fch und zielgerichtet leisten.<\/p>\n<pre><code>EXPLAIN SELECT * FROM orders WHERE YEAR(created_at) = 2026;\n\n-- Besser:\nCREATE INDEX idx_orders_created ON orders(created_at);\nSELECT * FROM orders\nWHERE created_at &gt;= '2026-01-01' AND created_at &lt; '2027-01-01';\n<\/code><\/pre>\n<p><strong>JOINs<\/strong> optimiere ich, indem ich die Join-Reihenfolge und passende Indizes auf Join-Schl\u00fcsseln kontrolliere. Ich pr\u00fcfe, ob ein Composite-Index WHERE + ORDER BY abdeckt, um Filesort zu vermeiden. LIMIT setze ich, wo nur eine Vorschau n\u00f6tig ist. Ergebnis-Caching auf Applikationsebene spare ich mir f\u00fcr wiederholte, identische Abfragen mit geringer \u00c4nderungsrate. Eine tiefergehende Einf\u00fchrung in Indizes und Sperren findest du hier: <a href=\"https:\/\/webhosting.de\/datenbank-performance-abfragen-indizes-locking-serverboost\/\">Indizes und Locking<\/a>.<\/p>\n\n<h2>Index-Strategien f\u00fcr CMS und Shops<\/h2>\n<p><strong>WordPress<\/strong>, WooCommerce oder Shop-Systeme erzeugen typische Muster: viel Lesen, punktuell Schreiben, oft mit Meta- oder Produkt-Tabellen. Ich analysiere die h\u00e4ufigsten Routen \u2013 Startseite, Kategorie, Suche, Checkout \u2013 und lege Indizes gezielt auf Filter-, Sortier- und Join-Spalten. Covering-Indizes (z. B. (status, created_at, id)) sparen viele R\u00fcckgriffe auf die Tabelle. F\u00fcr Suchen auf Pr\u00e4fixe nutze ich geeignete Indexformen oder Fulltext, statt LIKE &#8218;%wort%&#8216;. Jede Index\u00e4nderung messe ich vor und nach dem Livegang mit denselben Lastprofilen.<\/p>\n<p><strong>Wachstum<\/strong> in Datenmengen pr\u00fcfe ich \u00fcber Kardinalit\u00e4t und Histogramme, damit ich nicht auf seltene Werte indexiere. Ich halte die Anzahl der Indizes schlank, um Schreiblast und Speicherbedarf im Griff zu behalten. Konsolidierte Composite-Indizes ersetzen mehrere Einzelindizes. Ich reguliere Autovacuum-\u00e4hnliche Aufgaben in MySQL durch regelm\u00e4\u00dfige Analyse und Rebuilds nur bei Bedarf. So bleibt der Optimizer verl\u00e4sslich.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql_query_log_analyse_4891.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Servereinstellungen, Caching und Speicher<\/h2>\n<p><strong>InnoDB<\/strong> Buffer Pool Gr\u00f6\u00dfe bestimme ich anhand aktiver Datens\u00e4tze und Indexgr\u00f6\u00dfen, nicht nach Pauschalwerten. Ich erh\u00f6he ihn, bis die Working Set Size weitgehend im Speicher liegt und die Page Miss Rate f\u00e4llt. tmp_table_size und max_heap_table_size setze ich so, dass weniger tempor\u00e4re Tabellen auf Disk landen. F\u00fcr Schreibsicherheit und Latenz balanciere ich innodb_flush_log_at_trx_commit sinnvoll zur Anwendung. Auf Applikationsebene cache ich h\u00e4ufige Ergebnisse und nutze HTTP-Caching, damit die Datenbank weniger Anfragen sieht.<\/p>\n<p><strong>Hardware<\/strong> und Netzwerkeffekte beziehe ich in die Diagnose ein: Langsame Storage-I\/O oder \u00fcberlastete CPU sp\u00fcren Queries sofort. Ich messe deshalb IO-wait parallel zu den Datenbankmetriken. Wer mehr Reserven braucht, plant vertikale oder horizontale Skalierung mit messbarem Ziel. Eine kompakte \u00dcbersicht zu Engp\u00e4ssen, Tuning und Ressourcen liefert dir dieser Leitfaden: <a href=\"https:\/\/webhosting.de\/mysql-performance-optimieren-probleme-tipps-hardware-skalierung-cache-speed\/\">Hardware und Cache<\/a>. So stelle ich sicher, dass ich nicht blind am falschen Regler drehe.<\/p>\n\n<h2>Concurrency und Locking im Hosting<\/h2>\n<p><strong>Lock_time<\/strong> w\u00e4chst, wenn lange Transaktionen viele Zeilen ber\u00fchren oder wenn Aufr\u00e4umjobs zur Hauptzeit laufen. Ich k\u00fcrze Schreibvorg\u00e4nge, splitte gro\u00dfe Updates in kleinere Batches und reduziere so die Haltezeit von Sperren. Geeignete Isolation Levels senken Konflikte, ohne Datenkonsistenz zu gef\u00e4hrden. Hotspots entlaste ich mit sekund\u00e4ren Indizes und passenden WHERE-Bedingungen, damit weniger Zeilen betroffen sind. Hintergrundjobs plane ich in verkehrsarmen Zeitfenstern, damit Nutzeraktionen Vorrang bekommen.<\/p>\n<p><strong>Deadlocks<\/strong> untersuche ich anhand wiederkehrender Muster: gleiche Tabellen, wechselnde Reihenfolge, identische Zeilen. Ich vereinheitliche die Zugriffsreihenfolge in Code und Stored Procedures. Retry-Logik mit Jitter l\u00f6st tempor\u00e4re Kollisionen. Wo m\u00f6glich, isoliere ich teuerste Operationen in Job-Queues. So sinkt die Varianz sp\u00fcrbar und die gef\u00fchlte Performance steigt.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql-slow-query-log-3842.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Automatisierte Alarme und Workflows<\/h2>\n<p><strong>Routine<\/strong> schl\u00e4gt Aktionismus: Ich werte den Log t\u00e4glich oder w\u00f6chentlich aus, je nach Traffic und Release-Frequenz. Ein kleines Skript z\u00e4hlt neue Treffer in den letzten Minuten und schickt mir eine E-Mail, wenn der Schwellwert steigt. Zus\u00e4tzlich generiere ich regelm\u00e4\u00dfige pt-query-digest Reports und halte die Top-10 immer im Blick. Release-Tage begleite ich mit engerem Monitoring. So erkenne ich Regressionen, bevor Nutzer sie merken.<\/p>\n<pre><code>#!\/bin\/bash\nLOG_FILE=\"\/var\/log\/mysql\/slow-query.log\"\nTHRESHOLD=100\nRECENT_COUNT=$(awk -v cutoff=\"$(date -d '5 minutes ago' '+%Y-%m-%dT%H:%M')\" '\/^# Time:\/ { if ($3 &gt;= cutoff) count++ } END { print count+0 }' \"$LOG_FILE\")\nif [ \"$RECENT_COUNT\" -gt \"$THRESHOLD\" ]; then\n    echo \"ALERT: $RECENT_COUNT slow queries\" | mail -s \"MySQL Alert\" admin@example.com\nfi\n<\/code><\/pre>\n<p><strong>Transparenz<\/strong> schaffe ich mit klaren Zust\u00e4ndigkeiten: Wer reagiert bei Peaks, wer passt Indizes an, wer testet Releases. Ich fasse Ergebnisse in kurzen Changelogs zusammen. So versteht jedes Teammitglied, warum eine \u00c4nderung kam und welche Wirkung sie hatte. Ein strukturierter Ablauf spart Zeit und verhindert Fehlalarme.<\/p>\n\n<h2>Fehlerbilder und schnelle Korrekturen<\/h2>\n<p><strong>Full<\/strong> Table Scans l\u00f6sen \u00fcberproportional viel Last aus. Ich pr\u00fcfe zuerst, ob ein passender Index auf der Filterspalte fehlt oder ob ein Ausdruck den Index blockiert. Hohe Lock_time beseitige ich, indem ich Transaktionen k\u00fcrze und konkurrierende Operationen entzerre. \u00dcberlaufende Logs entsch\u00e4rfe ich mit log_throttle_queries_not_using_indexes und einem realistischen long_query_time. Jede Korrektur messe ich sofort gegen die urspr\u00fcnglichen Zahlen, damit Erfolge sichtbar bleiben.<\/p>\n<p><strong>Storage<\/strong>-Engp\u00e4sse erkenne ich an steigender IO-wait und hoher Disk-Latenz w\u00e4hrend Query-Spitzen. Ich reduziere dann unn\u00f6tige Schreibvorg\u00e4nge, etwa durch selteneres Aktualisieren unver\u00e4nderlicher Felder. Wenn Tabellen wachsen, plane ich Archivierung oder Partitionsstrategien, damit Hot Data im Speicher bleibt. F\u00fcr Admin-Statements im Peak schalte ich log_slow_admin_statements, um stille Kostentreiber zu identifizieren. Kleine, gezielte Fixes zahlen sich hier schneller aus als gro\u00dfe Umbauten.<\/p>\n\n<!-- ERWEITERUNG: Vertiefende Abschnitte -->\n\n<h2>Besonderheiten in Managed- und Cloud-Umgebungen<\/h2>\n<p><strong>Managed Hosting<\/strong> oder Cloud-Dienste begrenzen oft Dateizugriffe. In solchen F\u00e4llen stelle ich log_output auf TABLE und werte den Slow Log direkt aus der Datenbank aus. In MySQL 8.0 nutze ich zus\u00e4tzlich SET PERSIST, um Einstellungen ohne direkten Zugriff auf my.cnf dauerhaft zu setzen. In Cloud-Parametergroups (z. B. bei verwalteten Diensten) trage ich die gleichen Variablen ein und plane ein Wartungsfenster f\u00fcr den Neustart.<\/p>\n<pre><code>-- Wenn erlaubt: Persistente Einstellungen ohne Neustart\nSET PERSIST slow_query_log = ON;\nSET PERSIST long_query_time = 0.5;\nSET PERSIST log_output = 'TABLE';  -- Alternative zu FILE bei eingeschr\u00e4nktem Dateizugriff\n\n-- Auswertung bei log_output=TABLE\nSELECT start_time, user_host, query_time, lock_time, rows_sent, rows_examined, sql_text\nFROM mysql.slow_log\nORDER BY query_time DESC\nLIMIT 50;\n<\/code><\/pre>\n<p><strong>Hinweis<\/strong>: Bei starkem Traffic kann log_output=FILE performanter sein, da Tabellenlogging zus\u00e4tzlichen Overhead erzeugt. In restriktiven Umgebungen ist TABLE jedoch oft der einzige Weg. Ich setze dann engere Grenzwerte (z. B. min_examined_row_limit), um das Volumen kontrollierbar zu halten.<\/p>\n\n<h2>Rotation, Aufbewahrung und Datenschutz<\/h2>\n<p><strong>Rotation<\/strong> verhindert, dass Logs die Platte f\u00fcllen. Ich rotiere t\u00e4glich oder nach Gr\u00f6\u00dfe, komprimiere Altdateien und halte eine klare Aufbewahrungsstrategie ein (z. B. 14 Tage). Nach der Rotation triggere ich einen Log-Flush, damit MySQL sauber in die neue Datei schreibt. So bleiben Analyse und Betrieb stabil.<\/p>\n<pre><code># \/etc\/logrotate.d\/mysql-slow\n\/var\/log\/mysql\/slow-query.log {\n  daily\n  rotate 14\n  size 100M\n  compress\n  missingok\n  notifempty\n  create 640 mysql adm\n  postrotate\n    test -x \/usr\/bin\/mysqladmin || exit 0\n    \/usr\/bin\/mysqladmin flush-logs\n  endscript\n}\n<\/code><\/pre>\n<p><strong>Datenschutz<\/strong> ist Pflicht: Slow Logs k\u00f6nnen Parameterwerte enthalten. Ich limitiere den Zugriff strikt (Dateirechte, Gruppen) und pr\u00fcfe, ob sensible Daten geloggt werden. Bei Bedarf arbeite ich mit Parameterbindung in der Anwendung, damit im Log keine personenbezogenen Klartexte auftauchen. F\u00fcr Teamfreigaben teile ich bevorzugt aggregierte Reports statt Rohlogs.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/03\/mysql-log-analyse-7472.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Performance Schema und sys Schema nutzen<\/h2>\n<p><strong>Performance Schema<\/strong> liefert Metriken auch ohne aktivierten Slow Log. Ich aktiviere die relevanten Consumer f\u00fcr Statements und werte dann die sys-Views aus. Vorteil: Ich sehe Top-Digests und Latenzverteilung nahezu in Echtzeit, gruppiert \u00fcber \u00e4hnliche Queries hinweg.<\/p>\n<pre><code>-- Consumer f\u00fcr Statement-Historie aktivieren (soweit zur Laufzeit m\u00f6glich)\nUPDATE performance_schema.setup_consumers\nSET ENABLED = 'YES'\nWHERE NAME IN ('events_statements_history', 'events_statements_history_long');\n\n-- Schneller \u00dcberblick \u00fcber teure Query-Gruppen\nSELECT schema_name, digest_text, count_star,\n       ROUND(sum_timer_wait\/1e12, 3) AS total_s,\n       ROUND(avg_timer_wait\/1e9, 3)  AS avg_ms,\n       ROUND(max_timer_wait\/1e9, 3)  AS pmax_ms\nFROM sys.statement_analysis\nORDER BY sum_timer_wait DESC\nLIMIT 10;\n<\/code><\/pre>\n<p><strong>Kombination<\/strong> aus Slow Log (langsame Ausrei\u00dfer) und Performance Schema (Breite, H\u00e4ufigkeit) zeigt mir sowohl Einzelf\u00e4lle als auch systematische Kostentreiber. Ich gleiche beide Sichten mit Trafficmustern ab, um priorisierte To-dos zu erstellen.<\/p>\n\n<h2>EXPLAIN ANALYZE und Optimizer Trace<\/h2>\n<p><strong>EXPLAIN ANALYZE<\/strong> (ab MySQL 8.0.18) erg\u00e4nzt Sch\u00e4tzungen um gemessene Zeiten. Ich vergleiche Zeilenabsch\u00e4tzungen mit tats\u00e4chlichen Werten und decke Fehleinsch\u00e4tzungen des Optimizers auf. Bei widerspr\u00fcchlichen Pl\u00e4nen analysiere ich den Optimizer Trace, um zu sehen, warum ein Index nicht gew\u00e4hlt wurde.<\/p>\n<pre><code>-- Plan mit Messwerten\nEXPLAIN ANALYZE\nSELECT o.id, o.created_at\nFROM orders o\nJOIN customers c ON c.id = o.customer_id\nWHERE c.country = 'DE' AND o.status = 'paid'\nORDER BY o.created_at DESC\nLIMIT 50;\n\n-- Optimizer-Entscheidungen nachvollziehen\nSET optimizer_trace=\"enabled=on\";\nSELECT ...;  -- zu untersuchende Abfrage\nSELECT TRACE FROM information_schema.OPTIMIZER_TRACE\\G\nSET optimizer_trace=\"enabled=off\";\n<\/code><\/pre>\n<p><strong>Ergebnis<\/strong>: Wenn Sch\u00e4tzungen stark danebenliegen, aktualisiere ich Statistiken (ANALYZE TABLE), erg\u00e4nze Histogramme oder forme Indizes\/Abfragen so um, dass Selektivit\u00e4t fr\u00fch greift.<\/p>\n\n<h2>Rewrite-Muster, die fast immer wirken<\/h2>\n<p><strong>OR zu UNION ALL<\/strong>: Mehrere OR-Bedingungen auf verschiedenen Spalten verhindern oft Index-Nutzung. Ich trenne sie in zwei selektive Abfragen und vereinige die Ergebnisse, sofern sich Duplikate ausschlie\u00dfen lassen.<\/p>\n<pre><code>-- Vorher:\nSELECT * FROM t WHERE a = ? OR b = ?;\n\n-- Besser:\n(SELECT * FROM t WHERE a = ?)\nUNION ALL\n(SELECT * FROM t WHERE b = ? AND a &lt;&gt; ?);\n<\/code><\/pre>\n<p><strong>Paginierung<\/strong>: OFFSET\/LIMIT wird mit wachsendem OFFSET teuer. Ich steige auf Keyset Pagination um und nutze einen geeigneten Sortierschl\u00fcssel (idealerweise indexiert und monoton).<\/p>\n<pre><code>-- Teuer:\nSELECT id, title FROM posts ORDER BY created_at DESC LIMIT 50 OFFSET 5000;\n\n-- Besser (Keyset):\nSELECT id, title\nFROM posts\nWHERE created_at &lt; :cursor\nORDER BY created_at DESC\nLIMIT 50;\n<\/code><\/pre>\n<p><strong>Composite-Indizes<\/strong>: Reihenfolge z\u00e4hlt. Ich sortiere Spalten im Index nach Selektivit\u00e4t und Query-Muster (WHERE-Filter zuerst, dann Sortierspalten). Ziel ist ein Covering-Index, der Filesort und Table-Lookups vermeidet.<\/p>\n\n<h2>Funktionale und generierte Indizes in MySQL 8<\/h2>\n<p><strong>Ausdr\u00fccke<\/strong> in WHERE\/JOIN blockieren h\u00e4ufig Indizes. In MySQL 8.0 indexiere ich gezielt Ausdr\u00fccke oder arbeite mit generierten Spalten, um Sargability herzustellen. Das lohnt sich besonders bei CASTs f\u00fcr numerische Metawerte oder JSON-Feldern.<\/p>\n<pre><code>-- Beispiel: numerische Sortierung auf Textfeld\nALTER TABLE product ADD COLUMN price_num DECIMAL(10,2)\n  GENERATED ALWAYS AS (CAST(price AS DECIMAL(10,2))) STORED;\nCREATE INDEX idx_product_price_num ON product(price_num);\n\n-- Query ohne CAST und mit Index\nSELECT * FROM product\nWHERE price_num BETWEEN 10 AND 50\nORDER BY price_num;\n<\/code><\/pre>\n<p><strong>Praxis<\/strong>: Ich teste, ob der neue Index wirklich zieht (EXPLAIN) und messe die Auswirkung im Slow Log. Generierte Spalten helfen auch, Pr\u00e4fixe oder normalisierte Varianten (LOWER(email)) effizient zu filtern.<\/p>\n\n<h2>CMS-\/Shop-Patterns noch gezielter angehen<\/h2>\n<p><strong>Meta-Tabellen<\/strong> (z. B. wp_postmeta) profitieren von kombinierten Indizes auf (post_id, meta_key) bzw. (meta_key, meta_value). F\u00fcr h\u00e4ufige Filter auf meta_value_numeric nutze ich generierte Spalten wie oben, statt in jeder Query zu CASTen. Suchseiten beschleunige ich, indem ich Redundanzen ablege (Denormalisierung light) und den Lesezugriff indexfreundlich gestalte.<\/p>\n<pre><code>-- WordPress-typisch: schneller Zugriff auf Meta-Daten eines Beitrags\nCREATE INDEX idx_postmeta_postid_metakey ON wp_postmeta(post_id, meta_key);\nCREATE INDEX idx_postmeta_metakey_metavalue ON wp_postmeta(meta_key, meta_value(100));\n<\/code><\/pre>\n<p><strong>Checkout<\/strong>-Pfade optimiere ich f\u00fcr minimale Sperrzeiten: kurze Transaktionen, nur die n\u00f6tigen Zeilen, und Indizes exakt auf die verwendeten WHERE-Bedingungen. F\u00fcr Reports plane ich asynchrone Aggregation (Zwischentabellen), damit Nutzerflows nicht ausgebremst werden.<\/p>\n\n<h2>Grenzen des Slow Logs und erg\u00e4nzende Metriken<\/h2>\n<p><strong>Viele kleine, schnelle Queries<\/strong> fallen im Slow Log nicht auf, summieren sich aber zur Last. Ich tracke deshalb auch Durchsatz (Queries\/sec), 95.\/99.-Perzentile und den Anteil an Abfragen ohne Index. In Performance Schema oder APM-Tools erkenne ich N+1-Muster, die ich anschlie\u00dfend gezielt durch Joins, Batch-Ladevorg\u00e4nge oder Caching aufl\u00f6se.<\/p>\n<p><strong>Sampling<\/strong> ist sinnvoll, wenn Logs zu gro\u00df werden. Ich erh\u00f6he long_query_time leicht oder setze min_examined_row_limit, um nur relevante Abfragen zu erfassen. Wichtig: \u00c4nderungen immer notieren, damit Zeitreihen vergleichbar bleiben.<\/p>\n\n<h2>Arbeitsweise: Vom Befund zur nachhaltigen Verbesserung<\/h2>\n<p><strong>Baseline<\/strong> zuerst: Ich sichere mir einen Vorher-Report (Zeitfenster, Traffic, Konfiguration). Dann optimiere ich eine Query-Familie nach der anderen und vergleiche identische Zeitfenster. Jeder Fix landet dokumentiert im Repository (Was? Warum? Messwert vorher\/nachher?). So bleiben Erfolge nachvollziehbar und regressionssicher.<\/p>\n<pre><code># Grober Ablauf (Beispiel)\n1) pt-query-digest --since '7d' slow-query.log &gt; baseline.txt\n2) Top 3 Query-Digests ausw\u00e4hlen (nach Gesamtzeit)\n3) EXPLAIN\/EXPLAIN ANALYZE, Index- und Rewrite-Vorschl\u00e4ge ausarbeiten\n4) Testdaten generieren, Lastprofil simulieren\n5) Rollout mit Monitoring (engere Grenzwerte f\u00fcr 48h)\n6) Vergleichsreport: pt-query-digest --since '48h' &gt; after.txt\n7) Ergebnis dokumentieren, n\u00e4chste Tranche planen\n<\/code><\/pre>\n<p><strong>Planstabilit\u00e4t<\/strong> beobachte ich \u00fcber Zeit: Wenn sich Pl\u00e4ne \u00e4ndern (neue Versionen, ge\u00e4nderte Statistiken), pr\u00fcfe ich Histogramme, ANALYZE TABLE und die Indexlandschaft. Hints setze ich nur punktuell und dokumentiert, um nicht den Optimizer dauerhaft zu fesseln.<\/p>\n\n<h2>Zusammenfassung in klaren Schritten<\/h2>\n<p><strong>Starten<\/strong> hei\u00dft: Log aktivieren, sinnvolle Grenzwerte setzen, erste Woche Daten sammeln. Danach fasse ich mit pt-query-digest zusammen, priorisiere nach Gesamtzeit und Varianz und w\u00e4hle die Top-Treiber. Ich optimiere Queries mit EXPLAIN, sargablen Bedingungen und passenden Indizes und kontrolliere Locking durch k\u00fcrzere Transaktionen. Serverseitig stelle ich Puffer, tempor\u00e4re Tabellen und Flush-Strategien passend ein. Am Ende automatisiere ich Alarme und wiederhole den Zyklus regelm\u00e4\u00dfig \u2013 so bleibt die Datenbank schnell, auch wenn Traffic und Datenvolumen wachsen.<\/p>","protected":false},"excerpt":{"rendered":"<p>Analyser loggen over langsomme MySQL-foresp\u00f8rgsler i hosting: Aktivering, forst\u00e5else af metrikker og tuning af foresp\u00f8rgsler til hosting af databaseoptimering.<\/p>","protected":false},"author":1,"featured_media":18586,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_crdt_document":"","inline_featured_image":false,"footnotes":""},"categories":[781],"tags":[],"class_list":["post-18593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-datenbanken-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"524","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"MySQL Slow Query Log","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"18586","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/18593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/comments?post=18593"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/posts\/18593\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media\/18586"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/media?parent=18593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/categories?post=18593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/da\/wp-json\/wp\/v2\/tags?post=18593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}