Eine kurze Einführung in die Softwareseitige Performance-Optimierung und das Debugging von MySQL-Datenbanken
Im nachfolgenden Text bekommen Sie eine kurze Einführung darin, mit welchen Möglichkeiten sich die Lese- und Schreibgeschwindigkeit auf MySQL-Datenbanken optimieren lassen. Zudem werden Möglichkeiten des Debuggings von MySQL-Datenbanken erläutert.
Hinweis: Generell ist es sinnvoll, so viel wie möglich in den RAM des Systems auszulagern, da dieser wesentlich schneller ist als die Festplatte. Daher ist es sinnvoll, möglichst viel RAM dem System zu geben, damit so viel wie irgendwie möglich dort von MySQL gecacht werden kann. Dies hat wesentliche Auswirkungen auf die Performance mit den unten aufgeführten Einstellungsmöglichkeiten.
Darüber hinaus ist es sinnvoll, zwischen den Optimierungsmöglichkeiten für den lesenden und den schreibenden Zugriff zu differenzieren. Findet keine Replikation statt, so übernimmt die gleiche MySQL-Datenbank sowohl die lesenden wie auch die schreibenden Zugriffe. In diesem Fall muss für beides optimiert und eine entsprechende Balance gefunden werden. Existiert eine Master-Slave Replikation, so kann der Master für den schreibenden Zugriff und der Slave für die Leseoperationen optimiert werden.
In MySQL ist es möglich, Einstellungen für die Datenbank zur Laufzeit zu ändern. Diese Änderungen gehen bei einem Neustart der MySQL-Instanz verloren und müssen beim nächsten Mal wieder neu gesetzt werden.
Um Änderungen permanent zu machen, gibt es die Möglichkeit eine my.cnf (für Unix-Systeme und Windows-Systeme) bzw. eine my.ini (nur Windows-Systeme) anzulegen.
Die my.cnf kann auf Linux Debian basierten Systemen unter /etc/my.cnf angelegt werden. Die my.ini kann beispielsweise unter C:\my.ini angelegt werden. Andere Ablageorte sind ebenfalls möglich. Eine genaue Übersicht kann hier nachgelesen werden.
Nachfolgend einige Beispiele für MySQL-Einstellungen für Entwicklungs- und Produktiv-Systeme.
Einstellungen für Entwicklungs-Systeme
Logging
Logging in MySQL dient unter anderem dazu Entwicklern Aufschlüsse darüber zu geben, welche Operationen durchgeführt werden (z.B.start, stop, insert, update, delete), welche Auswirkungen diese auf die Performance des Systems haben und welche Datenbankabfragen optimiert werden können/müssen.
Um das Logging zu aktivieren, müssen in der my.cnf die folgenden Einträge gemacht werden:
Nachfolgend werden die oben genannten Loggings erläutert.
- Der bin_log speichert unter anderem Informationen über Änderungen an der Struktur der Datenbank und Tabellen, sowie die Dauer einer Operation
- Der slow_query_log loggt alle MySQL-Abfragen, die zur Ausführung länger als die in „long_query_time“ benötigte Zeit in Sekunden benötigen. Für die Größe der „long_query_time“ gibt es keine allgemein gültige Regel. Dies hängt davon ab, ob Abfragen in der Datenbank zu lange dauern oder nicht. Aber generell sollte z. B. die Auslieferung einer Webseite nicht länger als eine Sekunde dauern.
- Der error_log speichert Informationen über Fehler, die zur Laufzeit des MySQL-Servers auftreten.
- Der general_query_log ist z.B. hilfreich, um Anfragen an den Server zu untersuchen oder um festzustellen, welche Nutzer sich mit der Datenbank verbinden.
Einstellungen für alle Systeme
Caching zur Optimierung der Lesegeschwindigkeit
Um die Lesegeschwindigkeit von MySQL zu erhöhen, können die oben genannten Einstellungen in der my.conf (my.ini) vorgenommen werden. Hierbei ist zu beachten, dass der Query-Cache ab MySQL 5.6 standardmäßig ausgeschaltet ist.
- Query Cache: Sollte eigentlich "result cache" heißen, weil es die Abfrage Ergebnisse (+ hash + affected tables) speichert. Es steigert die Lese-Geschwindigkeit (select-Operationen). Hierbei werden die Ergebnisse von select-queries gecacht. Funktioniert gut, wenn viele gleiche select-queries angefragt werden. Daher sollte man viele identische Queries schreiben, queries wieder verwenden oder Stored Procedures einsetzen, damit der Cache zum Einsatz kommt. Ist die Abfrage eigentlich identisch, aber z. B. die Reihenfolge in der Abfrage ist unterschiedlich, so ergibt sich ein anderer Hash Wert und der Cache wird nicht verwendet.
Query cache ist nicht wirksam für update-, insert- und delete-Operationen.
Ist die Anzahl der Thread größer als 10 wird der query_cache zum Bottleneck. In diesem Fall ist es besser den query_cache zu deaktivieren.
Empfehlung: Via Monitoring die Anzahl der Threads und das Caching überwachen.
- Table Definition Cache: Dieser Cache dient dazu, die Abfrage von Tabellen schneller zu machen, indem die Definitionen der Tabellen im Cache gespeichert werden. So muss nicht jedes Mal erneut die Tabellendefinition geladen werden.
- Table Open Cache: Hier wird die Anzahl der Tabellen gespeichert, die MySQL gleichzeitig offen halten kann. Idealerweise ist diese Anzahl so groß wie möglich.
- InnoDB buffer pool size: Dieser Cache reduziert die schreibenden und lesenden Zugriffe auf der Festplatte während auf Datenbanktabellen zugegriffen wird. Wenn möglich sollte diesem so viel RAM wie möglich zugewiesen werden, idealerweise etwa 80 % des verfügbaren RAMs bei einem dedizierten MySQL Server.
Optimierung der Schreibgeschwindigkeit
- InnoDB log file size: Dieser Cache beschreibt die Größe der Dateien iblog0 und iblog1. Diese sollten groß genug sein, um 60 Sekunden oder sogar eine Stunde die SQL Statements zu speichern.
- innodb_flush_log_at_trx_commit: Einstellung, wann der log Puffer in die log Datei auf der Festplatte geschrieben wird.
Mögliche Werte:
0 bedeutet einmal pro Sekunde (gut bei viel Traffic) - der log Puffer wird einmal pro Sekunde ins log file geschrieben und der Puffer wird wieder geleert, außer es handelt sich um eine Transaktion
1 (default) der log Puffer wird bei jedem Commit einer Transaktion in die log Datei auf der Festplatte geschrieben und der Puffer wird wieder geleert.
2 bedeutet, dass die Daten gleichzeitig in eine Cache Datei auf der Festplatte geschrieben werden - der log Puffer wird bei jedem commit in die Datei auf der Festplatte geschrieben. Das Leeren des Puffers erfolgt jede Sekunde.
Fazit
Die Standard-Konfiguration von MySQL ist nicht die beste, daher sollten Änderungen an den Einstellungen vorgenommen werden. Zu beachten ist hierbei, dass sich die Einstellungen je nach Entwicklungsumgebung (dev, test, prod) unterscheiden können. Für Produktivsysteme empfiehlt es sich, die Einstellungen auf Lese- / Schreibgeschwindigkeit zu optimieren. Bei Entwicklungssystemen ist dies, je nach Projekt und Größe der Datenbank, nicht ganz so wichtig und Einstellungen zum Debugging eventuell wichtiger. Eine weitere wichtige Rolle spielt auch die Rechenleistung der jeweiligen Systeme oder ob es sich um eine Master/Slave-Replikation handelt. Für Produktivumgebungen empfiehlt sich auch, ein Monitoring der wichtigsten Werte, wie die Anzahl der gleichzeitigen Threads oder die Auslastung der Caches. Auf diese Weise wird relativ schnell ersichtlich, ob es irgendwo einen Engpass gibt.