MySQL dauert zu lange, um Daten zu senden

9

Ich habe eine einfache Tabelle mit Millionen von Datensätzen (14.000.000) und für eine einfache Abfrage verbringt sie zu viel Zeit mit dem "Senden von Daten".

Der Tisch

CREATE TABLE IF NOT EXISTS details (
  id int(11) NOT NULL,
  date date NOT NULL,
  time int(2) NOT NULL,
  minutes_online decimal(5,0) NOT NULL,
  minutes_playing decimal(5,0) NOT NULL,
  minutes_chatting decimal(5,0) NOT NULL,
  minutes_away decimal(5,0) NOT NULL
  PRIMARY KEY (id,date,time)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_general_ci;

Die einfache Abfrage

mysql> SELECT * FROM details WHERE id = 3014595;

Erklären

mysql> EXPLAIN SELECT * FROM details WHERE id = 3014595;
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
| id | select_type | table     | type | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | details   | ref  | PRIMARY       | PRIMARY | 4       | const | 1482 |       |
+----+-------------+-----------+------+---------------+---------+---------+-------+------+-------+

Profil für die Abfrage

mysql> SHOW PROFILE FOR QUERY 1;
+--------------------------------+----------+
| Status                         | Duration |
+--------------------------------+----------+
| starting                       | 0.000024 |
| checking query cache for query | 0.000078 |
| checking permissions           | 0.000014 |
| Opening tables                 | 0.000126 |
| System lock                    | 0.000011 |
| Table lock                     | 0.000030 |
| init                           | 0.000027 |
| optimizing                     | 0.000117 |
| statistics                     | 0.040077 |
| preparing                      | 0.000029 |
| executing                      | 0.000006 |
| Sending data                   | 7.536960 |
| end                            | 0.000013 |
| query end                      | 0.000004 |
| freeing items                  | 0.000037 |
| storing result in query cache  | 0.000006 |
| logging slow query             | 0.000003 |
| cleaning up                    | 0.000006 |
+--------------------------------+----------+

Wie Sie sehen können, hat die SELECTAnweisung den Index verwendet und nur 1482 Zeilen gelesen. Die Abfrage dauerte jedoch 7,536960 Sekunden, um die Daten zu senden. Es ist, als würde die Abfrage viel mehr Zeilen lesen, die sie benötigt.

Es ist eine einfache Abfrage mit nur 7 Feldern (Zeile durchschnittlich 59 Bytes) und ohne ausgefallene Funktion. Irgendeine Idee, was dies verursachen kann?

Hinweis: id ist die Benutzer-ID. Jeder Benutzer kann mindestens einen Eintrag für jede Stunde eines jeden Tages haben. Daher ist id nicht eindeutig.

Bearbeiten: Ich habe eine andere Tabelle mit der gleichen Struktur und viel mehr Zeilen (34 Millionen). Wenn ich dieselbe Abfrage für diese größere Tabelle ausführe, werden die Ergebnisse in weniger als 1 Sekunde zurückgegeben.

Der einzige Unterschied besteht darin, dass die größere Tabelle nicht so viele Abfragen erhält wie die kleinere Tabelle.

  • Ist es möglich, dass die Anzahl der Abfragen den Prozess verlangsamt? Der MySQL-Cache ist aktiviert. Ich habe auch CakePHP zwischengespeichert, um die Anzahl der Abfragen zu reduzieren.
  • Ist es möglich, dass die Datei, in der die Tabelle gespeichert ist, beschädigt ist oder so?

Update Das Problem wurde behoben, indem die Datenschicht von der Webschicht getrennt wurde. Die Datenschicht hat auch ein Upgrade im RAM erhalten und läuft auf raid10.

rlcabral
quelle
Wie viele Zeilen gibt die SELECTRückgabe?
hjpotter92
1591 rows in set (16.48 sec)Ich habe die Abfrage erneut ausgeführt. Aus diesem Grund ist die Dauer unterschiedlich. Es dauerte jetzt 16 Sekunden (!!)
rlcabral
Anstatt * zu verwenden, versuchen Sie, Spalten zu verwenden und sehen Sie dann, welchen Unterschied es macht
Muhammad Raheel
Nee. Gleiches Ergebnis.
Rlcabral
Versuchen Sie, die ID-Spalte zu einem einfachen Primärindex zu machen. Da ID ein eindeutiges Feld sein sollte, müssen Sie damit keine komplexen Indizes erstellen. Dies sollte Ihre Suche nach Primärschlüssel schnell wie eine Lichtgeschwindigkeit machen.
Alexander Pravdin

Antworten:

1

Für alle, die über diese Frage stolpern und sich auch ohne RAM-Upgrade fragen, warum das Senden von Daten so viel länger dauert. Dies liegt daran, dass das Senden von Daten tatsächlich die Zeit für die Suche nach den zu sendenden Daten umfasst.

https://dev.mysql.com/doc/refman/5.7/en/general-thread-states.html

Der Thread liest und verarbeitet Zeilen für eine SELECT-Anweisung und sendet Daten an den Client. Da Operationen, die in diesem Status ausgeführt werden, in der Regel große Mengen an Festplattenzugriff (Lesevorgängen) ausführen, ist dies häufig der Status mit der längsten Laufzeit über die Lebensdauer einer bestimmten Abfrage.

Vaibhav Gupta
quelle
-2

Versuchen Sie, die Tabelle mithilfe des Tabellennamens "Tabelle optimieren" zu optimieren, und überprüfen Sie den Status.

Es müssen große Änderungen vorgenommen werden:

Alter table tablename engine = 'INNODB'

Dies wird Ihnen viel helfen und möglicherweise sollte es einen Primärschlüssel in der Tabelle geben, aber Sie haben drei Spalten als Primärschlüssel hinzugefügt.

SAM AB
quelle
-3

Erstellen Sie einen separaten Index für die ID:

Tabellendetails ändern Schlüssel hinzufügen d1 (id);

Starten Sie MySQL oder neu, um diesen Index in Kraft zu setzen

Tabellendetails analysieren;

Wenn möglich, können Sie die Datenbank auch in InnoDB ändern, um Transaktionsunterstützung und andere Vorteile zu erhalten.

Krishnakumar
quelle
Wie wird das helfen?
Colin 't Hart