Wenn ich an das Wort „Sortieren“ denke, ist mein erster Eindruck, dass fast alle Apps eine Sortierfunktion haben. Taobao-Produkte werden nach Kaufzeitpunkt sortiert und Bilibili-Kommentare werden nach Popularität sortiert … Was fällt Ihnen als Erstes zum Sortieren in MySQL ein? Stichwort sortieren nach? Ist es am besten, einen Index für das Order-by-Feld zu haben? Sind die Blattknoten schon geordnet? Oder sollten wir das Sortieren innerhalb von MySQL so weit wie möglich vermeiden? Die Ursache des VorfallsNehmen wir nun an, es gibt eine Freundestabelle eines Benutzers: CREATE TABLE `Benutzer` ( `id` int(10) AUTO_INCREMENT, `Benutzer-ID` int(10), `Freundadresse` varchar(1000), `Freundname` varchar(100), Primärschlüssel (`id`), SCHLÜSSEL `user_id` (`user_id`) )ENGINE=InnoDB; Derzeit gibt es in der Tabelle zwei Punkte, die Aufmerksamkeit erfordern:
Eines Tages erhielt ein Junior-Entwicklungsingenieur namens Xiaoyuan eine Anfrage von einem Junior-Produktmanager namens Xiaowang: Also hat Xiaoyuan das folgende SQL geschrieben: wähle friend_name,friend_addr vom Benutzer, wobei user_id=? nach Namen sortieren Im Handumdrehen ging Xiaoyuan mit großem Tamtam online. Alles lief gut, bis eines Tages ein Kommilitone aus dem Fach Operations Research folgende Frage stellte: Wählen Sie Friend_Name , Friend_Addr vom Benutzer aus, wobei User_ID = 10086 nach Namen sortiert ist Diese Abfrage war jedoch viel langsamer als üblich und die Datenbank meldete eine langsame Abfrage. Xiaoyuan geriet in Panik: Was ist los? Es gibt einen Index für die Benutzer-ID und ich habe geschickterweise nur „Select Friend_Name, Friend_Addr“ anstelle von „Select *“ verwendet. Zu diesem Zeitpunkt beruhigte sich Xiaoyuan immer wieder selbst und sagte sich, er solle ruhig bleiben, bis ihm plötzlich einfiel, dass es einen „explain“-Befehl gab. Er beschloss, „explain“ zu verwenden, um den Ausführungsplan dieses SQL zu überprüfen. Nachdem Xiaoyuan „explain“ verwendet hatte, fand er im zusätzlichen Feld ein gefährlich aussehendes Wort: „using filesort“. „Diese Abfrage verwendet tatsächlich die legendäre Dateisortierung, aber wenn eine Person nicht viele Freunde hat, sollte sie auch mit Dateisortierung schnell sein“, es sei denn, user_id=10086 hat viele Freunde. Später überprüfte Xiaoyuan und stellte fest, dass dieser Benutzer tatsächlich mehr als 100.000 Freunde hat~. Der kleine Affe war in Gedanken versunken und dachte: Es scheint, ich muss die Schuld dafür auf mich nehmen. 100.000 Datenpunkte sind doch etwas zu viel. Und was ist das Sortierprinzip von Filesort? Sortieren von AnatomiedateienJemand könnte sagen, dass das obige Problem darin besteht, dass 10 W Daten zu groß sind und es langsam ist, auch wenn es nicht sortiert ist. Das macht tatsächlich Sinn. Wenn 10 W Daten auf einmal überprüft werden, werden sowohl der MySQL-Speicherpuffer als auch die Netzwerkbandbreite sehr stark beansprucht. Was ist, wenn ich ein Limit von 1000 hinzufüge? Das Problem der Netzwerkbandbreite wurde definitiv gelöst, da die Gesamtgröße der Datenpakete kleiner geworden ist, aber das Problem der Verwendung von Filesort wurde nicht gelöst. Angesichts dessen haben Sie möglicherweise Fragen: Werden die Dateien durch die Verwendung von Filesort sortiert? Wie sind sie in der Datei sortiert? Oder lassen Sie mich Folgendes fragen: Wie würden Sie vorgehen, wenn Sie mit der Gestaltung einer Sorte beauftragt würden? Lassen Sie uns vor dem Hintergrund dieser Fragen und Überlegungen einen Blick auf die technischen Schwierigkeiten werfen, die mit der Verwendung von Filesort verbunden sind, und wie diese gelöst werden können.
Alles sieht reibungslos aus, aber sort_buffer nimmt Speicherplatz ein, was unangenehm ist. Der Speicher selbst ist nicht unendlich, er hat definitiv eine Obergrenze. Natürlich kann sort_buffer nicht zu klein sein. Wenn er zu klein ist, macht es nicht viel Sinn. In der InnoDB-Speicher-Engine beträgt dieser Wert standardmäßig 256 K. mysql> Variablen wie „sort_buffer_size“ anzeigen; +------------------+--------+ | Variablenname | Wert | +------------------+--------+ | Sortierpuffergröße | 262144 | +------------------+--------+ Das heißt, wenn die in den Sortierpuffer einzufügenden Daten größer als 256 KB sind, funktioniert die Schnellsortiermethode im Sortierpuffer definitiv nicht. Zu diesem Zeitpunkt fragen Sie sich möglicherweise: Kann MySQL nicht automatisch entsprechend der Datengröße erweitert werden? Nun, MySQL ist ein Multithread-Modell. Wenn jeder Thread erweitert wird, wird der anderen Funktionen zugewiesene Puffer kleiner (z. B. Änderungspuffer usw.), was sich auf die Qualität anderer Funktionen auswirkt. Zu diesem Zeitpunkt müssen wir die Sortiermethode ändern. Ja, dies ist die eigentliche Dateisortierung, d. h. die temporäre Datei auf der Festplatte. MySQL verwendet die Idee der Zusammenführungssortierung, um die zu sortierenden Daten in mehrere Teile aufzuteilen. Nachdem jedes Datenstück im Speicher sortiert wurde, wird es in eine temporäre Datei abgelegt. Schließlich werden die Daten dieser sortierten temporären Dateien zusammengeführt und erneut sortiert. Dies ist ein typisches Teile-und-herrsche-Prinzip. Die spezifischen Schritte sind wie folgt:
Das Sortieren von Dateien ist sehr langsam. Gibt es eine andere Lösung?Durch den obigen Sortiervorgang wissen wir, dass eine Dateisortierung erforderlich ist, wenn die zu sortierenden Daten sehr groß sind und die Größe von sort_buffer überschreiten. Die Dateisortierung umfasst Stapelsortierung und Zusammenführung, was sehr zeitaufwändig ist. Die Hauptursache dieses Problems ist, dass sort_buffer nicht ausreicht. Ich weiß nicht, ob Sie bemerkt haben, dass unser friend_name sortiert werden muss, aber friend_addr auch in sort_buffer gestopft wird. Auf diese Weise ist die Größe einer einzelnen Datenzeile gleich der Länge von friend_name + der Länge von friend_addr. Können wir nur das Feld friend_name in sort_buffer speichern? Auf diese Weise ist der gesamte Nutzungsraum groß und temporäre Dateien werden möglicherweise nicht benötigt. Richtig, dies ist eine weitere Sortieroptimierung, über die ich als nächstes sprechen werde: Rowid-Sortierung. Die Idee der Zeilen-ID-Sortierung besteht darin, unnötige Daten aus dem Sortierpuffer fernzuhalten und nur die erforderlichen Daten im Sortierpuffer zu behalten. Was sind Ihrer Meinung nach also die erforderlichen Daten? Geben Sie einfach den Namen Ihres Freundes ein. Das wird definitiv nicht funktionieren. Was passiert mit friend_addr, nachdem die Sortierung abgeschlossen ist? Daher müssen wir auch die Primärschlüssel-ID eingeben. Nach dem Sortieren können wir über die ID zur Sekundärtabelle zurückkehren und die Friend_Addr abrufen. Daher ist der allgemeine Prozess wie folgt:
Hier sind tatsächlich einige Punkte zu beachten:
Die Frage ist also, wie MySQL zwischen den beiden Methoden wählen sollte. Die Entscheidung, welche Methode verwendet wird, hängt von einer bestimmten Bedingung ab. Die Bedingung ist die Länge einer einzelnen Zeile im Sortierpuffer. Wenn die Länge zu groß ist (die Länge von friend_name + friend_addr), wird rowid verwendet. Andernfalls verwendet die erste Methode den Längenstandard basierend auf max_length_for_sort_data, der standardmäßig 1024 Byte beträgt: mysql> Variablen wie „max_length_for_sort_data“ anzeigen; +--------------------------+----------+ | Variablenname | Wert | +--------------------------+----------+ | maximale Länge für Sortierdaten | 1024 | +--------------------------+----------+ Ich möchte nicht zum Tisch zurückkehren und ihn erneut sortierenTatsächlich müssen alle der oben genannten Methoden, egal welche verwendet wird, zur Tabelle zurückkehren und sortieren. Die Rückkehr zur Tabelle erfolgt, weil im sekundären Index kein Zielfeld vorhanden ist, und die Sortierung erfolgt, weil die Daten nicht geordnet sind. Wenn im sekundären Index ein Zielfeld vorhanden ist und dieses bereits sortiert ist, wäre das dann nicht das Beste aus beiden Welten? Das ist richtig, es ist ein gemeinsamer Index. Wir müssen nur einen gemeinsamen Index von (user_id, friend_name, friend_addr) erstellen. Auf diese Weise kann ich die Zieldaten über diesen Index abrufen, und das Feld friend_name ist bereits sortiert. Es gibt auch ein Feld friend_addr. Dies ist in einem Durchgang erledigt, ohne zur Tabelle zurückzukehren oder erneut zu sortieren. Daher ist der allgemeine Ablauf für das obige SQL wie folgt:
Obwohl gemeinsame Indizes dieses Problem lösen können, sollten sie in tatsächlichen Anwendungen nicht blind erstellt werden. Sie sollten anhand der tatsächlichen Geschäftslogik entscheiden, ob sie erstellt werden müssen. Wenn ähnliche Abfragen nicht häufig sind, müssen Sie sie nicht erstellen, da gemeinsame Indizes mehr Speicherplatz beanspruchen und Wartungskosten verursachen. Zusammenfassen
Oben finden Sie den detaillierten Inhalt der Sortierung der MySQL-Datenbank. Weitere Informationen zur Sortierung der MySQL-Datenbank finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: Problem mit Zeitzonenfehler im Docker-Container
>>: Eine Codezeile löst verschiedene IE-Kompatibilitätsprobleme (IE6-IE10)
Inhaltsverzeichnis React-Native-Projektinitialisi...
So konfigurieren Sie benutzerdefinierte Pfadalias...
30 kostenlose englische Ribbon-Schriftarten in hoh...
Überblick In tatsächlichen Geschäftsszenarioanwen...
Die Pseudoklasse „Before/After“ entspricht dem Ei...
Wie definiert man komplexe Komponenten (Klassenko...
Wenn wir eine neue CSS-Funktion verwenden möchten...
Umfeld: 1. CentOS6.5 X64 2.mysql-5.6.34-linux-gli...
Bei der Verwendung von MySQL werden häufig Trigge...
Wenn wir SQL zum Extrahieren von Daten verwenden,...
Die Installation der MySQL-Software und die Daten...
Inhaltsverzeichnis 1. Direkte Zuordnung 2. Oberfl...
1. Melden Sie sich bei der MySQL-Datenbank an mys...
Nginx unterstützt drei Möglichkeiten zum Konfigur...
Der Ursprung des Problems Das erste Mal, dass ich...