Die Erstellung von Ausführungsplänen für SQL-Statements bei MySQL ist ein alter Hut. Anhand des Beispielschemas „sakila" wird hier im Folgenden für einen einfachen Join ein solcher Plan erstellt:
Auch die Tatsache, dass sich Ausführungspläne mittlerweile in anderen Formaten (TREE & JSON) darstellen lassen, dürfte sich rumgesprochen haben:
Bis zur Version 8.0.10 basieren die Informationen eines Ausführungsplans auf Schätzungen und stellen damit so etwas wie eine Prognose da. Natürlich werden vom Optimizer für diese Prognose zahlreiche vorhandene Daten und Statistiken herangezogen, um die Qualität der Vorhersage möglichst optimal zu gestalten.
Ist Messen besser als Schätzen?
Mit der aktuellen MySQL-Version 8.0.18 können nun zusätzlich Informationen generiert werden. Die Option „analyze" ermittelt nach der Ausführung (!) des Statements einige statistische Daten (man beachte die unterschiedliche Laufzeit zur Erstellung der Ausführungspläne: Plan 1 in 0,00 Sek; Plan 2 0,39 Sek.):
- die geschätzten (!) Kosten des Optimizers
- die geschätzten, zu liefernden Zeilen (Datensätze)
- die benötigte Zeit zur Lieferung der ersten Zeile
- die benötigte Zeit zur Lieferung aller Datensätze
- die Anzahl der Zeilen je Iterator
- die Anzahl der Schleifen (Loops)
Für das oben genutzte Statement sieht ein so erstellter Plan nun wie folgt aus:
Pro Ausführungsschritt werden nun detaillierte Statistiken generiert. Im ersten Schritt erfolgt jeweils ein Zugriff auf die Tabellen „a" (Alias für „actor") und „fa" (Alias für „film_actor") über verfügbare Indices.
Schaut man sich die beiden Indexzugriffe (Index scan… und Index lookup…) an, so lässt sich erkennen, dass der erste Satz der Tabelle „a" bereits nach 0.049 Millisekunden geliefert wurde.
„Die Lieferung" aller 200 Sätze hat hingegen 2.368 Millisekunden gedauert. Mit den ermittelten 200 Indexwerten dieser Tabellen wurde dann über eine Schleife (Nested Loop) auf die Tabelle „fa" (Alias für film_actor) zugegriffen. Die gesamte Laufzeit dafür betrug 0,331 Millisekunden (der erste Wert wurde bereits nach 0,026 Millisekunden geliefert). Der Plan kann so von unten nach oben gelesen werden.
Im letzten Schritt (der obersten Zeile) wird letztendlich die Gesamtlaufzeit präsentiert. In Summe wurden 5.462 Zeilen in 358 Millisekunden oder 0,36 Sekunden geliefert. Aber stimmt dies auch?
Über eine Schleife wurde für das oben stehende Statement abwechselnd der Zeitwert des Ausführungsplans und die Zeit der tatsächlichen Ausführung ermittelt. Die Ergebnisse für ein eher kurz laufendes SELECT waren leider eher ernüchternd:
Die vom Ausführungsplan ermittelten Zeiten waren in dieser kleinen Messreihe deutlich (ca. Faktor 3) größer als die tatsächlichen Ausführungszeiten. Diese Abweichungen ließen sich auch mit weiteren Statements noch gravierender reproduzieren:
Hier liegt die Differenz zwischen der Ausführungszeit von gerundeten 0,00 Sekunden (oben) und fast 1,2 Sekunden (unten) die über den Ausführungsplan ermittelt worden.
Fazit: Traue keiner Statistik, die du nicht selbst überprüft hast!
Das neue "Feature" ist mit Vorsicht zu genießen. Mehr Informationen sind immer gut, wenn man auf der Suche nach Performanceproblemen ist. Leider nützt es nichts, wenn man sich auf die Daten nicht verlassen kann. Es bleibt zu hoffen, dass es hier in den nächsten Versionen zu Verbesserungen und/oder zumindest zu Erklärungen für dieses Verhalten kommt.
Sie haben Fragen rund um das Thema von Datenbank-Performance? Dann sprechen Sie mit uns.
Sie haben Interesse an einer Weiterbildung oder Fragen zum Thema MySQL? Sprechen Sie uns an oder besuchen Sie einen unserer Kurse aus unserem Seminarshop:
Zu unseren MySQL Seminaren