Hintergrund Als ich kürzlich SQL-Anweisungen schrieb, war ich mir nicht sicher, ob ich IN oder Exists wählen sollte. Also schrieb ich das SQL beider Methoden auf, um die Ausführungseffizienz zu vergleichen. Ich stellte fest, dass die Abfrageeffizienz von IN viel höher ist als die von Exists, also nahm ich natürlich an, dass die Effizienz von IN besser ist als die von Exists. Im Einklang mit dem Prinzip, den Dingen auf den Grund zu gehen, möchte ich jedoch wissen, ob diese Schlussfolgerung auf alle Szenarien zutrifft und warum dieses Ergebnis auftritt. Experimentelle Daten Meine experimentellen Daten umfassen zwei Tabellen: t_author-Tabelle und t_poetry-Tabelle. t_author-Tabelle, 13355 Datensätze; Die entsprechende Tabellenstruktur ist wie folgt:
Ausführungsplananalyse im Ausführungsprozess SQL-Beispiel: Sein Ausführungsplan: Existiert Ausführungsprozess SQL-Beispiel: Sein Ausführungsplan: (1) Rufen Sie zunächst alle Datensätze aus der Tabelle tabA ab. Experimentelle Verfahren Das Experiment analysiert die SQL-Anweisungen „IN“ und „Exists“ für denselben Ergebnissatz.
SQL-Anweisung mit „Existiert“:
Daten aus dem ersten Experiment t_author-Tabelle, 13355 Datensätze; t_poetry-Tabelle, Unterabfrage-Filterergebnissatz, wobei poetry_id>293650, 121 Datensätze; Ausführungsergebnisse Die Verwendung von „exists“ dauert 0,94 Sekunden, die Verwendung von „in“ 0,03 Sekunden. „IN“ ist effizienter als „Exists“. Ursachenanalyse Der Ergebnisset der Unterabfrage der Tabelle t_poetry ist sehr klein, und beide können Indizes der Tabelle t_poetry verwenden, und der Verbrauch der Unterabfrage t_poetry ist grundsätzlich derselbe. Der Unterschied zwischen beiden besteht darin, dass bei Verwendung von „in“ die Tabelle „t_author“ den Index verwenden kann: Bei Verwendung von exists wird die Tabelle t_author vollständig gescannt: Wenn der Unterabfrage-Ergebnissatz klein ist, spiegelt sich die Abfragezeit hauptsächlich in der Durchquerung der t_author-Tabelle wider. Zweite experimentelle Daten t_author-Tabelle, 13.355 Datensätze; t_poetry-Tabelle, Unterabfrage-Filterergebnissatz, wobei poetry_id>3650, 287.838 Datensätze; Ausführungszeit Die Verwendung von exists dauert 0,12 Sekunden, die Verwendung von in 0,48 Sekunden. Exists ist effizienter als IN . Ursachenanalyse Die Indexverwendung der beiden Experimente stimmt mit der des ersten Experiments überein. Der einzige Unterschied ist die Größe des Unterabfragefilter-Ergebnissatzes. Die experimentellen Ergebnisse unterscheiden sich jedoch von denen des ersten. In diesem Fall ist der Ergebnissatz der Unterabfrage sehr groß. Schauen wir uns den MySQL-Abfrageplan an: Bei Verwendung von exists ändert die Änderung des Datenvolumens den Ausführungsplan nicht. Aufgrund des großen Unterabfrageergebnissatzes verwenden MySQL-Versionen nach 5.5 jedoch Block Nested-Loop (Block Nested Loop, Einführung eines Join-Puffer, ähnlich der Cache-Funktion), wenn die Abfrageergebnisse von exists abgeglichen werden, was sich erheblich auf die Abfrageeffizienz auswirkt, insbesondere wenn der Unterabfrageergebnissatz groß ist, kann dies die Abfrageabgleicheffizienz erheblich verbessern: Experimentelle Schlussfolgerung Basierend auf den beiden oben genannten Experimenten und ihren Ergebnissen können wir den Ausführungsprozess von IN und Exists klar verstehen und die anwendbaren Szenarien von IN und Exists zusammenfassen: IN-Abfragen können Indizes sowohl für innere als auch für äußere Tabellen verwenden; Exists-Abfragen können Indizes nur für innere Tabellen verwenden. Wenn der Ergebnissatz der Unterabfrage groß und die äußere Tabelle klein ist, beginnt der Block Nested Loop von Exists eine Rolle zu spielen und gleicht den Mangel aus, dass die äußere Tabelle keine Indizes verwenden kann. Die Abfrageeffizienz wird dann besser sein als bei IN. Wenn der Unterabfrageergebnissatz klein und die externe Tabelle groß ist, ist der Optimierungseffekt der Blockverschachtelungsschleife von Exists nicht offensichtlich, und der Vorteil des externen Tabellenindex von IN spielt eine wichtige Rolle. In diesem Fall ist die Abfrageeffizienz von IN besser als die von Exists. Was online gesagt wird, ist ungenau. Tatsächlich bezieht sich die „Größe der Tabelle“ nicht auf die interne Tabelle und die externe Tabelle, sondern auf die externe Tabelle und den Unterabfrage-Ergebnissatz . Der letzte Punkt ist zugleich der wichtigste: Es gibt keine absolute Wahrheit auf der Welt. Das Wesen der Dinge zu erfassen und praktische Überprüfungen für verschiedene Szenarien durchzuführen, ist die zuverlässigste und effektivste Methode. Ergänzende Informationen zu während des Experiments festgestellten Problemen Bei der Analyse der oben genannten Exist-Anweisungen unter verschiedenen Datensätzen habe ich festgestellt, dass der Zeitaufwand umso geringer ist, je größer der Datensatz ist, was sehr merkwürdig ist.
Mögliche Gründe: Je größer der Bedingungswert ist, desto später erfolgt die Abfrage, desto mehr Datensätze müssen durchlaufen werden, was zu einem höheren Zeitaufwand führt. Diese Erklärung muss noch weiter überprüft werden. Das könnte Sie auch interessieren:
|
<<: So zeigen Sie laufende Hintergrundprogramme in Linux an und beenden sie
>>: Detaillierte Erläuterung der benutzerdefinierten Vue-Anweisungen und ihrer Verwendung
Inhaltsverzeichnis Globale Variable „globalData“ ...
Inhaltsverzeichnis MySQL-Abfragebaumstruktur 1. Ü...
In diesem Artikel wird der spezifische Code der b...
Strukturbezogene Tags ----------------------------...
Inhaltsverzeichnis Docker-Images Was ist ein Spie...
In diesem Artikel wird der spezifische Code von U...
In diesem Artikelbeispiel wird der spezifische Co...
Inhaltsverzeichnis Grundlegende allgemeine MySQL-...
Hier sind 30 Best Practices für HTML-Anfänger. 1....
Inhaltsverzeichnis Tabellenkonflikte finden und b...
MySQL-Vollsicherung 1. Aktivieren Sie das Binärpr...
1. Die mysqldump-Sicherungsmethode verwendet eine...
Ziel Zeigen Sie eine der Daten im iostat-Befehl i...
Wie können Sie die Leistung einer Webseite verbes...
1. Was ist Continuous Delivery Der Ausgabeprozess...