Ich habe eine Datenbank mit einer Anzahl von Tabellen.
Ich möchte einige Datensätze aus den Tabellen löschen, wenn die Anzahl der Datensätze mehr als 20 KB oder 50 KB beträgt.
Alle Tabellen sind InnoDB. Und file_per_table
ist aus .
Wenn ich die Datensätze aus einer Reihe von Tabellen lösche, werden die Tabellen fragmentiert.
Gibt es eine Möglichkeit, die Fragmentierung zu entfernen?
Update am 17. April
mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City | world_innodb | 5242880 |
| City_Copy | world_innodb | 5242880 |
| Country | world_innodb | 5242880 |
| CountryLanguage | world_innodb | 5242880 |
| a | world_innodb | 5242880 |
| t1 | world_innodb | 5242880 |
| t2 | world_innodb | 5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)
Nun ist meine Frage, wie ich entscheiden werde, ob meine Tabellen fragmentiert sind oder nicht.
Antworten:
Ich habe dies bereits im Oktober 2010 in StackOverflow angesprochen .
Beachten Sie die am stärksten ausgelastete Datei in der InnoDB-Infrastruktur: / var / lib / mysql / ibdata1
Diese Datei enthält normalerweise vier Arten von Informationen
Das Ausführen
OPTIMIZE TABLE
gegen eine in ibdata1 gespeicherte InnoDB-Tabelle bewirkt zwei Dinge:Sie können Tabellendaten und Tabellenindizes von ibdata1 trennen und sie unabhängig mit innodb_file_per_table verwalten , wird der große klaffende gesamte Speicherplatz in ibdata1 einfach nicht verschwinden und kann nicht zurückgefordert werden. Du musst mehr tun.
Um zu schrumpfen ibdata1 ein für alle Mal , müssen Sie Folgendes tun:
1) MySQLDump alle Datenbanken in eine SQL-Textdatei (nennen Sie es /root/SQLData.sql)
2) Löschen Sie alle Datenbanken (außer MySQL-Schema)
3) Fahren Sie mysql herunter
4) Fügen Sie die folgenden Zeilen zu /etc/my.cnf hinzu
Anmerkung: Unabhängig von Ihrer Einstellung für innodb_buffer_pool_size müssen Sie sicherstellen, dass innodb_log_file_size 25% von innodb_buffer_pool_size beträgt.
5) Löschen Sie ibdata1, ib_logfile0 und ib_logfile1
Zu diesem Zeitpunkt sollte nur das MySQL-Schema in / var / lib / mysql vorhanden sein
6) Starten Sie mysql neu
Dadurch wird ibdata1 mit 10 oder 18 MB (je nach MySQL-Version), ib_logfile0 und ib_logfile1 mit jeweils 1 GB neu erstellt
7) Laden Sie /root/SQLData.sql neu in mysql
ibdata1 wächst, enthält jedoch nur Tabellenmetadaten. In der Tat wird es im Laufe der Jahre sehr langsam wachsen. Der einzige Weg, wie ibdata1 schnell wachsen kann, ist, wenn Sie eine oder mehrere der folgenden Möglichkeiten haben:
CREATE TABLE
,DROP TABLE
,ALTER TABLE
)Jede InnoDB-Tabelle existiert außerhalb von ibdata1
Angenommen, Sie haben eine InnoDB-Tabelle mit dem Namen mydb.mytable. Wenn Sie in / var / lib / mysql / mydb gehen, sehen Sie zwei Dateien, die die Tabelle darstellen
ibdata1 enthält nie mehr InnoDB-Daten und -Indizes.
Mit der Option innodb_file_per_table in /etc/my.cnf können Sie ausführen
OPTIMIZE TABLE mydb.mytable;
und die Datei /var/lib/mysql/mydb/mytable.ibd wird tatsächlich verkleinert.Ich habe dies in meiner Karriere als MySQL-DBA viele Male getan
Tatsächlich habe ich beim ersten Mal eine 50 GB große ibdata1-Datei auf 500 MB reduziert.
Versuche es. Wenn Sie weitere Fragen dazu haben, senden Sie mir eine E-Mail. Vertrau mir. Dies wird kurzfristig und langfristig funktionieren !!!
UPDATE 19.04.2012 09:23 EDT
Wie können Sie ermitteln, welche Tabellen defragmentiert werden müssen, nachdem Sie die obigen Schritte ausgeführt haben? Es ist möglich, es herauszufinden, aber Sie werden es als Skript haben.
Hier ist ein Beispiel: Angenommen, Sie haben die Tabelle
mydb.mytable
. Wenn innodb_file_per_table aktiviert ist, haben Sie die Datei /var/lib/mysql/mydb/mytable.ibdSie müssen zwei Nummern abrufen
FILESIZE FROM OS: So können Sie die Dateigröße vom Betriebssystem ermitteln
FILESIZE FROM INFORMATION_SCHEMA: Sie können die Dateigröße wie folgt aus information_schema.tables ermitteln:
Subtrahieren Sie einfach den INFORMATION_SCHEMA-Wert vom OS-Wert und dividieren Sie die Differenz durch den INFORMATION_SCHEMA-Wert.
Von dort aus würden Sie entscheiden, wie viel Prozent es für erforderlich halten, diese Tabelle zu defragmentieren. Natürlich defragmentieren Sie es mit einem der folgenden Befehle:
oder
quelle
Wenn Sie häufig Zeilen löschen (oder Zeilen mit Datentypen variabler Länge aktualisieren), wird möglicherweise viel Speicherplatz in den Datendateien verschwendet, ähnlich wie bei der Fragmentierung des Dateisystems.
Wenn Sie diese
innodb_file_per_table
Option nicht verwenden , können Sie lediglich die Datenbank exportieren und importieren. Dies ist eine zeit- und festplattenintensive Prozedur.Aber wenn Sie verwenden
innodb_file_per_table
, können Sie diesen Platz identifizieren und zurückfordern!Vor 5.1.21 ist der Zähler für freien Speicherplatz in der Spalte table_comment von information_schema.tables verfügbar. Hier einige SQL-Anweisungen zum Identifizieren von Tabellen mit mindestens 100 MB (tatsächlich 97,65 MB) freiem Speicherplatz:
Ab 5.1.21 wurde dies in die data_free-Spalte verschoben (ein viel geeigneterer Ort):
Sie können den verlorenen Speicherplatz zurückfordern, indem Sie die Tabelle neu erstellen. Der beste Weg, dies zu tun, ist die Verwendung von 'alter table', ohne etwas zu ändern:
Dies ist, was MySQL hinter den Kulissen macht, wenn Sie 'Optimize Table' auf einer InnoDB-Tabelle ausführen. Dies führt zu einer Lesesperre, jedoch nicht zu einer vollständigen Tabellensperre. Wie lange es dauert, hängt vollständig von der Datenmenge in der Tabelle ab (jedoch nicht von der Größe der Datendatei). Wenn Sie eine Tabelle mit vielen Lösch- oder Aktualisierungsvorgängen haben, können Sie diese monatlich oder sogar wöchentlich ausführen.
quelle