Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Warum gibt InnoDB offensichtlich falsche Informationen zum freien Speicherplatz aus?

(Dies beantwortet einige der Fragen, die in den Kommentaren vergraben sind.)

Falsche Bezeichnung "Freier" Speicherplatz umfasst nur ganze Blöcke, keinen freien Platz innerhalb von Blöcken und viele andere Details.

Fall 1:Alle Tabellen sind in ibdata1 -- SHOW TABLE STATUS (oder die entsprechende Abfrage in information_schema zeigt dasselbe Data_free Wert, nämlich wie viel in ibdata1 frei ist . Dieser Platz kann von jedem Tisch wiederverwendet werden. Es ist schwierig, den Speicherplatz an das Betriebssystem zurückzugeben.

Fall 2:Alle Tabellen sind file_per_table -- Jetzt jedes Data_free bezieht sich auf den Platz für den Tisch. Und die SUM() ist aussagekräftig. (ibdata1 existiert noch, aber es enthält keine echten Tabellen; es gibt eine Menge anderer Sachen, die InnoDB braucht.)

Fall 3:Mischung -- Wenn Sie file_per_table zu verschiedenen Zeiten ein-/ausschalten, befinden sich einige Tabellen in ibdata1, andere haben ihre eigenen Tablespaces.

Fall 4:TABLESPACE in 5.7 ERSTELLEN -- Beispielsweise können Sie für jede Datenbank einen Tablespace haben.

Fall 5:PARTITIONIERTE Tabellen -- Jede Partition verhält sich wie eine Tabelle.

Fall 6:8.0 -- Es kommen noch mehr Änderungen.

Datenbank ==Verzeichnis Im Verzeichnisbaum von MySQL kann jede Datenbank als Dateisystemverzeichnis betrachtet werden. Innerhalb dieses Verzeichnisses sind einige Dateien für jede Tabelle zu sehen. Die .frm Datei enthält die Tabellendefinition. Wenn eine .ibd file existiert, wurde die Tabelle mit file_per_table erstellt. Dies ist möglicherweise der zuverlässigste Weg, um festzustellen, ob die Tabelle file_per_table ist. (8.0 wird hier signifikante Änderungen haben.)

Wie viel Speicherplatz kann ich wiederverwenden ? Es gibt keine gute Antwort. Normalerweise findet das Einfügen einer Zeile Platz in dem Block, wo sie hingehört, und Data_free wird nicht schrumpfen. Aber wenn es Block-Split(s) gab, kann Data_free um ein Vielfaches von 16 KB (die Blockgröße) oder 4 MB (die "Extent-Größe" - oder vielleicht sind es 8 MB?) fallen. Außerdem führen zufällige Einfügungen dazu, dass BTree-Blöcke im Durchschnitt zu etwa 69 % voll sind.

Ändern von innodb_file_per_table hat bis zum nächsten CREATE TABLE keine Auswirkung oder ALTER TABLE . Und dann hat es nur Auswirkungen darauf, wo die neu erstellten/kopierten Daten+Indizes (ibdata1 oder .ibd) abgelegt werden sollen. Es werden keine Daten zerstört.

Große Tische haben normalerweise 4 MB bis 7 MB Data_free. Wenn Sie berechnen, wie viele Zeilen Sie hinzufügen können, planen Sie nicht, dass Data_free unter diesen Bereich fällt.

Avg_row_size sollte nützlich sein. Aber manchmal sind es (und Zeilen) schlecht angenähert. Ihr Produkt (Data_length) ist immer korrekt. Also, das vielleicht eine gute Schätzung von "Zeilen, die noch zu erledigen sind, bevor mehr Platz vom Betriebssystem beansprucht wird:

(Data_free - 7M) / Avg_row_size

Tablespace-Empfehlungen :Legen Sie 'große' Tabellen in file_per_table. Setzen Sie 'winzige' Tabellen in ibdata1 oder datenbankspezifische Tablespaces (5.7). Leider keine einfache Empfehlung auf der Trennlinie zwischen „groß“ und „winzig“. Und es ist umständlich, eine Tabelle zu migrieren:SET global innodb_file_per_table = ...;; Ausloggen; Login (um das Globale abzurufen); ALTER TABLE tbl ENGINE=InnoDB; . Und es ist notwendigerweise eine vollständige Kopie der Tabelle.

(Vorsicht :Ich habe viele Details weggelassen.)