[MYSQL] MYSQL-Lerntutorial (8) 12 Gründe für langsame SQL-Abfragen

In der täglichen Entwicklung stoßen wir häufig auf langsame Datenbankabfragen. Was sind also die häufigsten Gründe für eine langsame Datenabfrage? Heute werde ich mit Ihnen über 12 häufige Ursachen langsamer MySQL-Abfragen und die entsprechenden Lösungen sprechen:

  • SQL ohne Index
  • SQL-Index ungültig
  • Begrenzen Sie das Deep-Paging-Problem
  • Die Datenmenge in einer einzelnen Tabelle ist zu groß
  • Join oder zu viele Unterabfragen
  • Zu viele Elemente
  • Die Datenbank löscht fehlerhafte Seiten
  • Sortieren nach Dateisortierung
  • Kann das Schloss nicht bekommen
  • delete + in der Unterabfrage verwendet den Index nicht
  • Gruppieren nach verwendet eine temporäre Tabelle
  • Systemhardware oder Netzwerkressourcen

1. SQL fügt keine Indizes hinzu

Oft sind unsere langsamen Abfragen auf die fehlende Indizierung zurückzuführen. Wenn kein Index vorhanden ist, führt dies zu einem vollständigen Tabellenscan . Daher sollten Sie erwägen, einen Index für die Where-Bedingungsspalte zu erstellen und vollständige Tabellenscans zu vermeiden.

2. SQL-Indexfehler

[MYSQL] MYSQL-Lerntutorial (4) Indexfehlerszenario

Manchmal haben wir einen Index hinzugefügt, aber der Index wird nicht wirksam. In welchen Szenarien wird der Index nicht wirksam? Es gibt hauptsächlich zehn klassische Szenen wie folgt:

  1. Die Abfragebedingung enthält oder, was zu einem Indexfehler führen kann
  2. Implizite Typkonvertierung, Indexfehler
  3. Der Platzhalter „%“ vor Schlüsselwörtern führt zum Indexfehler
  4. Wenn Sie die integrierten Funktionen von MYSQL für Indexspalten verwenden, wird der Index ungültig.
  5. Bei Operationen an indizierten Spalten (z. B. +, -, *, /) wird der Index ungültig.
  6. Bei Verwendung negativer Abfragen (NOT, !=, <>, NOT IN, NOT LIKE) auf Indexfeldern kann der Index ungültig werden.
  7. Das Indexfeld kann null sein. Die Verwendung von „ist null“ oder „ist nicht null“ kann zu einem Indexfehler führen.
  8. Verstößt gegen das am weitesten links stehende Matching-Prinzip des Index (gemeinsamer Index, die Bedingungsspalte bei der Abfrage ist nicht die erste Spalte im gemeinsamen Index, der Index ist ungültig).
  9. Die zugehörigen Feldkodierungsformate von Left-Join-Abfragen und Right-Join-Abfragen sind unterschiedlich, was zu Indexfehlern führen kann.
  10. MYSQL schätzt, dass die Verwendung eines vollständigen Tabellenscans schneller ist als die Verwendung eines Index, sodass der Index nicht verwendet wird.

3. Begrenzen Sie das Deep-Paging-Problem

3.1 Warum wird Limit Deep Paging langsamer?

Warum führt die Begrenzung des Deep-Paging dazu, dass SQL langsamer wird? Angenommen, wir haben eine Tabellenstruktur wie folgt:

CREATE TABLE account (
  id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
  name varchar(255) DEFAULT NULL COMMENT '账户名',
  balance int(11) DEFAULT NULL COMMENT '余额',
  create_time datetime NOT NULL COMMENT '创建时间',
  update_time datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (id),
  KEY idx_name (name),
  KEY idx_create_time (create_time) //索引
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

Führen Sie das folgende SQL aus:

select id,name,balance from account where create_time> '2020-09-19' limit 100000,10;

Der Ausführungsablauf dieser SQL:

  1. idx_create_timeFiltern Sie die Bedingungen über den normalen Sekundärindexbaum create_timeund finden Sie die Primärschlüssel-ID, die die Bedingungen erfüllt.
  2. Kehren Sie über die Primärschlüssel-ID zum ID-Primärschlüssel-Indexbaum zurück, suchen Sie die Zeile, die den Datensatz erfüllt, und entfernen Sie dann die anzuzeigenden Spalten (Tabellenrückgabeprozess).
  3. Scannen Sie 100.010 Zeilen, die die Bedingung erfüllen, verwerfen Sie dann die ersten 100.000 Zeilen und geben Sie das Ergebnis zurück

Wie nachfolgend dargestellt:

Fügen Sie hier eine Bildbeschreibung ein

Es gibt zwei Gründe, warum die Beschränkung von Deep Paging zu einer Verlangsamung von SQL führt:

  • Die limit-Anweisung scannt zunächst offset+ nZeilen, verwirft dann die vorherige offsetZeile und gibt die nächsten n Datenzeilen zurück. Mit anderen Worten limit 100000,10: Es werden 100.010 Zeilen gescannt und bei einem Grenzwert von 0,10 werden nur 10 Zeilen gescannt.
  • limit 100000,10Das Scannen weiterer Zeilen bedeutet auch, dass die Tabelle öfter zurückgegeben wird.

3.2 So optimieren Sie das Deep-Paging-Problem

Wir können optimieren, indem wir die Anzahl der Tabellenrückgaben reduzieren. Im Allgemeinen umfassen: Tag-Aufzeichnungsmethode, verzögerte Korrelationsmethode

3.2.1 Tag-Aufzeichnungsmethode

Etikettenaufzeichnungsmethode: Markieren Sie, welches Element Sie zuletzt gefunden haben. Wenn Sie das nächste Mal erneut nachsehen, beginnen Sie mit dem Scannen ab diesem Element.

Unter der Annahme, dass der letzte Datensatz 100.000 erreicht hat, kann die SQL wie folgt geändert werden:

select  id,name,balance FROM account where id > 100000 limit 10;

In diesem Fall ist die Leistung unabhängig davon, wie viele Seiten später umgeblättert werden, gut, da der ID-Primärschlüsselindex erreicht wird. Diese Methode weist jedoch Einschränkungen auf: Sie erfordert ein Feld, das der kontinuierlichen automatischen Inkrementierung ähnelt

3.2.2 Verzögerte Korrelationsmethode

Verzögerte Assoziationsmethode: Übertragen Sie die Bedingung an den Primärschlüssel-Indexbaum und reduzieren Sie dann die Rückgabetabelle

select  acct1.id,acct1.name,acct1.balance FROM account acct1 INNER JOIN (SELECT a.id FROM account a WHERE a.create_time > '2020-09-19' limit 100000, 10) AS acct2 on acct1.id= acct2.id;

Optimierungsidee: idx_create_timeFragen Sie zunächst über den Sekundärindexbaum die Primärschlüssel-ID ab, die die Bedingungen erfüllt, und verbinden Sie sie dann über die Primärschlüssel-ID mit der Originaltabelle. Auf diese Weise wird der Primärschlüsselindex später direkt und auch reduziert die Notwendigkeit von Tabellenrückgaben.

4. Die Datenmenge in einer einzelnen Tabelle ist zu groß

4.1 Warum wird es langsamer, wenn das Datenvolumen einer einzelnen Tabelle zu groß ist?

Wenn die Datenmenge in einer Tabelle Dutzende oder Hunderte Millionen erreicht, ist der Effekt des Hinzufügens von Indizes nicht so offensichtlich. Der Grund für die Verschlechterung der Leistung liegt darin, dass die B+Baumstrukturebene der Indexverwaltung höher wird. Beim Abfragen eines Datenelements müssen mehr Festplatten-E/A-Vorgänge durchgeführt werden, sodass die Abfrageleistung langsamer wird.

4.2 Wie viele Daten kann ein B+-Baum speichern?

[MYSQL] MYSQL-Lern-Tutorial (5) MySQL-Index-Unterschicht: Detaillierte Erläuterung des B+-Baums
Ein B+-Baum mit einer Höhe von 3 kann speichern 1170 *1170 *16 =21902400, das heißt, er kann etwa 20 Millionen Datensätze speichern. Die Höhe des B+-Baums beträgt im Allgemeinen 1–3 Schichten, was den Anforderungen von mehreren zehn Millionen Ebenen der Datenspeicherung gerecht werden kann.

Wenn der B+-Baum mehr Daten speichern möchte, ist die Baumstrukturebene höher. Beim Abfragen eines Datenelements muss mehr Festplatten-E/A erlebt werden, sodass die Abfrageleistung langsamer wird.

4.3 So lösen Sie das Problem zu vieler Daten in einer einzelnen Tabelle und einer langsamen Abfrage

Wenn das Niveau mehrere zehn Millionen überschreitet, können wir im Allgemeinen Unterdatenbanken und Tabellen in Betracht ziehen .

Mögliche Probleme durch Sharding-Datenbanken und Sharding-Tabellen:

  • Geschäftsprobleme
  • Datenbankübergreifende Probleme
  • Sortierproblem
  • Paginierungsproblem
  • Verteilte ID

Bevor Sie beurteilen, ob Datenbanken und Tabellen aufgeteilt werden sollen, überlegen Sie zunächst, ob ein Teil . Wenn möglich, sollten Sie Datenbanken und Tabellen nicht überstürzen. Wenn Sie Datenbanken und Tabellen wirklich trennen möchten, sollten Sie den Plan umfassend prüfen und bewerten. Sie können beispielsweise vertikale und horizontale Unterdatenbanken und Tabellen berücksichtigen. Für horizontale Datenbank- und Tabellen-Sharding-Strategien, Bereichsbereich, Hash-Modul, Bereich+Hash-Modulo-Mischung usw.

5. Zu viele Joins oder Unterabfragen

Im Allgemeinen wird die Verwendung von Unterabfragen nicht empfohlen. Sie können die Unterabfrage zur Optimierung in „Join“ ändern.

In der Datenbank gibt es eine Standardvereinbarung: Versuchen Sie, nicht mehr als 3 Tabellenverbindungen zu haben.

In MySQL sind die Join-Ausführungsalgorithmen: Index Nested-Loop Join,Block Nested-Loop Join

  • Index Nested-Loop Join(索引嵌套循环连接): Dieser Join-Algorithmus ähnelt der verschachtelten Abfrage beim Schreiben von Programmen und kann den Index der gesteuerten Tabelle verwenden
  • Block Nested-Loop Join(缓存块嵌套循环连接): Es ist kein Index für die getriebene Tabelle verfügbar . Zuerst werden die Daten der treibenden Tabelle in den Thread-Speicher join_buffer eingelesen, dann die getriebene Tabelle gescannt, jede Zeile der getriebenen Tabelle herausgenommen und mit den Daten in verglichen join_buffer zur Erfüllung der Join-Bedingung, zurückgegeben als Teil der Ergebnismenge

Probleme mit zu vielen Joins:

  1. Zu viele Tabellenverbindungen erhöhen die Komplexität von SQL erheblich
  2. Es wäre gut, wenn der Index der getriebenen Tabelle verwendet werden könnte, und wenn eine kleine Tabelle als treibende Tabelle verwendet würde, wäre die Abfrageeffizienz besser. Wenn in der gesteuerten Tabelle kein Index verfügbar ist, erfolgt die Verknüpfung im Speicher „join_buffer“. Wenn die Menge der übereinstimmenden Daten relativ klein ist oder „join_buffer“ auf einen großen Wert eingestellt ist, ist die Geschwindigkeit nicht zu langsam. Wenn jedoch die zu verbindende Datenmenge relativ groß ist, erstellt MySQL temporäre Tabellen auf der Festplatte, um den Zuordnungsabgleich mehrerer Tabellen durchzuführen. Dies ist offensichtlich sehr ineffizient. Die Festplatten-E/A ist nicht schnell und eine Zuordnung ist erforderlich.

Wenn das Unternehmen dies benötigt, ist es im Allgemeinen akzeptabel, zwei bis drei Tabellen zuzuordnen, die zugehörigen Felder müssen jedoch indiziert werden . Wenn Sie weitere Tabellen zuordnen müssen, wird empfohlen, diese von der Codeebene aufzuteilen: Fragen Sie zuerst die Daten einer Tabelle auf der Geschäftsebene ab, fragen Sie dann die zugehörige Tabelle ab und verwenden Sie die zugehörigen Felder als Bedingungen, um eine Karte zu erstellen, und fügen Sie sie dann zusammen die Daten auf der Business-Ebene.

6. Zu viele Elemente

Wenn in verwendet wird, achten Sie darauf, nicht zu viele Elemente nach in zu haben, auch wenn die Folgebedingung indiziert ist. Es wird allgemein empfohlen, dass das In-Element 500 nicht überschreiten sollte. Wenn es größer ist, wird empfohlen, es in Gruppen von jeweils 500 zu gruppieren.

Wenn wir der In-Bedingung keine Einschränkungen auferlegen, fragt die Abfrageanweisung möglicherweise viele Daten gleichzeitig ab, was leicht zu einer Zeitüberschreitung der Schnittstelle führen kann. Besonders manchmal verwenden wir Unterabfragen. Sie kennen die Anzahl der Unterabfragen nach in nicht, was es einfacher macht, in Schwierigkeiten zu geraten. Eine Unterabfrage wie die folgende:

select * from user where user_id in (select author_id from artilce where type = 1);

Ein positives Beispiel ist die stapelweise Ausführung, wobei jeder Stapel 500 umfasst:

select user_id,name from user where user_id in (1,2,3...500);

7. Die Datenbank löscht fehlerhafte Seiten

7.1 Was sind Dirty Pages?

Wenn die Speicherdatenseite nicht mit der Festplattendatenseite übereinstimmt, nennen wir diese Speicherseite eine „schmutzige Seite“ . Nachdem die Speicherdaten auf die Festplatte geschrieben wurden, sind die Inhalte der Datenseiten im Speicher und auf der Festplatte konsistent, was als „saubere Seite“** bezeichnet wird. Im Allgemeinen kann die Aktualisierung von SQL zu fehlerhaften Seiten führen.

7.2 Wie wird eine Update-Anweisung ausgeführt?

Wie wird das folgende Update-SQL ausgeführt?

update t set c=c+1 where id=666;
  1. Für dieses Update-SQL sucht der Executor zunächst nach der Engine, um die Zeilen-ID = 666 zu erhalten. Wenn sich die Datenseite, auf der sich diese Zeile befindet, bereits im Speicher befindet, wird sie direkt an den Executor zurückgegeben. Wenn es nicht im Speicher ist, gehen Sie zur Festplatte, um es in den Speicher zu lesen, und kehren Sie dann zurück
  2. Nachdem der Executor die von der Engine bereitgestellten Zeilendaten erhalten hat, addiert er eins zum Wert von C in dieser Zeile, um eine neue Datenzeile zu erhalten, und ruft dann die Engine-Schnittstelle auf, um diese neue Datenzeile zu schreiben.
  3. Die Engine aktualisiert diese neue Datenzeile im Speicher und zeichnet den Aktualisierungsvorgang im Redo-Log auf. Allerdings befindet sich das Redo-Log zu diesem Zeitpunkt im Vorbereitungszustand.
  4. Der Executor generiert ein Binlog dieser Operation und schreibt das Binlog auf die Festplatte.
  5. Der Executor ruft die Commit-Transaktionsschnittstelle der Engine auf, und die Engine ändert das gerade geschriebene Redo-Protokoll in den Commit-Status, und die Aktualisierung ist abgeschlossen.

Wie nachfolgend dargestellt:

Fügen Sie hier eine Bildbeschreibung ein

Wenn InnoDB die Update-Anweisung verarbeitet, führt es nur den Festplattenvorgang zum Schreiben des Protokolls aus. Dieses Protokoll wird Redo-Protokoll genannt. Normalerweise wird die Update-SQL sehr schnell ausgeführt. Dies liegt tatsächlich daran, dass sie nur in den Speicher und das Redo-Log schreibt. Wenn sie inaktiv ist, synchronisiert sie die Daten im Redo-Log mit der Festplatte.

Befindet sich das Redo-Log nicht auf der Festplatte? Warum also nicht langsamer? Tatsächlich liegt es daran, dass beim Schreiben des Redo-Protokolls nacheinander auf die Festplatte geschrieben wird. Sequentielles Schreiben auf die Festplatte verkürzt die Suchwartezeit und ist viel schneller als zufälliges Schreiben.

7.3 Warum erscheinen schmutzige Seiten?

Beim Aktualisieren von SQL werden nur der Speicher und das Redo-Log geschrieben. Im Leerlauf werden die Daten im Redo-Log mit der Festplatte synchronisiert. Zu diesem Zeitpunkt sind die Inhalte der Speicherdatenseite und der Festplattendatenseite inkonsistent und es werden fehlerhafte Seiten angezeigt.

7.4 Wann werden verschmutzte Seiten geleert?

Die Redo-Log-Größe der InnoDB-Speicher-Engine ist fest und wird in einem Ring geschrieben, wie unten gezeigt:

Fügen Sie hier eine Bildbeschreibung ein

Wann werden die verschmutzten Seiten geleert? Es gibt mehrere Szenarien:

  1. Das Redo-Log ist voll und fehlerhafte Seiten müssen geleert werden. Diese Situation sollte so weit wie möglich vermieden werden. Denn in diesem Fall kann das gesamte System keine Updates mehr annehmen, d. h. alle Updates müssen blockiert werden.
  2. Wenn der Speicher nicht ausreicht und neue Speicherseiten benötigt werden, müssen einige Datenseiten entfernt werden. Zu diesem Zeitpunkt werden fehlerhafte Seiten geleert.

InnoDB verwendet einen Pufferpool zur Speicherverwaltung. Wenn sich die zu lesende Datenseite nicht im Speicher befindet, muss eine Datenseite im Pufferpool beantragt werden. Zu diesem Zeitpunkt können nur die Datenseiten aus dem Speicher entfernt werden, die am längsten nicht verwendet wurden: Wenn es sich bei der zu entfernenden Seite um eine saubere Seite handelt, kann sie direkt zur Wiederverwendung freigegeben werden; wenn es sich jedoch um eine schmutzige Seite handelt , muss die schmutzige Seite zuerst auf die Festplatte geleert werden. , sie kann erst wiederverwendet werden, nachdem sie zu einer sauberen Seite geworden ist.

  1. MySQL löscht auch einige fehlerhafte Seiten, wenn es denkt, dass das System inaktiv ist.
  2. Wenn MySQL normal heruntergefahren wird, werden alle fehlerhaften Seiten im Speicher auf die Festplatte geleert.

7.5 Warum führt das Leeren schmutziger Seiten dazu, dass SQL langsamer wird?

  1. Das Redo-Protokoll ist voll und fehlerhafte Seiten müssen geleert werden. Zu diesem Zeitpunkt werden alle Systemaktualisierungen blockiert und die Schreibleistung sinkt auf 0, was langsam sein muss. Diese Situation sollte grundsätzlich vermieden werden.
  2. Wenn in einer Abfrage zu viele schmutzige Seiten entfernt werden müssen, verlängert sich auch die Antwortzeit der Abfrage erheblich.

8. Sortieren nach Dateisortierung

Wird die Reihenfolge nach definitiv zu einer langsamen Abfrage führen? Dies ist nicht der Fall, da „Ordnen nach“ normalerweise häufig verwendet wird und wenn die Datenmenge zunimmt und Sie immer noch die Dateisortierung verwenden , kann es leicht zu langsamem SQL kommen.

8.1 Sortieren mit filesort Dateisortierung

Sortieren nach wird häufig verwendet, hauptsächlich um bestimmte Felder zu sortieren. Zum Beispiel das folgende SQL:

select name,age,city from staff where city = '深圳' order by age limit 10;

Wenn Sie den EXPLAIN-Ausführungsplan anzeigen, können Sie sehen, dass in der Spalte „Extra“ die Option „Dateisortierung verwenden“ angezeigt wird, was darauf hinweist, dass die Dateisortierung verwendet wird.

8.2 Warum die Effizienz der Sortierung nach Datei niedrig ist

Warum ist die Abfrageeffizienz relativ gering, wenn zum Sortieren von Dateien „Sortieren nach“ verwendet wird?

Fügen Sie hier eine Bildbeschreibung ein

Sortieren nach Sortierung, unterteilt in Vollfeldsortierung und Zeilensortierung. Es wird max_length_for_sort_datamit der Datenlänge der Ergebniszeile verglichen. Wenn die Datenlänge der Ergebniszeile max_length_for_sort_datadiesen Wert überschreitet, wird eine Zeilen-ID-Sortierung durchgeführt . Im Gegensatz dazu wird eine vollständige Feldsortierung durchgeführt.

8.2.1 Rowid-Sortierung

Bei der Rowid-Sortierung muss im Allgemeinen zur Tabelle zurückgekehrt werden, um Daten zu finden, die die Bedingungen erfüllen, sodass die Effizienz langsamer ist. Das folgende SQL verwendet die Zeilen-ID-Sortierung und der Ausführungsprozess ist wie folgt:

select name,age,city from staff where city = '深圳' order by age limit 10;
  1. MySQL initialisiert den entsprechenden Thread sort_bufferund fügt das zu sortierende Altersfeld und die Primärschlüssel-ID ein.
  2. Suchen Sie im Indexbaum idx_city die erste Primärschlüssel-ID, die die Bedingung von city='Shenzhen' erfüllt, im Bild id=9.
  3. Rufen Sie 主键 id索引树die Datenzeile mit der ID = 9 ab, rufen Sie den Wert des Alters und der Primärschlüssel-ID ab und speichern Sie sie in sort_buffer
  4. Rufen Sie die Primärschlüssel-ID des nächsten Datensatzes ab 索引树 idx_city, d. h. id=13 im Bild
  5. Wiederholen Sie die Schritte 3 und 4, bis der Wert der Stadt nicht gleich Shenzhen ist.
  6. In den vorherigen 5 Schritten haben wir alle Daten gefunden, deren Stadt Shenzhen ist. Sortieren Sie in sort_buffer alle Daten nach Alter.
  7. Durchlaufen Sie die sortierten Ergebnisse, nehmen Sie die ersten 10 Zeilen, kehren Sie entsprechend dem ID-Wert zur Originaltabelle zurück, nehmen Sie die drei Felder Stadt, Name und Alter heraus und geben Sie sie an den Client zurück.

Fügen Sie hier eine Bildbeschreibung ein

8.2.2 Vollständige Feldsortierung

Das gleiche SQL, wenn Sie die vollständige Feldsortierung verwenden, sieht es so aus:

  1. MySQL initialisiert sort_buffer für den entsprechenden Thread und fügt die Felder Name, Alter und Stadt ein, die abgefragt werden müssen.
  2. Suchen Sie von dort 索引树 idx_citynach der ersten Primärschlüssel-ID, die die Bedingung von city='Shenzhen' erfüllt, was im Bild id=9 ist.
  3. Rufen Sie 主键id索引树die Datenzeile mit der ID = 9 ab, nehmen Sie die Werte der drei Felder Name, Alter und Stadt und speichern Sie sie in sort_buffer
  4. Rufen Sie die Primärschlüssel-ID des nächsten Datensatzes ab 索引树idx_city, d. h. id=13 im Bild
  5. Wiederholen Sie die Schritte 3 und 4, bis der Wert der Stadt nicht gleich Shenzhen ist.
  6. In den vorherigen 5 Schritten haben wir alle Daten gefunden, deren Stadt Shenzhen ist. Sortieren Sie in sort_buffer alle Daten nach Alter.
  7. Nehmen Sie die ersten 10 Zeilen entsprechend den Sortierergebnissen und geben Sie sie an den Client zurück

Fügen Sie hier eine Bildbeschreibung ein

sort_bufferDie Größe wird durch einen Parameter gesteuert:sort_buffer_size

  • Wenn die zu sortierenden Daten kleiner als sort_buffer_size sind, erfolgt die Sortierung im sort_buffer-Speicher
  • Wenn die zu sortierenden Daten größer als sort_buffer_size sind, sortieren Sie sie mithilfe von Festplattendateien

Das Sortieren mit Festplattendateien wird effizienter sein . Denn die Daten werden zuerst in sort_buffer abgelegt, wenn dieser fast voll ist. Es sortiert es und legt dann die Daten im sort_buffer in einer temporären Festplattendatei ab. Nachdem alle Daten, die die Bedingungen erfüllen, überprüft und sortiert wurden, wird der Zusammenführungsalgorithmus verwendet, um die vorübergehend sortierten kleinen Dateien auf der Festplatte zusammenzuführen eine bestellte. Große Dateien

8.3 So optimieren Sie die Reihenfolge durch Dateisortierung

order by verwendet die Dateisortierung , die weniger effizient ist. Wie optimieren wir

  • Da die Daten ungeordnet sind, müssen sie sortiert werden. Wenn die Daten selbst geordnet sind, wird die Dateisortierung nicht verwendet. Die Indexdaten selbst sind geordnet. Wir optimieren die Reihenfolge nach Anweisung, indem wir einen Index erstellen.
  • Kann durch Anpassung von Parametern optimiert werden, max_length_for_sort_datazsort_buffer_size

9. Ich kann das Schloss nicht bekommen

Manchmal fragen wir ein sehr einfaches SQL ab, warten aber lange und es werden keine Ergebnisse zurückgegeben. Im Allgemeinen ist die Tabelle zu diesem Zeitpunkt gesperrt oder eine oder mehrere abzufragende Zeilen sind gesperrt . Wir können nur langsam auf die Freigabe der Sperre warten

Zu diesem Zeitpunkt können wir show processlistden Befehl verwenden, um zu sehen, in welchem ​​Status sich die aktuelle Anweisung befindet.

10. delete + in der Unterabfrage verwendet den Index nicht

Wenn delete auf die Unterabfrage in stößt, wird der Index nicht verwendet, selbst wenn ein Index vorhanden ist. Die entsprechende Unterabfrage „select + in“ kann den Index verwenden

Während der tatsächlichen Ausführung optimierte MySQL die Unterabfrage „select in“ und änderte die Unterabfrage in eine Join-Methode, damit sie indiziert werden kann. Aber leider optimiert MySQL das Löschen in der Unterabfrage nicht.

11. Gruppieren nach Verwendung einer temporären Tabelle

Gruppieren nach wird im Allgemeinen für Gruppenstatistiken verwendet. Die darin ausgedrückte Logik besteht darin, nach bestimmten Regeln zu gruppieren.

Angenommen, es gibt eine Tabellenstruktur:

CREATE TABLE `staff` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
  `id_card` varchar(20) NOT NULL COMMENT '身份证号码',
  `name` varchar(64) NOT NULL COMMENT '姓名',
  `age` int(4) NOT NULL COMMENT '年龄',
  `city` varchar(64) NOT NULL COMMENT '城市',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='员工表';

Werfen wir einen Blick auf den Ausführungsplan dieser SQL:

explain select city ,count(*) as num from staff group by city;

Fügen Sie hier eine Bildbeschreibung ein

  • Extra Dieses Feld Using temporarygibt an, dass beim Durchführen der Gruppierung eine temporäre Tabelle verwendet wird.
  • Extra Dieses Feld Using filesortgibt an, dass die Dateisortierung verwendet wird

Wie nutzt Gruppierung nach temporäre Tabellen und Sortierung? Werfen wir einen Blick auf den Ausführungsprozess dieser SQL:

  1. Erstellen Sie eine temporäre Speichertabelle mit zwei Feldern „Stadt“ und „Num“.
  2. Durchsuchen Sie die gesamte Tabelle nach Personaldatensätzen und rufen Sie die Datensätze mit Stadt = „X“ der Reihe nach ab.
    • Stellen Sie fest, ob in der temporären Tabelle eine Zeile mit city='X' vorhanden ist. Wenn nicht, fügen Sie einen Datensatz (X,1) ein.
    • Wenn es in der temporären Tabelle eine Zeile mit city='X' gibt, addieren Sie 1 zum Num-Wert der X-Zeile;
  3. Nachdem die Durchquerung abgeschlossen ist, wird nach der Feldstadt sortiert, und die Ergebnismenge wird an den Client zurückgegeben.

Das Ausführungsdiagramm dieses Prozesses sieht wie folgt aus:

Fügen Sie hier eine Bildbeschreibung ein

Wie werden temporäre Tabellen sortiert?

Legen Sie einfach die zu sortierenden Felder in den Sortierpuffer und kehren Sie nach dem Sortieren zurück. Hierbei ist zu beachten, dass die Sortierung in vollständige Feldsortierung und Zeilenreihensortierung unterteilt ist.

  • Wenn es sich um eine All-Feld-Sortierung handelt, werden die Felder, die von der Abfrage zurückgegeben werden müssen, in den Sortierpuffer gestellt und direkt entsprechend den Sortierfeldern zurückgegeben.
  • Wenn es sich um eine Zeilen-ID-Sortierung handelt, legen Sie einfach die zu sortierenden Felder in den Sortierpuffer, kehren Sie dann noch einmal zur Tabelle zurück und kehren Sie dann zurück

11.2 Wo könnte die Gruppierung langsam sein?

Weil es standardmäßig sowohl temporäre Tabellen als auch Sortierung verwendet. Manchmal können auch temporäre Festplattentabellen verwendet werden

  • Wenn Sie während der Ausführung feststellen, dass die Größe der temporären Speichertabelle die Obergrenze erreicht hat (der Parameter, der diese Obergrenze steuert, ist tmp_table_size), wird die temporäre Speichertabelle in eine temporäre Festplattentabelle konvertiert.
  • Wenn die Datenmenge groß ist, ist es wahrscheinlich, dass die für diese Abfrage erforderliche temporäre Festplattentabelle viel Speicherplatz belegt.

11.3 Wie optimiert man die Gruppierung nach?

In welche Richtungen sollten wir optimieren?

  • Richtung 1: Da es standardmäßig sortiert ist, können wir es einfach nicht sortieren?
  • Richtung 2: Können wir die temporäre Tabelle nicht verwenden, da die temporäre Tabelle ein Faktor ist, der die Leistung der Gruppe nach beeinflusst?

Warum benötigen wir eine temporäre Tabelle, um die Group-By-Anweisung auszuführen? Die semantische Logik der Gruppierung nach besteht darin, die Anzahl des Vorkommens verschiedener Werte zu zählen. Wenn diese Werte von Anfang an geordnet sind, können wir sie dann einfach nach unten scannen und direkt zählen, ohne eine temporäre Tabelle zum Aufzeichnen und Zählen der Ergebnisse zu verwenden?

Diese Optimierungslösungen sind möglich:

  1. Die Felder nach „Gruppieren nach“ werden indiziert
  2. Sortierung nach Null, keine Sortierung erforderlich
  3. Versuchen Sie, nur temporäre Tabellen im Arbeitsspeicher zu verwenden
  4. Verwendung SQL_BIG_RESULT(verwenden Sie direkt die temporäre Tabelle der Festplatte. Es ist nicht erforderlich, von der temporären Tabelle des Speichers in die temporäre Tabelle der Festplatte zu übertragen. Dieser Vorgang ist zeitaufwändig.)

12. Systemhardware oder Netzwerkressourcen

  • Wenn der Speicher des Datenbankservers, die Hardwareressourcen oder die Netzwerkressourcen nicht sehr gut konfiguriert sind, wird er langsamer. Zu diesem Zeitpunkt können Sie die Konfiguration aktualisieren. Das ist so, als ob Ihr Computer manchmal hängen bleibt. Sie können einen Speicherstick oder etwas Ähnliches hinzufügen.
  • Wenn der Datenbankdruck selbst sehr hoch ist, beispielsweise in einem Szenario mit hoher Parallelität, kommt eine große Anzahl von Anforderungen an die Datenbank, die CPU-Auslastung des Datenbankservers ist hoch oder die E/A-Auslastung ist hoch, in diesem Fall die Ausführung von Alle Anweisungen können langsamer werden.

Supongo que te gusta

Origin blog.csdn.net/sco5282/article/details/135198645
Recomendado
Clasificación