Dieser Abschnitt behandelt Optimierungen, die für die
Verarbeitung von WHERE
-Klauseln durchgeführt
werden können. Die Beispiele verwenden
SELECT
-Anweisungen, dieselben Optimierungen
gelten aber auch für WHERE
-Klauseln in
DELETE
- und
UPDATE
-Anweisungen.
Wir arbeiten fortlaufend am MySQL-Optimierer, weswegen dieser Abschnitt nicht vollständig ist. MySQL führt eine Vielzahl von Optimierungen durch, die nicht alle an dieser Stelle dokumentiert sind.
Es folgen einige von MySQL durchgeführte Optimierungen:
Entfernung unnötiger Klammern:
((a AND b) AND c OR (((a AND b) AND (c AND d)))) -> (a AND b AND c) OR (a AND b AND c AND d)
Umstellen von Konstanten:
(a<b AND b=c) AND a=5 -> b>5 AND b=c AND a=5
Entfernung von Konstantenbedingungen (erforderlich zum Umstellen von Konstanten):
(B>=5 AND B=5) OR (B=6 AND 5=5) OR (B=7 AND 5=6) -> B=5 OR B=6
Konstantenausdrücke, die von Indizes verwendet werden, werden nur einmal ausgewertet.
COUNT(*)
für eine einzelne Tabelle ohne
WHERE
wird direkt aus den Tabellendaten
für MyISAM
- und
MEMORY
-Tabellen abgerufen. Dies wird auch
für jeden NOT NULL
-Ausdruck gemacht, der
nur für eine einzige Tabelle verwendet wird.
Früherkennung ungültiger Konstantenausdrücke. MySQL
erkennt sehr schnell, wenn eine
SELECT
-Anweisung nicht möglich ist, und
gibt keine Datensätze zurück.
HAVING
wird mit WHERE
verschmolzen, wenn Sie GROUP BY
nicht
verwenden oder Funktionen (wie COUNT()
,
MIN()
usw.) zusammenfassen.
Für jede Tabelle in einem Join wird eine einfachere
WHERE
-Klausel erstellt, um eine schnelle
WHERE
-Auswertung für die Tabelle zu
erhalten und außerdem Datensätze so früh wie möglich zu
überspringen.
Bevor andere Tabellen in der Abfrage gelesen werden, werden zunächst alle Konstantentabellen ausgelesen. Zu den Konstantentabellen gehören die folgenden:
Leere Tabellen oder solche mit nur einem Datensatz.
Tabellen, die mit einer WHERE
-Klausel
für einen Primärschlüssel oder einen eindeutigen
Index verwendet werden, wobei alle Indexteile mit
Konstantenausdrücken verglichen werden und als
NOT NULL
definiert sind.
Alle folgenden Tabellen werden als Konstantentabellen verwendet:
SELECT * FROM t WHEREprimary_key
=1; SELECT * FROM t1,t2 WHERE t1.primary_key
=1 AND t2.primary_key
=t1.id;
Die beste Join-Kombination zur Verknüpfung der Tabellen
wird durch Ausprobieren aller Möglichkeiten ermittelt. Wenn
alle Spalten in den ORDER BY
- und
GROUP BY
-Klauseln aus derselben Tabelle
stammen, dann wird diese Tabelle beim Verknüpfen bevorzugt.
Wenn eine ORDER BY
- und eine davon
unterschiedliche GROUP BY
-Klausel
vorhanden sind, oder wenn ORDER BY
oder
GROUP BY
Spalten aus anderen als der
ersten Tabelle in der Join-Warteschlange enthalten, dann
wird eine Temporärtabelle erstellt.
Wenn Sie die Option SQL_SMALL_RESULT
verwenden, dann benutzt MySQL eine speicherresidente
Temporärtabelle.
Alle Tabellenindizes werden abgefragt, und der beste Index wird verwendet, sofern der Optimierer nicht der Ansicht ist, dass die Verwendung eines Tabellenscans effizienter ist. Früher wurde ein Scan basierend darauf eingesetzt, ob der beste Index sich über einen Anteil von mehr als 30 Prozent der Tabelle erstreckte; mittlerweile wird die Frage, ob ein Index oder ein Scan verwendet werden soll, nicht mehr auf der Basis eines festen Prozentwerts entschieden. Der Optimierer ist mittlerweile komplexer, und seine Schätzungen fußen auf weiteren Faktoren wie Tabellengröße, Anzahl der Datensätze und I/O-Blockgröße.
In manchen Fällen kann MySQL Datensätze aus dem Index auslesen, ohne überhaupt die Datendatei abfragen zu müssen. Wenn alle aus dem Index verwendeten Spalten numerisch sind, wird zur Auflösung der Abfrage nur der Indexbaum verwendet.
Bevor ein Datensatz ausgegeben wird, werden alle
Datensätze, die nicht der HAVING
-Klausel
entsprechen, übersprungen.
Hier einige Beispiele für Abfragen, die sehr schnell sind:
SELECT COUNT(*) FROMtbl_name
; SELECT MIN(key_part1
),MAX(key_part1
) FROMtbl_name
; SELECT MAX(key_part2
) FROMtbl_name
WHEREkey_part1
=constant
; SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
,... LIMIT 10; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC, ... LIMIT 10;
MySQL löst die folgenden Abfragen nur mithilfe des Indexbaums auf und setzt dabei voraus, dass die indizierten Spalten numerisch sind:
SELECTkey_part1
,key_part2
FROMtbl_name
WHEREkey_part1
=val
; SELECT COUNT(*) FROMtbl_name
WHEREkey_part1
=val1
ANDkey_part2
=val2
; SELECTkey_part2
FROMtbl_name
GROUP BYkey_part1
;
Die folgenden Abfragen verwendet die Indizierung zur Abfrage von Datensätzen in sortierter Reihenfolge ohne separaten Sortierdurchlauf:
SELECT ... FROMtbl_name
ORDER BYkey_part1
,key_part2
,... ; SELECT ... FROMtbl_name
ORDER BYkey_part1
DESC,key_part2
DESC, ... ;
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.