So optimieren Sie InnoDB-Tabellen in MySQL

8

Ich habe untersucht, wie nur fragmentierte Tabellen in MySQL optimiert werden können, und diesen Beitrag zur Optimierung von Tabellen gelesen . Grundsätzlich führt es eine Abfrage für die Datenbank information_schema für jede Tabelle mit durch data_free > 0und erstellt eine SQL-Anweisung OPTIMIZEnur für diese Tabellen. Ich habe diese Abfrage ausgeführt und 148 Tabellen zur Optimierung identifiziert. Alle identifizierten Tabellen sind InnoDB-Tabellen. Nachdem ich das resultierende Optimierungs-SQL-Skript ausgeführt hatte, führte ich das ursprüngliche Skript erneut aus, um fragmentierte Tabellen zu identifizieren, und es gab im ersten Durchgang genau dieselben Tabellen zurück.

Ich habe widersprüchliche Beiträge zu den InnoDB-Tabellen und dem OPTIMIZEBefehl gesehen. Einige sagen, dass OPTIMIZEdies mit InnoDB-Tabellen nicht funktioniert und dass Sie ausgeführt werden müssen ALTER TABLE table_name ENGINE=INNODB. Andere sagen, dass OPTIMIZEder ALTER TABLEBefehl tatsächlich ausgeführt wird, wenn er für InnoDB-Tabellen ausgeführt wird. In diesem Sinne habe ich den ALTER TABLEBefehl für eine der InnoDB-Tabellen ausgeführt, die als fragmentiert ( data_free > 0) identifiziert wurden, und festgestellt, dass sich die data_freedanach nicht geändert hat. Es ist immer noch größer als 0. Ich habe auch MySQL neu gestartet und es nur überprüft, um die gleichen Ergebnisse zu finden.

Jetzt haben wir mehrere Server in unserer Organisation, auf denen MySQL 5.5.29 ausgeführt wird, und ich habe eine Abfrage für alle ausgeführt, um InnoDB-Tabellen zu identifizieren, DATA_FREE=0 or NULLund es wurden keine zurückgegeben. Sie sind alle größer als Null.

Ich habe den OPTIMIZEBefehl auch für einige MyISAMTabellen ausgeführt, DATA_FREEdie größer als Null waren, und danach überprüft, ob er Null war.

Kann mir jemand etwas Licht ins Dunkel bringen? Was ist die richtige Methode, um Fragmentierung aus InnoDB-Tabellen zu entfernen? Was ist die richtige Methode, um fragmentierte InnoDB-Tabellen zu bestimmen?

Vielen Dank

user3151788
quelle

Antworten:

9

Ich gehe davon aus, dass Sie innodb_file_per_tablefür diese Antwort verwenden.

"InnoDB-Fragmentierung" hat mehr als eine Bedeutung:

  1. .ibd Die Datei ist fragmentiert und sehr groß, während der Datensatz klein ist
  2. Indexseiten sind dahingehend fragmentiert, dass zu viele Seiten vorhanden sind, um nur wenige Daten zu enthalten. In diesem Fall könnten sie zusammengeführt werden.

Bitte beachten Sie diesen Beitrag, den ich vor einiger Zeit geschrieben habe: Er zeigt, wie die Datendatei nach dem Löschen vieler Zeilen aus einer großen Tabelle fragmentiert ist (dh sie ist im Dateisystem sehr groß - es ist ein bekanntes Problem, dass diese Dateien niemals kleiner werden). Und dennoch waren die Indizes bis zum Ende des Löschvorgangs nicht fragmentiert: Dies liegt daran, dass InnoDB Seiten ordnungsgemäß zusammenführt, wenn sie leer werden (er).

Der OPTIMIZEBefehl gilt in der Tat nicht für InnoDB. Was es tut, ist die Tabelle neu zu erstellen (genau wie eine ALTER). Sieh dir das an:

mysql [localhost] {msandbox} (test) > create table t(id int) engine=innodb;

mysql [localhost] {msandbox} (test) > optimize table t;
+--------+----------+----------+-------------------------------------------------------------------+
| Table  | Op       | Msg_type | Msg_text                                                          |
+--------+----------+----------+-------------------------------------------------------------------+
| test.t | optimize | note     | Table does not support optimize, doing recreate + analyze instead |
| test.t | optimize | status   | OK                                                                |
+--------+----------+----------+-------------------------------------------------------------------+

Wie für DATA_FREE: Ich schlage vor, dass Sie diese Variable einfach ignorieren. Um ehrlich zu sein, arbeite ich seit Jahren mit InnoDB-Tabellen 10und habe nie festgestellt, dass dieser Wert mit irgendetwas sehr konsistent ist.

Und jetzt ist es Zeit für die eigentliche Diskussion: Was genau wollen Sie erreichen? Sofern Ihre Datenbank nicht vollständig veraltet ist, kommt es immer zu einer gewissen Fragmentierung. Das Hinzufügen, Entfernen und Aktualisieren von Zeilen in Ihrer Tabelle ist selbstverständlich.

Fragmentierung ist nicht so böse: Freier Speicherplatz kann durch neue Daten zurückgewonnen werden. Wenn Ihre Tische nicht sehr groß sind, vergessen Sie einfach das Ganze. Bei sehr großen Tabellen können Sie durch Optimieren der Tabelle Speicherplatz gewinnen. Aber fragen Sie sich: Wie schnell würde die Tabelle dieselbe Fragmentierung erreichen? Eine Stunde? Ein Tag? Eine Woche? IMHO ist es in all diesen Fällen sinnlos, die Tabelle zu optimieren.

Wenn eine große Tabelle jedoch massiv von Daten gelöscht wird, von denen nicht erwartet wird, dass sie zurückkehren, bin ich alle dafür, sie zu optimieren. Angenommen, Sie stellen fest, dass Sie über redundante Daten verfügen, die etwa 30% Ihrer Tabellengröße ausmachen. Sicher, es wäre großartig, diesen Speicherplatz wieder zu haben.

Fazit: Berücksichtigen Sie diese Probleme nur bei sehr großen Tabellen. Nur wenn Sie Probleme mit dem Speicherplatz haben.

Shlomi Noach
quelle
Ich bin damit einverstanden, dass data_free nicht nützlich ist. Es wird nur Speicherplatz in "freien Bereichen" für den Tabellenbereich gezählt, was eine schreckliche Metrik für die Berechnung der Fragmentierung ist. Ich denke, wenn Sie es nicht verwenden innodb_file_per_table, wird auch für jede Tabelle im gemeinsam genutzten Tabellenbereich der gleiche Wert angezeigt.
Jeremyycole