Mit dem Befehl EXPLAIN
vor einem SELECT
kann man sehen wie MySQL die Query optimiert und verarbeitet. Man kann sehen ob und welche Indexe benutzt werden und wie hoch die Kosten für die Ausführung sind. Anhand des Ergebnisses kann man z.B. auch sehen wo evtl. noch ein Index fehlt oder wie man die Query noch weiter optimieren kann.
1 |
EXPLAIN SELECT * FROM .... |
Wenn man z.B. nur EXPLAIN TABLENAME
ausführt, kann man sehen welche Spalten einer Tabelle bereits mit einem Index versehen sind und welche nicht.
EXPLAIN bietet noch eine erweiterte Auswertung an, die noch weitere Werte zu Tage fördert.
1 |
EXPLAIN EXTENDED SELECT * FROM ... |
Hilfreiche Queries bei der Verwendung von EXPLAIN
Wenn man mit EXPLAIN
arbeitet, sind die folgenden Queries sehr hilfreich. Sie haben zwar nichts direkt mit EXPLAIN
zu tun, können aber das Ergebnis der EXPLAIN
Auswertung deutlich verändern.
Z.B. kann man die Tabellenreihenfolge bei JOINS mal ändern, um zu sehen wie die Performance dann ist. Man kann dabei u.a. auch sehen ob der Query Optimizer die Reihenfolge der Tabellen im JOIN optimiert oder nicht.
1 |
SELECT STRAIGHT_JOIN * FROM table1 JOIN table2 ON (table1.id=table2.id) ... |
Nach dem setzen eines Indexes oder wenn man die Vermutung hat ein Index wird nicht benutzt, sollte man die Tabellen Statistik mal aktualisieren.
1 |
ANALYZE TABLE tbl_name |
Auswertung des Ergebnisses von EXPLAIN
Die Spalten im Ergebnis bedeuten dabei folgendes:
- select_type –
- table – Name der abgefragten Tabelle
- type – Art des Lesezugriffs
- possible_keys – gibt an, unter welchen Indizes MySQL auswählen kann
- key – gibt den Schlüssel(index) an, für dessen Verwendung sich MySQL tatsächlich entschieden hat.
- key_len – gibt die Länge des Schlüssels an, für dessen Verwendung sich MySQL entschieden hat.
- ref – zeigt an, welche Spalten oder Konstanten mit dem in der Spalte key genannten Index verglichen werden,
- rows – gibt die Anzahl der Datensätze an, die MySQL glaubt untersuchen zu müssen, um die Abfrage ausführen zu können.
- extra – zusätzliche Angaben dazu, wie MySQL die Abfrage auflöst
- filtered – (Nur bei EXTENDED)
Hier die Bedeutung der Werte von einigen Spalten
select_type
SIMPLE |
einfache SELECT -Anweisung (ohne UNION oder Unterabfragen). |
PRIMARY |
äußerste SELECT -Anweisung. |
UNION |
zweite oder spätere SELECT -Anweisung in einer UNION . |
DEPENDENT UNION |
zweite oder spätere SELECT -Anweisung in einer UNION , abhängig von der äußeren Abfrage. |
UNION RESULT |
Ergebnis einer UNION . |
SUBQUERY |
erste SELECT -Anweisung in einer Unterabfrage. |
DEPENDENT SUBQUERY |
erste SELECT -Anweisung in einer Unterabfrage, abhängig von der äußeren Abfrage. |
DERIVED |
abgeleitete Tabellen-SELECT – Anweisung (Unterabfrage in FROM -Klausel). |
type
system |
Diese Tabelle hat nur einen Datensatz (Systemtabelle). Dies ist ein Sonderfall des Join-Typs const. |
const |
Die Tabelle hat maximal einen passenden Datensatz, der beim Start der Abfrage gelesen wird. |
eq_ref |
Für jede Datensatzkombination aus den vorherigen Tabellen wird genau ein Datensatz aus dieser Tabelle gelesen. Anders als die Typen system und const ist dies der beste Join-Typ. Er wird verwendet, wenn alle Teile eines Indexes vom Join verwendet werden und der Index ein Primärschlüssel oder ein eindeutiger Index ist. |
ref |
Alle Datensätze mit passenden Indexwerten werden aus dieser Tabelle für jede Kombination von Datensätzen in den vorherigen Tabellen gelesen. |
ref_or_null |
Dieser Join-Typ ähnelt ref weitgehend, allerdings führt MySQL hierbei eine zusätzliche Suche nach Datensätzen durch, die NULL-Werte enthalten. |
index_merge |
Dieser Join-Typ gibt an, dass die Indexverschmelzungsoptimierung verwendet wird. mehr infos dazu |
unique_subquery |
Dieser Typ ersetzt ref in einigen IN-Unterabfragen |
index_subquery |
Dieser Join-Typ ähnelt unique_subquery. Er ersetzt IN-Unterabfragen |
range |
Es werden nur Datensätze abgerufen, die in einem gegebenen Bereich liegen. Sie werden anhand eines Indexes ausgewählt. |
index |
Dieser Join-Typ ist mit ALL bis auf die Tatsache identisch, dass nur der Indexbaum gescannt wird. |
ALL |
Ein vollständiger Tabellenscan wird für jede Kombination von Datensätzen aus den vorherigen Tabellen durchgeführt. |
extra
Distinct |
MySQL sucht nach unterschiedlichen Werten, d. h., die Suche nach weiteren Datensätzen zur aktuellen Datensatzkombination wird beendet, sobald der erste Datensatz gefunden wurde. |
Not exists |
vvv |
range checked for each record (index map: N) |
vvv |
Using filesort |
MySQL muss einen zusätzlichen Durchlauf vornehmen, um zu ermitteln, wie die Datensätze in sortierter Reihenfolge abgerufen werden können. |
Using index |
Die Spaltendaten werden ausschließlich unter Verwendung von Angaben im Indexbaum aus der Tabelle abgerufen – es erfolgt kein zusätzlicher Suchvorgang, um jeweils den eigentlichen Datensatz auszulesen. |
Using temporary |
Um die Abfrage aufzulösen, muss MySQL eine Temporärtabelle zur Aufnahme des Ergebnisses erstellen. Dies geschieht typischerweise, wenn die Abfrage GROUP BY- und ORDER BY-Klauseln enthält, die Spalten unterschiedlich auflisten. |
Using where |
Mit einer WHERE-Klausel wird festgelegt, welche Datensätze mit der nächsten Tabelle verglichen oder an den Client gesendet werden. Wollen Sie Ihre Abfragen so schnell wie möglich machen, dann sollten Sie nach den Extra -Werten Using filesort und Using temporary suchen. |
Using sort_union(…), Using union(…), Using intersect(…) |
to do… |
Using index for group-by |
to do… |
Using where with pushed condition |
to do… |
Weblinks
- MySQL 5.1 Referenz Handbuch – Select Optimization
- Section 8.2.2, “EXPLAIN Output Format”.
- Section 8.2.3, “EXPLAIN EXTENDED Output Format”.
- Section 8.3.1.11, “ORDER BY Optimization”.
- Section 18.3.4, “Obtaining Information About Partitions”.
EXPLAIN
Join Types.