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 Hadoop aus und erstellen Images in Docker
>>: Analysieren Sie, wie Sie automatisch Vue-Komponentendokumentation generieren
Inhaltsverzeichnis 1. Geltungsbereich 2. Funktion...
Inhaltsverzeichnis 1. Redo-Log (Transaktionsproto...
BackUpMysql.sh-Skript #!/bin/bash PATH=/bin:/sbin...
Linux-Befehl zum Ändern des Hostnamens 1. Wenn Si...
Responsive Layoutsysteme sind in den heute gängig...
Einführung Wenn eine große Anzahl an Systemen ins...
Inhaltsverzeichnis 1. Sortierfunktion 2. Vorberei...
Inhaltsverzeichnis Lassen Sie uns zunächst über d...
Aufschlag: # chkconfig --list Alle Systemdienste ...
Was ist LNMP: Linux+Nginx+Mysql+(php-fpm,php-mysq...
https-Basisport 443. Er wird für etwas verwendet,...
Windows Server 2019 ist das neueste Server-Betrie...
Heutzutage erlauben viele Websites nicht das direk...
KVM steht für Kernel-based Virtual Machine und is...
Eigenschaften des Listenstils Es gibt 2 Arten von...