Tencent-Interview: Was sind die Gründe, warum eine SQL-Anweisung sehr langsam ausgeführt wird? ---Sehen Sie sich die Serie „Regret“ nicht an (empfohlen)

Tencent-Interview: Was sind die Gründe, warum eine SQL-Anweisung sehr langsam ausgeführt wird? ---Sehen Sie sich die Serie „Regret“ nicht an (empfohlen)

Ehrlich gesagt erfordert diese Frage eine Menge grundlegendes MySQL-Wissen und kann viele Themen aufwerfen, genau wie wenn Sie Ihr Wissen über Computernetzwerke testen und gefragt werden: „Was passiert, nachdem Sie die URL eingegeben und die Eingabetaste gedrückt haben?“, um zu sehen, wie viel Sie sagen können.

Ehrlich gesagt wurde mir diese Frage bei meinem letzten Vorstellungsgespräch bei Tencent gestellt, aber ich habe eine sehr schlechte Antwort gegeben. Ich hatte vorher nie über die entsprechenden Gründe nachgedacht, was dazu führte, dass ich vorerst keine Antwort finden konnte. Deshalb werde ich heute ausführlich über die Gründe sprechen. Ich glaube, dass Sie nach der Lektüre etwas gewinnen werden, andernfalls können Sie mich schlagen.

Fangen Sie an, so zu tun, als ob: Klassifizierungsdiskussion

Wenn eine SQL-Anweisung sehr langsam ausgeführt wird, bedeutet das, dass sie bei jeder Ausführung langsam ist? Oder ist es in den meisten Fällen normal und manchmal sehr langsam? Daher denke ich, dass wir die folgenden beiden Situationen besprechen müssen.

1. Meistens ist es normal, aber gelegentlich kann es sehr langsam sein.

2. Bei unveränderter Datenmenge wurde diese SQL-Anweisung immer sehr langsam ausgeführt.

Lassen Sie uns für diese beiden Situationen die möglichen Gründe analysieren.

Für gelegentlich langsame Situationen

Eine SQL-Anweisung läuft in den meisten Fällen normal, läuft aber gelegentlich sehr langsam. In diesem Fall denke ich, dass mit dem Schreiben der SQL-Anweisung selbst nichts falsch ist, sondern dass es andere Gründe hat. Was könnte das sein?

Die Datenbank aktualisiert schmutzige Seiten und ich bin hilflos

Wenn wir ein Datenelement in die Datenbank einfügen oder ein Datenelement aktualisieren möchten, wissen wir, dass die Datenbank die Daten des entsprechenden Felds im Speicher aktualisiert. Nach der Aktualisierung werden diese aktualisierten Felder jedoch nicht sofort synchronisiert und auf der Festplatte gespeichert. Stattdessen werden diese aktualisierten Datensätze in das Redo-Protokoll geschrieben. Wenn es inaktiv ist, werden die neuesten Daten über das Protokoll im Redo-Protokoll mit der Festplatte synchronisiert.

Die Kapazität des Redo-Logs ist jedoch begrenzt. Wenn die Datenbank immer ausgelastet ist und häufig aktualisiert wird, ist das Redo-Log bald voll. Zu diesem Zeitpunkt besteht keine Möglichkeit, bis zur Leerlaufzeit zu warten, um die Daten mit der Festplatte zu synchronisieren. Sie können nur andere Vorgänge anhalten und sich auf die Synchronisierung der Daten mit der Festplatte konzentrieren. Zu diesem Zeitpunkt führt dies dazu, dass unsere normalen SQL-Anweisungen plötzlich sehr langsam ausgeführt werden. Wenn die Datenbank Daten mit der Festplatte synchronisiert, kann dies daher dazu führen, dass unsere SQL-Anweisungen sehr langsam ausgeführt werden.

Was kann ich tun, wenn ich das Schloss nicht bekomme?

Das ist relativ einfach zu verstehen. Die Anweisung, die wir ausführen möchten, betrifft zufällig eine Tabelle, die gerade von jemand anderem verwendet wird und gesperrt ist. Wir können die Sperre nicht erhalten und können nur warten, bis andere die Sperre freigeben. Oder die Tabelle ist nicht gesperrt, aber eine zu verwendende Zeile ist gesperrt. Zu diesem Zeitpunkt kann ich nichts tun.

Wenn wir feststellen möchten, ob wirklich auf die Sperre gewartet wird, können wir den aktuellen Status mit dem Befehl „show processlist“ anzeigen. Hier möchte ich Sie daran erinnern, dass es am besten ist, einige Befehle aufzuzeichnen. Wie auch immer, ich wurde nach mehreren Befehlen gefragt und weiß nicht, wie ich sie schreiben soll, haha.

Als nächstes analysieren wir die zweite Situation. Ich denke, die Analyse der zweiten Situation ist die wichtigste.

Für die Situation, die immer so langsam war

Wenn diese SQL-Anweisung bei gleicher Datenmenge jedes Mal so langsam ausgeführt wird, sollten Sie Ihre SQL-Schreibweise sorgfältig überdenken. Lassen Sie uns die Gründe analysieren, die dazu führen können, dass unsere SQL-Anweisungen sehr schlecht ausgeführt werden.

Nehmen wir zunächst an, dass wir eine Tabelle mit den folgenden zwei Feldern haben, dem Primärschlüssel-ID und zwei gemeinsamen Feldern c und d.

mysql> CREATE TABLE `t` (
 `id` int(11) NICHT NULL,
 `c` int(11) DEFAULT NULL,
 `d` int(11) DEFAULT NULL,
 PRIMÄRSCHLÜSSEL (`id`)
)ENGINE=InnoDB;

Es wird leider kein Index verwendet.

Der Index wird nicht verwendet. Ich denke, dieser Grund ist etwas, das vielen Leuten einfällt. Wenn Sie beispielsweise diese Anweisung abfragen möchten

wähle * aus t, wobei 100 < c und c < 100000;

Das Feld ist nicht indiziert

Es kommt vor, dass für Ihr C-Feld kein Index vorhanden ist. Es tut uns leid, Sie können nur die gesamte Tabelle scannen und kommen nicht in den Genuss des Nichtvorhandenseins eines Indexes. Daher wird die Abfrageanweisung dieses Mal sehr langsam sein.

Das Feld hat einen Index, aber der Index wird nicht verwendet

Nun haben Sie dem Feld „c“ einen Index hinzugefügt und können eine weitere Abfrage ausführen:

wähle * aus t, wobei c - 1 = 1000;

Ich möchte Ihnen eine Frage stellen: Wird bei dieser Abfragemethode eine Indexabfrage verwendet?

Die Antwort ist nein. Wenn wir Berechnungen auf der linken Seite des Felds durchführen, wird der Index während der Abfrage leider nicht verwendet. Daher sollte jeder auf die Situation achten, in der es einen Index für dieses Feld gibt, das System den Index jedoch aufgrund Ihrer eigenen Nachlässigkeit nicht verwendet.

Die korrekte Abfrage müsste wie folgt lauten

wähle * aus t, wobei c = 1000 + 1;

Jemand könnte sagen, wenn auf der rechten Seite eine Operation steht, können wir dann den Index verwenden? Würde die Datenbank nicht automatisch für uns optimieren und c - 1=1000 automatisch in c = 1000+1 umwandeln?

Es tut mir leid, ich kann Ihnen wirklich nicht helfen, also müssen Sie vorsichtig sein.

Bei Funktionsoperation wird der Index nicht verwendet

Wenn wir während der Abfrage Funktionsoperationen auf den Feldern ausführen, wird der Index nicht verwendet. Zum Beispiel

wähle * aus t, wobei pow(c,2) = 1000;

Hier gebe ich nur ein Beispiel und gehe davon aus, dass die Funktion pow darin besteht, c mit n zu potenzieren. Tatsächlich kann es jedoch sein, dass es keine Funktion pow(c,2) gibt. Tatsächlich ist dies der Berechnung oben links sehr ähnlich.

Wenn eine Anweisung also sehr langsam ausgeführt wird, kann es sein, dass die Anweisung den Index nicht verwendet. Sie müssen jedoch in der Lage sein, die spezifischen Gründe zu analysieren, warum der Index nicht verwendet wird. Die drei oben aufgeführten Gründe dürften die häufigsten sein.

Haha, die Datenbank hat den falschen Index gewählt.

Wenn wir beispielsweise eine Abfrageoperation durchführen,

wähle * aus t, wobei 100 < c und c < 100000;

Wir wissen, dass es einen Unterschied zwischen Primärschlüsselindex und Nicht-Primärschlüsselindex gibt. Der im Primärschlüsselindex gespeicherte Wert sind die Daten des gesamten Zeilenfelds, während der im Nicht-Primärschlüsselindex gespeicherte Wert nicht die Daten des gesamten Zeilenfelds sind, sondern der Wert des Primärschlüsselfelds. Wenn Sie es nicht verstehen, können Sie meinen Artikel „Interviewtipps: Im Zusammenhang mit MySQL-Indizes“ lesen, in dem der Unterschied zwischen Primärschlüsselindizes und Nicht-Primärschlüsselindizes erläutert wird.

Mit anderen Worten, wenn wir den Index des Felds c verwenden, finden wir schließlich den Wert des entsprechenden Primärschlüssels und verwenden dann den auf dem Primärschlüsselwert basierenden Primärschlüsselindex, um die gesamte zurückzugebende Datenzeile zu finden.

Okay, nachdem ich so viel geredet habe, möchte ich Ihnen eigentlich nur sagen, dass das System, selbst wenn Sie einen Index für das Feld c haben, nicht unbedingt den Index für das Feld c verwendet, sondern möglicherweise direkt die gesamte Tabelle durchsucht, um alle Daten zu finden, die 100 < c und c < 100000 erfüllen.

Warum passiert das?

Tatsächlich wird das System bei der Ausführung dieser Anweisung eine Vorhersage treffen: Wird die Anzahl der vom Index C gescannten Zeilen geringer sein, oder wird die Anzahl der Zeilen geringer sein, die durch direktes Scannen der gesamten Tabelle gescannt werden? Natürlich ist es besser, je weniger Scanzeilen es gibt, denn weniger Scanzeilen bedeuten weniger E/A-Vorgänge.

Wenn die gesamte Tabelle gescannt wird, entspricht die Anzahl der Scans der Gesamtzahl der Zeilen in der Tabelle, vorausgesetzt, sie ist n. Wenn der Index c verwendet wird, müssen wir, nachdem wir den Primärschlüssel über den Index c gefunden haben, den Primärschlüsselindex verwenden, um die Daten der gesamten Zeile zu finden, d. h. wir müssen den Index zweimal verwenden. Darüber hinaus wissen wir nicht, wie viele Datenzeilen die Bedingung 100 c < und c < 10000 erfüllen. Was wäre, wenn alle Daten in dieser Tabelle die Bedingung erfüllen? Dies bedeutet, dass bei Verwendung des Index c nicht nur n Zeilen gescannt werden, sondern der Index für jede Datenzeile zweimal gescannt werden muss.

Daher ist es dem System möglich, anstelle einer Indizierung einen vollständigen Tabellenscan durchzuführen. Wie urteilt das System?

Die Beurteilung erfolgt durch die Vorhersage des Systems. Das heißt, wenn der Feldindex c verwendet werden soll, sagt das System voraus, wie viele Zeilen gescannt werden müssen, um den Feldindex c zu verwenden. Wenn vorhergesagt wird, dass eine große Anzahl von Zeilen gescannt wird, wird der Index möglicherweise nicht verwendet, sondern die gesamte Tabelle direkt gescannt.

Die Frage ist also: Wie trifft das System Vorhersagen und Urteile? Ich möchte Ihnen hier erklären, wie das System Urteile fällt, auch wenn mir vom vielen Schreiben ein wenig der Nacken schmerzt.

Das System trifft Urteile auf der Grundlage der Unterscheidungskraft des Index. Je mehr unterschiedliche Werte ein Index hat, desto weniger Indizes mit demselben Wert gibt es, was bedeutet, dass der Index eine höhere Unterscheidungskraft hat. Wir nennen die Diskriminierung auch Kardinalität, das heißt, je höher die Diskriminierung, desto größer die Kardinalität. Eine größere Kardinalität bedeutet daher, dass es weniger Zeilen gibt, die die Bedingung 100 < c und c < 10000 erfüllen.

Daher gilt: Je größer die Kardinalität eines Indexes, desto mehr Vorteile bietet er bei Indexabfragen.

Die Frage ist also, woher kennen wir die Kardinalität dieses Index?

Natürlich wird das System nicht alle Daten durchlaufen, um die Kardinalität eines Index zu ermitteln, da der Aufwand zu hoch ist. Das Indexsystem prognostiziert die Kardinalität des Index, indem es einen Teil der Daten durchläuft, also durch Stichproben.

Nach all dem Gerede kommt nun der entscheidende Punkt, nämlich die Stichprobennahme. Es besteht die Möglichkeit von Fehlern. Das heißt, die Kardinalität des Index c ist tatsächlich sehr groß, aber bei der Stichprobennahme wird vorhergesagt, dass die Kardinalität dieses Indexes sehr klein ist. Wenn beispielsweise die Kardinalität der von Ihnen abgetasteten Daten sehr gering ist, könnten Sie fälschlicherweise annehmen, dass die Kardinalität des Index sehr gering ist. Dann, haha, verwendet das System nicht den C-Index, sondern scannt direkt die gesamte Datei.

Nachdem wir so viel gesagt haben, kommen wir zu dem Schluss, dass das System aufgrund statistischer Fehler nicht den Index, sondern einen vollständigen Tabellenscan verwendet hat, was auch der Grund ist, warum unsere SQL-Anweisungen sehr langsam ausgeführt werden.

Lassen Sie mich hier klarstellen, dass die Systembestimmung, ob der Index verwendet werden soll, und die Vorhersage der Anzahl der Scanzeilen eigentlich nur einer der Gründe sind. Ob diese Abfrageanweisung eine temporäre Tabelle verwenden oder sortieren muss, wirkt sich auch auf die Wahl des Systems aus.

Manchmal können wir jedoch auch abfragen, indem wir den Index erzwingen, zum Beispiel

Wählen Sie * aus t-Force-Index (a), wobei c < 100 und c < 100000;

Wir können auch

Index von t anzeigen;

Um zu prüfen, ob die Kardinalität des Indexes mit der tatsächlichen übereinstimmt

Tabelle t analysieren;

Wenn dies nicht mit der tatsächlichen Situation übereinstimmt, können wir die Kardinalität des Index neu berechnen. Sie können diesen Befehl verwenden

Um die Statistiken erneut zu analysieren.

Da die Kardinalität des Index falsch vorhergesagt wird, bedeutet dies auch, dass das System, wenn unsere Abfrageanweisung mehrere Indizes hat, möglicherweise auch den falschen Index auswählt, was auch ein Grund dafür sein kann, warum die SQL-Ausführung sehr langsam ist.

Okay, das ist alles, was ich vorerst zu sagen habe. Ich finde es toll, dass du dir so viel ausgedacht hast. Ich fasse es im Folgenden zusammen.

### Zusammenfassen

Das Obige ist meine Zusammenfassung und mein Verständnis. Was den letzten Teil betrifft, befürchte ich, dass viele Leute, die sich mit Datenbanken nicht gut auskennen, den falschen Index wählen könnten, deshalb habe ich es ausführlich erklärt. Jetzt werde ich das Obige zusammenfassen.

Wenn eine SQL-Anweisung sehr langsam ausgeführt wird, besprechen wir zwei Situationen:

1. Meistens ist es normal, aber gelegentlich ist es langsam, es gibt die folgenden Gründe

(1) Die Datenbank aktualisiert verschmutzte Seiten. Beispielsweise ist das Redo-Protokoll voll und muss mit der Festplatte synchronisiert werden.

(2) Während der Ausführung tritt eine Sperre auf, beispielsweise eine Tabellensperre oder eine Zeilensperre.

2. Diese SQL-Anweisung wird immer sehr langsam ausgeführt. Dafür gibt es folgende Gründe:

(1) Index nicht verwendet: Beispielsweise hat das Feld keinen Index; der Index kann aufgrund von Berechnungen oder Funktionsoperationen auf dem Feld nicht verwendet werden.

(2) Die Datenbank hat den falschen Index ausgewählt.

Wenn du Ergänzungen hast, kannst du diese auch gerne im Kommentarbereich hinzufügen.

Oben finden Sie eine ausführliche Erklärung der Gründe, warum SQL-Anweisungen langsam ausgeführt werden. Ich hoffe, dass dies für Sie hilfreich sein wird. Wenn Sie Fragen haben, hinterlassen Sie mir bitte eine Nachricht und ich werde Ihnen rechtzeitig antworten. Ich möchte auch allen für ihre Unterstützung der Website 123WORDPRESS.COM danken!

Das könnte Sie auch interessieren:
  • So führen Sie SQL-Anweisungen in Stapeln aus
  • Führen Sie die gespeicherte Prozedur automatisch aus, wenn SQL Server gestartet wird.
  • Fünf ASP-Methoden zur Verbesserung der SQL-Ausführungseffizienz
  • ASP-Online-Ausführung SQL-Anweisungsfunktion
  • Warum erscheint beim Ausführen von dynamischem SQL in ASP immer eine Fehlermeldung? Syntaxfehler bei der Eingabeaufforderungsanweisung
  • MySQL-Code zum Anzeigen der Ausführungszeit von SQL-Anweisungen
  • So schreiben Sie PHP-SQL-Anweisungen
  • Fortgeschrittene MySQL-Datenbank-Interviewfragen mit Antworten
  • SQL-Interviewfrage (überprüfen Sie die angegebene Zeilenanzahl in den Daten)
  • Eine SQL-Interviewfrage mit Antworten

<<:  So führen Sie Hadoop aus und erstellen Images in Docker

>>:  Analysieren Sie, wie Sie automatisch Vue-Komponentendokumentation generieren

Artikel empfehlen

Details zur Funktionsverschachtelung und zu Funktionsabschlüssen in js

Inhaltsverzeichnis 1. Geltungsbereich 2. Funktion...

Einführung in die drei wesentlichen Protokolle für MySQL-Datenbankinterviews

Inhaltsverzeichnis 1. Redo-Log (Transaktionsproto...

Geplantes Teilen von Skripten für MySQL-Datenbanksicherungen

BackUpMysql.sh-Skript #!/bin/bash PATH=/bin:/sbin...

Detaillierte Erläuterung des Linux-Befehls zur Änderung des Hostnamens

Linux-Befehl zum Ändern des Hostnamens 1. Wenn Si...

Beispielcode eines CSS-responsiven Layoutsystems

Responsive Layoutsysteme sind in den heute gängig...

So stellen Sie Dienste in Windows Server 2016 bereit (Grafisches Tutorial)

Einführung Wenn eine große Anzahl an Systemen ins...

Mysql praktische Übungen einfaches Bibliotheksverwaltungssystem

Inhaltsverzeichnis 1. Sortierfunktion 2. Vorberei...

So implementieren Sie eine bidirektionale Bindungsfunktion in vue.js mit reinem JS

Inhaltsverzeichnis Lassen Sie uns zunächst über d...

Allgemeine Betriebsbefehle von MySQL im Linux-System

Aufschlag: # chkconfig --list Alle Systemdienste ...

Tutorial zum Bereitstellen von LNMP und Aktivieren des HTTPS-Dienstes

Was ist LNMP: Linux+Nginx+Mysql+(php-fpm,php-mysq...

Nginx implementiert ein Codebeispiel für die https-Websitekonfiguration

https-Basisport 443. Er wird für etwas verwendet,...

Windows Server 2019 installieren (grafisches Tutorial)

Windows Server 2019 ist das neueste Server-Betrie...

Erstellen einer KVM-Virtualisierungsplattform auf CentOS7 (drei Möglichkeiten)

KVM steht für Kernel-based Virtual Machine und is...

So legen Sie Listenstilattribute in CSS fest (lesen Sie einfach diesen Artikel)

Eigenschaften des Listenstils Es gibt 2 Arten von...