Bringen Sie Ihnen Schritt für Schritt das Tutorial zur MySQL-Abfrageoptimierungsanalyse bei

Bringen Sie Ihnen Schritt für Schritt das Tutorial zur MySQL-Abfrageoptimierungsanalyse bei

Vorwort

MySQL ist eine relationale Datenbank mit leistungsstarken Abfragefunktionen, hoher Datenkonsistenz, hoher Datensicherheit und Unterstützung für sekundäre Indizes. Allerdings ist die Leistung etwas schlechter als bei nicht-relationalen Datenbanken, und insbesondere bei mehr als einer Million Daten kommt es häufig zu langsamen Abfragen. Zu diesem Zeitpunkt müssen Sie die Gründe für die langsame Abfrage analysieren. Im Allgemeinen liegt dies an der schlechten SQL-Schreibweise des Programmierers, dem Fehlen eines Schlüsselindex oder dem ungültigen Index.

Besonders wichtig ist hierbei der von MySQL bereitgestellte EXPLAIN-Befehl, der die SELECT-Anweisung analysieren und detaillierte Informationen zur SELECT-Ausführung ausgeben kann, damit Entwickler diese gezielt optimieren können.

Und fügen Sie vor der Abfrageanweisung einfach „Explain“ hinzu:

EXPLAIN SELECT * FROM Kunde WHERE id < 100;

Vorbereiten

Zuerst müssen Sie zwei Testtabellen und Daten erstellen:

CREATE TABLE `Kunde` ( 
 `id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
 `name` VARCHAR(50) NICHT NULL STANDARD '',
 `Alter` INT(11) unsigned DEFAULT NULL,
 Primärschlüssel (`id`),
 SCHLÜSSEL `name_index` (`name`)
) ENGINE = InnoDB STANDARD-CHARSET = utf8mb4

INSERT INTO Kunde (Name, Alter) VALUES ('a', 1);
INSERT INTO Kunde (Name, Alter) VALUES ('b', 2);
INSERT INTO Kunde (Name, Alter) VALUES ('c', 3);
INSERT INTO Kunde (Name, Alter) VALUES ('d', 4);
INSERT INTO Kunde (Name, Alter) VALUES ('e', 5);
INSERT INTO Kunde (Name, Alter) VALUES ('f', 6);
INSERT INTO Kunde (Name, Alter) VALUES ('g', 7);
INSERT INTO Kunde (Name, Alter) VALUES ('h', 8);
INSERT INTO Kunde (Name, Alter) VALUES ('i', 9);
CREATE TABLE `Bestellungen` (
 `id` BIGINT(20) unsigned NOT NULL AUTO_INCREMENT,
 `user_id` BIGINT(20) unsigniert NICHT NULL STANDARD 0, `product_name` VARCHAR(50) NICHT NULL STANDARD '',
 `productor` VARCHAR(30) NICHT NULL STANDARD '',
 Primärschlüssel (`id`),
 SCHLÜSSEL `user_product_detail_index` (`Benutzer-ID`, `Produktname`, `Produkthersteller`)
) ENGINE = InnoDB STANDARD-CHARSET = utf8mb4

INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (1, „p1“, „WHH“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (1, „p2“, „WL“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (1, „p1“, „DX“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (2, „p1“, „WHH“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (2, „p5“, „WL“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (3, „p3“, „MA“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (4, „p1“, „WHH“);
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (6, 'p1', 'WHH');
INSERT INTO Bestellungen (Benutzer-ID, Produktname, Hersteller) VALUES (9, 'p8', 'TE');

EXPLAIN-Ausgabeformat

Die Ausgabe des EXPLAIN-Befehls lautet ungefähr wie folgt:

mysql> erklären select * from customer where id = 1\G
*************************** 1. Reihe ***************************
 ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
 Typ: const
mögliche Schlüssel: PRIMARY
 Schlüssel: PRIMARY
 Schlüssellänge: 8
 Verweis: const
 Reihen: 1
 gefiltert: 100,00
 Extra: NULL
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Die einzelnen Spalten haben folgende Bedeutung:

  • id: Die Kennung der SELECT-Abfrage. Jeder SELECT-Abfrage wird automatisch eine eindeutige Kennung zugewiesen.
  • select_type: Der Typ der SELECT-Abfrage.
  • Tabelle: welche Tabelle wird abgefragt Partitionen: passende Partitionen Typ: Verbindungstyp
  • Possible_keys: mögliche Indizes zur Verwendung in dieser Abfrage
  • Schlüssel: Der genaue Index, der in dieser Abfrage verwendet wird.
  • ref: welches Feld oder welche Konstante mit dem Schlüssel verwendet wird
  • Zeilen: Zeigt, wie viele Zeilen von dieser Abfrage gescannt wurden. Dies ist eine Schätzung.
  • gefiltert: Gibt den Prozentsatz der Daten an, die durch diese Abfragebedingung gefiltert wurden
  • extra: Zusatzinformationen

Schauen wir uns als Nächstes einige der wichtigeren Felder an.

Wählen Sie Typ

  • SIMPLE - Eine einfache Auswahlabfrage, die keine Unterabfragen oder UNIONs enthält
  • PRIMARY - Wenn die Abfrage komplexe Unterabfragen enthält, wird die äußerste Abfrage als primär markiert.
  • UNION - Gibt an, dass diese Abfrage die zweite oder nachfolgende Abfrage einer UNION ist.
  • DEPENDENT UNION – Die zweite oder nachfolgende Abfrage in einer UNION, die von der äußeren Abfrage abhängt
  • UNION RESULT - Ergebnis aus UNION-Tabelle auswählen
  • DERIVED - Unterabfragen, die in der From-Liste enthalten sind, werden als abgeleitet markiert. MySQL führt diese Unterabfragen rekursiv aus und speichert die Ergebnisse in einer temporären Tabelle.
  • SUBQUERY - enthält eine Unterabfrage in der Select- oder Where-Liste
  • ABHÄNGIGE UNTERABFRAGE - Die erste SELECT-Anweisung in einer Unterabfrage hängt von der äußeren Abfrage ab. Das heißt, die Unterabfrage hängt vom Ergebnis der äußeren Abfrage ab.

Der häufigste Abfragetyp sollte SIMPLE sein. Wenn unsere Abfrage beispielsweise keine Unterabfrage oder UNION-Abfrage hat, ist sie normalerweise vom Typ SIMPLE, zum Beispiel:

mysql> erklären select * from customer where id = 2\G
*************************** 1. Reihe ***************************
 ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
 Typ: const
mögliche Schlüssel: PRIMARY
 Schlüssel: PRIMARY
 Schlüssellänge: 8
 Verweis: const
 Reihen: 1
 gefiltert: 100,00
 Extra: NULL
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Wenn wir eine UNION-Abfrage verwenden, sieht die EXPLAIN-Ausgabe ungefähr wie folgt aus:

mysql> EXPLAIN (SELECT * FROM Kunde WHERE id IN (1, 2, 3)) 
 -> UNION
 -> (SELECT * FROM Kunde WHERE id IN (3, 4, 5));
+----+--------------+------------+------------+-------+---------------+--------+---------+---------+------+------+------+-----------------+
| ID | Auswahltyp | Tabelle | Partitionen | Typ | mögliche Schlüssel | Schlüssel | Schlüssellänge | Ref. | Zeilen | gefiltert | Extra |
+----+--------------+------------+------------+-------+---------------+--------+---------+---------+------+------+------+-----------------+
| 1 | PRIMARY | Kunde | NULL | Bereich | PRIMARY | PRIMARY | 8 | NULL | 3 | 100,00 | Verwenden von „where“ |
| 2 | UNION | Kunde | NULL | Bereich | PRIMARY | PRIMARY | 8 | NULL | 3 | 100,00 | Verwenden von „where“ |
| NULL | UNION-ERGEBNIS | <union1,2> | NULL | ALL | NULL | NULL | NULL | NULL | NULL | NULL | Temporäre | verwenden |
+----+--------------+------------+------------+-------+---------------+--------+---------+---------+------+------+------+-----------------+
3 Zeilen im Satz, 1 Warnung (0,00 Sek.)

Tisch

Gibt die Tabelle oder abgeleitete Tabelle an, die in der Abfrage enthalten ist.

Typ

Das Typfeld ist wichtig, da es eine wichtige Grundlage für die Beurteilung der Effizienz der Abfrage bietet. Über das Typfeld können wir beurteilen, ob es sich bei der Abfrage um einen vollständigen Tabellenscan oder einen Indexscan handelt.

Typ Gängige Typen

Übliche Werte für Typ sind:

  • System: Es gibt nur ein Datum in der Tabelle. Dieser Typ ist ein spezieller Konstantentyp.
  • const: Bei gleichwertigen Abfragen, die nach Primärschlüssel oder eindeutigem Index scannen, wird höchstens eine Datenzeile zurückgegeben. Const-Abfragen sind sehr schnell, da sie nur einmal gelesen werden. Die folgende Abfrage verwendet beispielsweise den Primärschlüsselindex, daher ist der Typ const.
mysql> erklären select * from customer where id = 2\G
*************************** 1. Reihe ***************************
 ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
 Typ: const
mögliche Schlüssel: PRIMARY
 Schlüssel: PRIMARY
 Schlüssellänge: 8
 Verweis: const
 Reihen: 1
 gefiltert: 100,00
 Extra: NULL
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

eq_ref: Dieser Typ erscheint normalerweise in Verknüpfungsabfragen mit mehreren Tabellen und gibt an, dass für jedes Ergebnis der vorherigen Tabelle nur eine Ergebniszeile in der nächsten Tabelle abgeglichen werden kann. Und die Vergleichsoperation der Abfrage ist normalerweise =, was eine hohe Abfrageeffizienz aufweist. Beispiel:

mysql> EXPLAIN SELECT * FROM Kunde, Bestellinfo WHERE Kunden-ID = Bestellinfo.Benutzer-ID\G
*************************** 1. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Bestellinfo
 Partitionen: NULL
  Typ: Index
mögliche Schlüssel: Benutzer-Produktdetailindex
  Schlüssel: user_product_detail_index
 Schlüssellänge: 314
  Ref: NULL
  Reihen: 9
 gefiltert: 100,00
 Extra: Verwenden von „where“; Verwenden von „index“
*************************** 2. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
  Typ: eq_ref
mögliche Schlüssel: PRIMARY
  Schlüssel: PRIMARY
 Schlüssellänge: 8
  Referenz: test.order_info.user_id
  Reihen: 1
 gefiltert: 100,00
 Extra: NULL
2 Zeilen im Satz, 1 Warnung (0,00 Sek.)

Ref.: Dieser Typ erscheint normalerweise in Verknüpfungsabfragen für mehrere Tabellen, für nicht eindeutige oder nicht auf Primärschlüsseln basierende Indizes oder für Abfragen, die den ganz linken Präfixregelindex verwenden.

Im folgenden Beispiel wird beispielsweise die Abfrage vom Typ „Ref“ verwendet:

mysql> EXPLAIN SELECT * FROM Kunde, Bestellinfo WHERE Kunden-ID = Bestellinfo.Benutzer-ID AND Bestellinfo.Benutzer-ID = 5\G
*************************** 1. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
  Typ: const
mögliche Schlüssel: PRIMARY
  Schlüssel: PRIMARY
 Schlüssellänge: 8
  Verweis: const
  Reihen: 1
 gefiltert: 100,00
 Extra: NULL
*************************** 2. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Bestellinfo
 Partitionen: NULL
  Typ: ref
mögliche Schlüssel: Benutzer-Produktdetailindex
  Schlüssel: user_product_detail_index
 Schlüssellänge: 9
  Verweis: const
  Reihen: 1
 gefiltert: 100,00
 Extra: Index verwenden
2 Zeilen im Satz, 1 Warnung (0,01 Sek.)

Bereich: Gibt an, dass eine Indexbereichsabfrage verwendet wird, um über den Indexfeldbereich partielle Datensätze in der Tabelle abzurufen. Dieser Typ erscheint normalerweise in den Operationen =, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, IN(). Wenn der Typ Bereich ist, ist das von EXPLAIN ausgegebene Referenzfeld NULL und das Feld key_len ist der längste Index, der in dieser Abfrage verwendet wird.

Das folgende Beispiel ist beispielsweise eine Bereichsabfrage:

mysql> EXPLAIN SELECT * FROM customer WHERE id ZWISCHEN 2 UND 8 \G
*************************** 1. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
  Typ: Bereich
mögliche Schlüssel: PRIMARY
  Schlüssel: PRIMARY
 Schlüssellänge: 8
  Ref: NULL
  Reihen: 7
 gefiltert: 100,00
 Extra: Verwenden von „where“
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Index: Gibt einen vollständigen Indexscan an, der dem Typ ALL ähnelt, mit der Ausnahme, dass der Typ ALL die gesamte Tabelle scannt, während der Typ Index nur alle Indizes scannt, ohne Daten zu scannen.

Der Indextyp wird normalerweise angezeigt, wenn die abzufragenden Daten direkt im Indexbaum abgerufen werden können, ohne dass die Daten gescannt werden müssen. In diesem Fall wird im Feld „Extra“ „Index wird verwendet“ angezeigt.

Zum Beispiel:

mysql> EXPLAIN SELECT Name FROM Kunde \G
*************************** 1. Reihe ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
  Typ: Index
mögliche Schlüssel: NULL
  Schlüssel: name_index
 Schlüssellänge: 152
  Ref: NULL
  Reihen: 10
 gefiltert: 100,00
 Extra: Index verwenden
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Im obigen Beispiel ist das von uns abgefragte Namensfeld zufällig ein Index, sodass wir die Daten direkt aus dem Index abrufen können, um die Abfrageanforderungen zu erfüllen, ohne die Daten in der Tabelle abzufragen. Daher ist in diesem Fall der Wert von Typ Index und der Wert von Extra ist Index verwenden.

  • ALL: Zeigt einen vollständigen Tabellenscan an. Dieser Abfragetyp ist einer der Abfragen mit der schlechtesten Leistung. Generell sollten wir keine Abfragen vom Typ ALL verwenden, da solche Abfragen bei großen Datenmengen eine enorme Katastrophe für die Datenbankleistung darstellen. Wenn es sich bei einer Abfrage um eine Abfrage vom Typ ALL handelt, können Sie im Allgemeinen Indizes zu den entsprechenden Feldern hinzufügen, um dies zu vermeiden.

Nachfolgend sehen Sie ein Beispiel für einen vollständigen Tabellenscan. Sie können sehen, dass im vollständigen Tabellenscan sowohl die Possible_Keys- als auch die Key-Felder NULL sind, was darauf hinweist, dass kein Index verwendet wird. Außerdem sind die Zeilen sehr groß, sodass die Gesamtabfrageeffizienz sehr gering ist.

mysql> EXPLAIN SELECT age FROM customer WHERE age = 20 \G**************************** 1. Zeile ***************************
  ID: 1
 select_type: EINFACH
 Tabelle: Kunde
 Partitionen: NULL
  Typ: ALLE
mögliche Schlüssel: NULL
  Schlüssel: NULL
 key_len: NULL
  Ref: NULL
  Reihen: 10
 gefiltert: 10.00
 Extra: Verwenden von „where“
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Leistungsvergleich von Typ

Im Allgemeinen ist das Leistungsverhältnis zwischen den verschiedenen Typen wie folgt:

ALLE <Index <Bereich ~Index_Merge <Ref <Eq_Ref <const <System

Der Typ „ALL“ ist der langsamste, da es sich um einen vollständigen Tabellenscan unter denselben Abfragebedingungen handelt.

Obwohl die Abfrage vom Indextyp nicht die gesamte Tabelle durchsucht, durchsucht sie alle Indizes und ist daher etwas schneller als der Typ ALL. Die folgenden Typen verwenden alle Indizes zum Abfragen von Daten, sodass sie einen Teil oder die meisten Daten filtern können, sodass die Abfrageeffizienz relativ hoch ist.

Wenn ein Programmierer sicherstellen kann, dass die Abfrage mindestens die Bereichsebene oder besser noch die Referenzebene erreicht, gilt er als hervorragender und verantwortungsvoller Programmierer.

  • ALL: (vollständiger Tabellenscan) Der vollständige Tabellenscan ist zweifellos der schlechteste. Wenn das Datenvolumen im Millionen- oder Zehnmillionenbereich liegt, ist ein vollständiger Tabellenscan sehr langsam.
  • index: (vollständiger Indexscan) Ein vollständiger Indexdateiscan ist viel besser als alles andere. Schließlich ist das Suchen von Daten aus dem Indexbaum schneller als das Suchen von Daten aus der gesamten Tabelle.
  • Bereich: Ruft nur die Zeilen in einem bestimmten Bereich ab und verwendet dabei den Index zum Abgleichen der Zeilen. Der Umfang ist eingeschränkt und natürlich ist es schneller als ein vollständiger Tabellenscan und ein vollständiger Indexdateiscan. SQL-Anweisungen enthalten im Allgemeinen Abfragen wie „zwischen“, „in“, „>“, „<“ usw.
  • Ref: Ein nicht eindeutiger Indexscan ist im Wesentlichen ein Indexzugriff, der alle Zeilen zurückgibt, die einem einzelnen Wert entsprechen. Wenn Sie beispielsweise alle Kollegen im Forschungs- und Entwicklungsteam eines Unternehmens abfragen, sind die übereinstimmenden Ergebnisse mehrere, aber keine eindeutigen Werte.
  • eq_ref: Eindeutiger Indexscan, für jeden Indexschlüssel gibt es einen passenden Datensatz in der Tabelle. Wenn Sie beispielsweise den CEO eines Unternehmens abfragen, besteht das übereinstimmende Ergebnis möglicherweise nur aus einem Datensatz.
  • const: gibt an, dass der Wert durch einmaliges Indizieren gefunden werden kann. const wird zum Vergleichen von Primärschlüsseln oder eindeutigen Indizes verwendet. Da nur eine Datenzeile abgeglichen werden muss, kann MySQL die Abfrage schnell in eine Konstante umwandeln, wenn der Primärschlüssel in der Where-Liste platziert wird.
  • System: Die Tabelle hat nur einen Datensatz (gleich der Systemtabelle). Dies ist eine spezielle Spalte vom Typ const. Normalerweise erscheint sie nicht. Sie müssen es einfach verstehen.

möglicher_Schlüssel

Possible_keys gibt die Indizes an, die MySQL bei Abfragen verwenden kann. Beachten Sie, dass selbst wenn einige Indizes in Possible_keys erscheinen, dies nicht bedeutet, dass dieser Index tatsächlich von MySQL verwendet wird. Die spezifischen Indizes, die MySQL bei Abfragen verwendet, werden durch das Schlüsselfeld bestimmt.

Schlüssel

Dieses Feld ist der Index, den MySQL tatsächlich in der aktuellen Abfrage verwendet.

Schlüssellänge

Gibt die Anzahl der vom Abfrageoptimierer verwendeten Bytes an. Mit diesem Feld kann ausgewertet werden, ob der zusammengesetzte Index vollständig verwendet wird oder nur die Felder ganz links verwendet werden.

Die Berechnungsregeln für key_len lauten wie folgt:

  • Zeichenfolge
    • char(n): n Byte lang
    • varchar(n): Wenn es sich um UTF-8-Kodierung handelt, ist es 3
      n + 2 Bytes; wenn utf8mb4-Kodierung, dann 4
      n + 2 Bytes.
  • Werttyp:
    • TINYINT: 1 Byte
    • SMALLINT: 2 Bytes
    • MEDIUMINT: 3 Bytes
    • INT: 4 Bytes
    • BIGINT: 8 Bytes
  • Zeittyp
    • DATUM: 3 Bytes
    • ZEITSTEMPEL: 4 Bytes
    • DATETIME: 8 Bytes
  • Feldattribute: Das NULL-Attribut belegt ein Byte. Wenn ein Feld NICHT NULL ist, hat es dieses Attribut nicht.

Betrachten wir zwei einfache Beispiele:

mysql> EXPLAIN SELECT * FROM order_info WHERE user_id < 3 AND product_name = 'p1' AND productor = 'WHH' \G
*************************** 1. Reihe ***************************
   ID: 1
 select_type: EINFACH
  Tabelle: Bestellinfo
 Partitionen: NULL
   Typ: Bereich
mögliche Schlüssel: Benutzer-Produktdetailindex
   Schlüssel: user_product_detail_index
  Schlüssellänge: 9
   Ref: NULL
   Reihen: 5
  gefiltert: 11.11
  Extra: Verwenden von „where“; Verwenden von „index“
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Das obige Beispiel fragt den angegebenen Inhalt aus der Tabelle order_info ab. Aus der Anweisung zur Tabellenerstellung können wir erkennen, dass die Tabelle order_info einen gemeinsamen Index hat:

SCHLÜSSEL `user_product_detail_index` (`Benutzer-ID`, `Produktname`, `Produkthersteller`)

In der Abfrage WHERE user_id < 3 AND product_name = 'p1' AND productor = 'WHH' wird jedoch zuerst die user_id-Bereichsabfrage ausgeführt. Gemäß dem Prinzip des ganz linken Präfixabgleichs wird der Indexabgleich beendet, wenn eine Bereichsabfrage gefunden wird. Daher ist user_id tatsächlich das einzige Indexfeld, das wir verwenden. Daher ist in EXPLAIN die angezeigte key_len 9. Da das user_id-Feld BIGINT ist, belegt es 8 Bytes und das NULL-Attribut belegt ein Byte, sodass die Gesamtsumme 9 Bytes beträgt. Wenn wir das user_id-Feld in BIGINT(20) NOT NULL DEFAULT '0' ändern, sollte die key_length 8 sein.

Aufgrund des Prinzips des ganz linken Präfixabgleichs verwendet unsere Abfrage nur das Feld user_id des gemeinsamen Index, sodass die Effizienz nicht hoch ist.

Schauen wir uns das nächste Beispiel an:

mysql> EXPLAIN SELECT * FROM order_info WHERE user_id = 1 AND product_name = 'p1' \G;
*************************** 1. Reihe ***************************
   ID: 1
 select_type: EINFACH
  Tabelle: Bestellinfo
 Partitionen: NULL
   Typ: ref
mögliche Schlüssel: Benutzer-Produktdetailindex
   Schlüssel: user_product_detail_index
  Schlüssellänge: 161
   Verweis: konstant, konstant
   Reihen: 2
  gefiltert: 100,00
  Extra: Index verwenden
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

In dieser Abfrage haben wir keine Bereichsabfrage verwendet und der Wert von key_len ist 161. Warum? Weil in unserer Abfragebedingung WHERE user_id = 1 AND product_name = 'p1' nur die ersten beiden Felder im gemeinsamen Index verwendet werden, also keyLen(user_id) + keyLen(product_name) = 9 + 50 * 3 + 2 = 161

Reihen

Zeilen sind ebenfalls ein wichtiges Feld. Basierend auf den Statistiken schätzt der MySQL-Abfrageoptimierer die Anzahl der Zeilen, die SQL scannen muss, um den Ergebnissatz zu finden.

Dieser Wert zeigt direkt die Effizienz von SQL. Grundsätzlich gilt: je weniger Zeilen, desto besser.

Extra

Im Feld „Extra“ werden in „EXplain“ zahlreiche Zusatzinformationen angezeigt. Die häufigsten sind die folgenden:

  • Verwenden von Filesort

Wenn „Using Filesort“ im Extra-Modus ist, bedeutet dies, dass MySQL zusätzliche Sortiervorgänge benötigt und den Sortiereffekt nicht über die Indexreihenfolge erzielen kann. Generell wird empfohlen, „Using Filesort“ zu optimieren und zu entfernen, da solche Abfragen viele CPU-Ressourcen verbrauchen.

Beispielsweise das folgende Beispiel:

mysql> EXPLAIN SELECT * FROM order_info WHERE user_id = 1 AND product_name = 'p1' \G;
*************************** 1. Reihe ***************************
   ID: 1
 select_type: EINFACH
  Tabelle: Bestellinfo
 Partitionen: NULL
   Typ: ref
mögliche Schlüssel: Benutzer-Produktdetailindex
   Schlüssel: user_product_detail_index
  Schlüssellänge: 161
   Verweis: konstant, konstant
   Reihen: 2
  gefiltert: 100,00
  Extra: Index verwenden
1 Zeile im Satz, 1 Warnung (0,00 Sek.)

Unser Index ist

SCHLÜSSEL `user_product_detail_index` (`Benutzer-ID`, `Produktname`, `Produkthersteller`)

Die obige Abfrage ist jedoch nach Produktname sortiert, sodass der Index nicht zur Optimierung verwendet werden kann, was zur Verwendung von Filesort führt.

Wenn wir die Sortierbasis in ORDER BY user_id, product_name ändern, wird Using filesort nicht angezeigt. Beispiel:

mysql> EXPLAIN SELECT * FROM Bestellinfo ORDER BY Benutzer-ID, Produktname \G
*************************** 1. Reihe ***************************
   ID: 1
 select_type: EINFACH
  Tabelle: Bestellinfo
 Partitionen: NULL
   Typ: Index
mögliche Schlüssel: NULL
   Schlüssel: user_product_detail_index
  Schlüssellänge: 253
   Ref: NULL
   Reihen: 9
  gefiltert: 100,00
  Extra: Index verwenden
1 Zeile im Satz, 1 Warnung (0,00 Sek.)
  • Verwenden des Index

"Abdeckender Index-Scan" bedeutet, dass die Abfrage die erforderlichen Daten im Indexbaum finden kann, ohne die Tabellendatendatei zu scannen, was häufig auf eine gute Leistung hinweist

  • Mit temporären

Die Abfrage verwendet temporäre Tabellen, die normalerweise in Sortier-, Gruppierungs- und Mehrtabellenverknüpfungssituationen vorkommen. Die Abfrageeffizienz ist nicht hoch. Es wird empfohlen, sie zu optimieren.

Zusammenfassen

Das Obige ist der vollständige Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Lernwert für Ihr Studium oder Ihre Arbeit hat. Vielen Dank für Ihre Unterstützung von 123WORDPRESS.COM.

Das könnte Sie auch interessieren:
  • Implementierung von MySQL Select in der Unterabfrageoptimierung
  • Ein Artikel zum Erlernen von Fähigkeiten zur Optimierung von MySQL-Indexabfragen
  • Zusammenfassung der Wissenspunkte zur SQL-Abfrageoptimierung für MySQL-Big Data im zweistelligen Millionenbereich
  • Methode und Optimierungsprinzip für langsame MySQL-Abfragen
  • MySQL Slow Query-Optimierung: Die Vorteile von Limit aus Theorie und Praxis
  • MySQL-Abfrageoptimierung: Ursachen und Lösungen für langsame Abfragen

<<:  Analyse der zum Ausführen von Docker erforderlichen Berechtigungen

>>:  So installieren Sie Composer unter Linux

Artikel empfehlen

Vite+Electron zum schnellen Erstellen von VUE3-Desktopanwendungen

Inhaltsverzeichnis 1. Einleitung 2. Erstellen Sie...

DOCTYPE Dokumenttypdeklaration (unbedingt lesenswert für Webseiten-Liebhaber)

DOCTYPE-DEKLARATION: Oben auf jeder Seite, die Sie...

Standardzusammenfassung zur Analyse der Leistung einer SQL-Anweisung

In diesem Artikel wird die Verwendung von „Explai...

Implementierungsbeispiel für die Nginx-Zugriffskontrolle

Über Nginx, eine leistungsstarke, leichte Webserv...

Detaillierte Erklärung der atomaren DDL-Syntax von MySQL 8.0

Inhaltsverzeichnis 01 Einführung in Atomic DDL 02...

Das Installationstutorial zu mysql5.5.28 ist super detailliert!

mysql5.5.28 Installations-Tutorial zu Ihrer Infor...

Detaillierte Erklärung der CocosCreator MVC-Architektur

Überblick Dieser Artikel stellt die in Spieleclie...

Analyse der problematischen „Aborted“-Warnung in MySQL anhand von Fallstudien

Dieser Artikel stellt hauptsächlich den relevante...

Grafisches Tutorial zur Installation und Konfiguration von MySQL 8.0.13

In diesem Artikel finden Sie das Installations- u...