4 Möglichkeiten zur Optimierung von MySQL-Abfragen für Millionen von Daten

4 Möglichkeiten zur Optimierung von MySQL-Abfragen für Millionen von Daten

1. Der Grund, warum das Limit mit der Zeit langsamer wird

Wenn wir eine Begrenzung für die Paginierungsdaten verwenden, werden wir feststellen, dass die Geschwindigkeit beim Anzeigen der ersten paar Seiten sehr hoch ist. Beispielsweise wird die Begrenzung 200,25 sofort angezeigt. Aber die Geschwindigkeit wird mit der Zeit immer langsamer, und insbesondere nach einer Million Datensätzen bleibt es extrem hängen. Was ist das Prinzip dahinter? Schauen wir uns zunächst an, wie die SQL-Abfrage aussieht, wenn wir umblättern:

Wählen Sie * aus t_name, wobei c_name1 = "xxx" ist, sortiert nach c_name2, Limit 2000000,25;

Die Langsamkeit dieser Abfrage wird tatsächlich durch den großen Offset nach dem Limit verursacht. Beispielsweise entspricht die obige Grenze von 2000000,25 dem Scannen von 2000025 Daten durch die Datenbank, wobei die ersten 20000000 Daten verworfen und die restlichen 25 Daten an den Benutzer zurückgegeben werden. Dieser Ansatz ist offensichtlich unvernünftig.

2. Millionen Datensimulation

1. Erstellen Sie Mitarbeitertabellen und Abteilungstabellen und schreiben Sie gespeicherte Prozeduren zum Einfügen von Daten

/*Abteilungstabelle, löschen, falls vorhanden*/
Tabelle löschen, wenn EXISTIERT dep;
Tabelle erstellen dep(
    id int vorzeichenloser Primärschlüssel auto_increment,
    depno mediumint unsigned nicht null Standard 0,
    depname varchar(20) ungleich null Standard "",
    Memo varchar (200) nicht null Standard ""
);

/*Mitarbeitertabelle, löschen, falls vorhanden*/
Tabelle löschen, wenn emp EXISTIERT;
Tabelle emp erstellen(
    id int vorzeichenloser Primärschlüssel auto_increment,
    empno mediumint unsigned nicht null Standard 0,
    empname varchar(20) nicht null Standard "",
    Job varchar(9) nicht null Standard "",
    mgr mediumint unsigniert nicht null Standard 0,
    Einstellungsdatum, Datum und Uhrzeit sind nicht null,
    sal decimal(7,2) nicht null,
    comn decimal(7,2) nicht null,
    depno mediumint unsigniert nicht null Standard 0
);
/* Funktion zum Generieren eines zufälligen Strings */
TRENNUNGSZEICHEN $
FUNKTION löschen, wenn Rand_String EXISTIERT;
CREATE FUNCTION rand_string(n INT) gibt VARCHAR(255) zurück
BEGINNEN
    DECLARE chars_str VARCHAR(100) DEFAULT 'abcdefghijklmlopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    DECLARE return_str VARCHAR(255) DEFAULT '';
    DECLARE i INT DEFAULT 0;
    WÄHREND ich < n DO
    SET return_str = CONCAT(return_str,SUBSTRING(chars_str,FLOOR(1+RAND()*52),1));
    Setze i = i+1;
    ENDE WÄHREND;
    RETURN return_str;
ENDE $
TRENNUNGSZEICHEN;


/*Funktion zum Generieren einer zufälligen Abteilungsnummer*/
TRENNUNGSZEICHEN $
Funktion löschen, wenn rand_num EXISTIERT;
Funktion erstellen rand_num() gibt INT(5) zurück
BEGINNEN
    DECLARE i INT DEFAULT 0;
    SETZE i = FLOOR(100+RAND()*10);
    ZURÜCK i;
ENDE $
TRENNUNGSZEICHEN;
/*Erstellen Sie eine gespeicherte Prozedur: Fügen Sie Daten in die Tabelle emp ein*/
TRENNUNGSZEICHEN $
VERFAHREN löschen, wenn EXISTIERT insert_emp;
PROZEDUR ERSTELLEN insert_emp(IN START INT(10),IN max_num INT(10))
BEGINNEN
    DECLARE i INT DEFAULT 0;
    /*set autocommit =0 Setze Autocommit auf 0 und schalte das Standard-Commit aus*/
    SETZEN Sie Autocommit = 0;
    WIEDERHOLEN
    Setze i = i + 1;
    INSERT INTO emp(empno,empname,job,mgr,hiredate,sal,comn,depno) VALUES ((START+i),rand_string(6),'VERKÄUFER',0001,now(),2000,400,rand_num());
    BIS i = max_num
    ENDE WIEDERHOLUNG;
    BEGEHEN;
ENDE $
TRENNUNGSZEICHEN;

/*Erstellen Sie eine gespeicherte Prozedur: Fügen Sie Daten in die Dep-Tabelle ein*/
TRENNUNGSZEICHEN $
VERFAHREN löschen, falls EXISTIERT: insert_dept;
PROZEDUR ERSTELLEN insert_dept(IN START INT(10), IN max_num INT(10))
BEGINNEN
    DECLARE i INT DEFAULT 0;
    SETZEN Sie Autocommit = 0;
    WIEDERHOLEN
    Setze i = i+1;
    INSERT INTO dep( depno, depname, memo) VALUES((START+i), Randzeichenfolge(10), Randzeichenfolge(8));
    BIS i = max_num
    ENDE WIEDERHOLUNG;
    BEGEHEN;
ENDE $
TRENNUNGSZEICHEN;

2. Führen Sie die gespeicherte Prozedur aus

/*120 Datensätze einfügen*/
rufen Sie insert_dept(1,120) auf;
/*Fügen Sie 5 Millionen Daten ein*/
rufen Sie insert_emp(0,5000000) auf;

Das Einfügen von 5 Millionen Datensätzen kann langsam sein

3.4 Abfragemethoden

1. Gewöhnliches Limit-Paging

/*Offset ist 100, nimm 25*/
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a nach links verbinden dep b auf a.depno = b.depno, sortiert nach a.id, desc-Limit 100,25;
/*Offset ist 4800000, nimm 25*/
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a nach links verbinden dep b auf a.depno = b.depno, sortiert nach a.id, desc-Limit 4800000,25;

Ausführungsergebnisse

[SQL]
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a nach links verbinden dep b auf a.depno = b.depno, sortiert nach a.id, desc-Limit 100,25;
Betroffene Zeilen: 0
Zeit: 0,001 s
[SQL]
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a nach links verbinden dep b auf a.depno = b.depno, sortiert nach a.id, desc-Limit 4800000,25;
Betroffene Zeilen: 0
Zeit: 12.275s

Je weiter Sie gehen, desto langsamer ist die Abfrageeffizienz.

2. Verwenden Sie Indexabdeckung + Unterabfrageoptimierung

Da wir über die Primärschlüssel-ID verfügen und einen Index darauf erstellt haben, können wir zuerst den ID-Wert der Startposition im Indexbaum finden und dann die Zeilendaten basierend auf dem gefundenen ID-Wert abfragen.

/*Die Unterabfrage ruft die ID der um 100 verschobenen Position ab und erhält 25 nach dieser Position*/
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id >= (ID aus emp auswählen, sortiert nach ID-Limit 100,1)
Sortieren nach A.ID-Limit 25;

/*Die Unterabfrage ruft die ID der Position mit dem Offset 4800000 ab und erhält 25 nach dieser Position*/
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id >= (ID aus Emp auswählen, sortiert nach ID-Limit 4800000,1)
Sortieren nach A.ID-Limit 25;

Ausführungsergebnisse

[SQL]
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id >= (ID aus emp auswählen, sortiert nach ID-Limit 100,1)
Sortieren nach A.ID-Limit 25;
Betroffene Zeilen: 0
Zeit: 0,106 s

[SQL]
Wählen Sie a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id >= (ID aus Emp auswählen, sortiert nach ID-Limit 4800000,1)
Sortieren nach A.ID-Limit 25;
Betroffene Zeilen: 0
Zeit: 1.541s

3. Definieren Sie die Ausgangsposition neu

Gilt für Tabellen, deren Primärschlüssel automatisch inkrementell sind

/*Denken Sie daran, dass die ID der letzten Daten bei der vorherigen Paginierung 100 ist. Daher überspringen wir 100 und scannen die Tabelle ab 101*/
Wählen Sie a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id > 100, sortiert nach a.id-Limit 25;

/*Denken Sie daran, dass die ID der letzten Daten bei der vorherigen Paginierung 4800000 ist. Daher überspringen wir 4800000 und scannen die Tabelle ab 4800001*/
Wählen Sie a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id > 4800000
Sortieren nach A.ID-Limit 25;
[SQL]
Wählen Sie a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id > 100, sortiert nach a.id-Limit 25;
Betroffene Zeilen: 0
Zeit: 0,001 s

[SQL]
Wählen Sie a.id,a.empno,a.empname,a.job,a.sal,b.depno,b.depname
von emp a links verbinden dep b auf a.depno = b.depno
wobei a.id > 4800000
Sortieren nach A.ID-Limit 25;
Betroffene Zeilen: 0
Zeit: 0.000s

Dies ist am effizientesten. Unabhängig davon, wie die Seiten aufgeteilt werden, ist der Zeitaufwand grundsätzlich gleich, da nach der Ausführung der Bedingungen nur 25 Daten gescannt werden.

4. Downgrade-Strategie (Baidus Ansatz)

Diese Strategie ist die einfachste und effektivste, da allgemeine Big-Data-Abfragen Suchbedingungen haben und niemand dem Inhalt nach Seite 100 Aufmerksamkeit schenkt. Wenn die Anzahl der vom Benutzer abgefragten Seiten zu groß ist, wird einfach ein Fehler zurückgegeben. Beispielsweise kann Baidu nur Seite 76 durchsuchen.

Oben sind die Details von 4 Methoden zur Abfrageoptimierung für Millionen von MySQL-Daten aufgeführt. Weitere Informationen zur MySQL-Abfrageoptimierung für Millionen von Daten finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • MySQL fügt automatisch Millionen simulierter Datenoperationscodes ein
  • Fähigkeiten zur Optimierung der Paginierung der Leistung einer MySQL-Einzeltabelle mit Millionen von Datensätzen
  • So fügen Sie schnell Millionen von Testdaten in MySQL ein
  • Implementierung des Einfügens von Millionen von Datensätzen in eine MySQL-Datenbank innerhalb von 10 Sekunden

<<:  CSS-Code zur Steuerung der Hintergrundfarbe der Webseite

>>:  Detaillierte Erläuterung der Einführung in die JavaScript-Funktion

Artikel empfehlen

Vue ruft die PC-Kamera auf, um die Fotofunktion zu realisieren

In diesem Artikelbeispiel wird der spezifische Co...

Verwenden Sie CSS, um zwischen dem Dunkelmodus und dem Hellmodus zu wechseln

In der fünften Ausgabe von Web Skills wird ausdrü...

js realisiert die Bildschneidefunktion

In diesem Artikelbeispiel wird der spezifische Co...

Eine ausführliche Zusammenfassung der Überlegungen zu MySQL-Zeiteinstellungen

Existiert die Zeit wirklich? Manche Menschen glau...

Tutorial zur Verwendung des Multitail-Befehls unter Linux

MultiTail ist eine Software zum gleichzeitigen Üb...

Über die Fallstricke bei der Implementierung der angegebenen Kodierung in MySQL

Vorne geschrieben Umgebung: MySQL 5.7+, MySQL-Dat...

CSS-Einstellung Div-Hintergrundbild-Implementierungscode

Das Hinzufügen einer Hintergrundbildsteuerung zu ...

Vue-Anpassungsmethode für Großbildschirme

In diesem Artikelbeispiel wird der spezifische Co...

Docker stellt eine MySQL-Remoteverbindung bereit, um 2003-Probleme zu lösen

Herstellen einer Verbindung mit MySQL Hier verwen...

Unterschiede zwischen FLOW CHART und UI FLOW

Viele Konzepte im UI-Design mögen in der Formulie...

Detaillierte Erläuterung der gespeicherten Prozedur „MySql View Trigger“

Sicht: Wenn eine temporäre Tabelle wiederholt ver...

HTML-Code einer Webseite: Erzeugung von Lauftext

In diesem Abschnitt beschreibt der Autor die spez...