it-swarm.com.de

Die Auswahl einer Abfrage dauert länger als nötig

Ich habe eine MySQL-Datenbanktabelle mit fast 23 Millionen Datensätzen. Diese Tabelle hat keinen Primärschlüssel, da nichts eindeutig ist. Es hat 2 Spalten, beide sind indiziert. Unten ist seine Struktur:

enter image description here

Nachfolgend einige Daten:

enter image description here

Jetzt habe ich eine einfache Abfrage ausgeführt:

SELECT `indexVal` FROM `key_Word` WHERE `hashed_Word`='001'

Leider dauerte es mehr als 5 Sekunden, um die Daten abzurufen und mir zu zeigen. Mein zukünftiger Tisch wird 150 Milliarden Datensätze haben, also ist diese Zeit sehr, sehr hoch.

Ich habe den Befehl Explain ausgeführt, um zu sehen, was los ist. Ergebnis ist unten.

enter image description here

Dann habe ich das Profil mit dem folgenden Befehl ausgeführt.

SET profiling=1;
SELECT `indexVal` FROM `key_Word` WHERE `hashed_Word` = '001';
SHOW profile;

Unten sehen Sie das Ergebnis der Profilerstellung:

enter image description here

Nachfolgend finden Sie weitere Informationen zu meinem Tisch:

enter image description here

Warum dauert das so lange? Sie sind auch indiziert! In Zukunft muss ich viele LIKE -Befehle ausführen, daher dauert dies zu lange. Was ist schief gelaufen?

9
Lemon Juice

Sie haben gefragt ", warum dies zu lange dauert ?". Sie sagten auch " Leider dauerte es mehr als 5 Sekunden, um die Daten abzurufen und mir zu zeigen ". Außerdem haben Sie die Profilerstellungsausgabe Ihrer Abfrage gemeldet.

Wie Sie selbst sehen können, zählt die vom Profiler für jeden Schritt gemeldete Summe der Zeiten 0,000154 Sekunden. Aus Sicht des Profilers wurde die Abfrage also in einer solchen Zeit abgeschlossen (0,000154).

Warum erhalten Sie Ergebnisse in " ... mehr als 5 Sekunden? ".

Sie sagten, Sie filtern eine 23-Millionen-Datensatztabelle mit einem 3-Zeichen-Feld. Leider teilen Sie uns nicht mit, wie viele Datensätze Ihre Abfrage zurückgibt ... aber dank der bereitgestellten EXPLAIN SELECT scheint Ihre Abfrage 336052 Datensätze zurückgegeben zu haben.

Es scheint auch, dass alle Ihre Aktivitäten über eine GUI (PHPMyAdmin?) Laufen.

Nach alledem können wir Ihre ursprüngliche Frage wie folgt umformulieren:

"Warum erhalte ich in meiner GUI 336.052 Datensätze, die in mehr als 5 Sekunden angezeigt werden, wenn die MySQL-Ausführungszeit für die zugehörige Abfrage 0,000154 Sekunden beträgt?"

Die Antwort ist meiner Meinung nach recht einfach: 5 Sekunden sind die (wirklich niedrige) Zeit, um 336.052 Datensätze auf dem Pfad laufen zu lassen: MySQL-Engine => MySQL-Client-Bibliotheken => PHP MySQL-Modul => Apache => Netzwerk => Ihr PC TCP/IP-Stack => Browser => DOM-Parser/Builder/etc. => Gerenderte HTML-Seite.

Nach meiner bisherigen Erfahrung ist die für die Übermittlung der Ergebnisse erforderliche Zeit "normalerweise" viel höher als die zum Abrufen solcher Daten erforderliche Zeit. Dies gilt insbesondere dann, wenn Bibliotheken wie PHP-MySQL oder Perl-DBD-MySQL beteiligt sind: Sie benötigen wirklich viel Zeit, um die Datensätze abzurufen nachdem MySQL alle richtig identifiziert (... und extrahiert) hat.

Wie kann man dieses Problem lösen?

Wieder ganz einfach: Sind Sie wirklich sicher, dass Sie [~ # ~] alle [~ # ~] des 336.052-Datensatzes in einem einzigen, ganz, Datensatz?

  • Wenn Ihre Antwort wirklich "JA! Ich brauche alle" lautet, wird Ihre Anwendung die PAGINATION und/oder die BENUTZER-Interaktion selbst erledigen und ... sobald sie alle diese Daten gesammelt hat, wird sie wahrscheinlich viel Zeit aufwenden Interaktion mit dem Benutzer ohne weitere MySQL-Interaktion erforderlich. In einem solchen Fall sollte es kein Problem sein, 5 Sekunden (oder sogar länger) zu warten.

  • Wenn Ihre Antwort "NEIN, ich möchte mich mit einer" menschlicheren "Datensatzgröße" befassen, müssen Sie Ihre Abfrage (zumindest) verfeinern, damit Sie einen "menschlicheren" Datensatz erhalten (Zehner oder, "). höchstens Hunderte). In einem solchen Fall wette ich, dass Sie Ihr Ergebnis in kürzerer Zeit erhalten.


Übrigens: Dies ist genau das gleiche Problem, das Sie in diesem anderen Beitrag bei ServerFault erlebt haben: 88 Sekunden, damit 132 Millionen Datensätze auf dem .... nicht-mysql-streng verwandten magischen Pfad übertragen werden können :-)

10
  1. Überprüfen Sie die MySQL innodb_buffer_pool_size. Es sollte groß genug sein - je mehr, desto besser. Aber nicht zu viel, um einen Betriebssystemwechsel zu vermeiden.

    show variables like 'innodb_buffer_pool_size'
    

    zeigt die Puffergröße in Bytes an.

  2. Überprüfen Sie die Abfrage mehrmals. Der erste Lauf kann zu lang sein, da die Daten von der Festplatte in den Speicher gelesen werden sollen. Wenn Sie die Abfrage zum ersten Mal ausführen, befinden sich die Daten immer noch nicht im Innodb-Puffer und müssen von der Festplatte gelesen werden. Das ist viel langsamer, als wenn sich die Daten bereits im Cache befinden würden. Führen Sie die Abfrage daher einige Male aus, um sicherzustellen, dass sie aus dem Cache bereitgestellt wird.

  3. Deaktivieren Sie den Abfrage-Cache, da jeder nachfolgende Lauf von ihm ausgeführt wird und die Testergebnisse verzerrt. In MySQL gibt es einen Mechanismus, der als "Abfrage-Cache" bezeichnet wird und zum Speichern von Abfragen zusammen mit ihren Ergebnissen dient. Wenn MySQL zum zweiten Mal aufgefordert wird, die Abfrage auszuführen, kann es die Ausführung umgehen und die Ergebnisse aus dem Abfragecache abrufen.

  4. Erwägen Sie die Verwendung eines "Deckungsindex":

    ALTER TABLE key_Word ADD KEY IX_hashed_Word_indexVal (hashed_Word, indexVal);
    

Dies wäre viel effizienter, da MySQL dann die Abfrageanforderung nur aus dem Index erfüllen kann.

5
Boris