it-swarm.com.de

Löschen und Zurückfordern von Speicherplatz aus der InnoDB-Tabelle

Ich habe eine 700 GB InnoDB-Tabelle, in die ich keine Daten mehr schreibe (nur lesen). Ich möchte die darin enthaltenen älteren Daten löschen und diesen Speicherplatz zurückfordern (da mir der Speicherplatz ausgeht). Der Löschteil ist ziemlich einfach, da ich einen Auto-Inc-Primärindex habe, sodass ich ihn einfach in Blöcken durchlaufen und die Zeilen löschen kann, aber das bringt mich nicht zurück. Ich nehme an OPTIMIZE TABLE wird, aber das kann auf einem 700-GB-Tisch ewig dauern. Gibt es also eine andere Option, die ich übersehen habe?

Bearbeiten von RolandoMySQLDBA

Angenommen, Ihre Tabelle ist mydb.mytable, führen Sie bitte die folgende Abfrage aus und veröffentlichen Sie sie hier, damit Sie den für das Schrumpfen der Tabelle erforderlichen Speicherplatz ermitteln können:

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

Wir müssen auch die Tabellenstruktur sehen, wenn erlaubt.

Bearbeiten von Noam

Dies ist die Ausgabe der Abfrage:

datsize ndxsize tblsize
682,51 47,57 730,08

Dies ist die Tabellenstruktur (SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`
18
Noam

Das ist eine gute Frage. Sie haben mehrere Lösungen, aber Ihr Tisch ist ziemlich groß, so dass keiner ohne Schmerzen sein wird :)

Sie haben drei Lösungen, um InnoDB-Tabellen zu "verkleinern":

1. TABELLE OPTIMIEREN

Sie können OPTIMIZE TABLE Verwenden, wie Sie es erwähnt haben, aber Sie sollten sich um die Variable innodb_file_per_table Kümmern:

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

Lassen Sie mich erklären:

Das OPTIMIZE TABLE Mit InnoDB-Tabellen sperrt die Tabelle, kopiert die Daten in eine neue saubere Tabelle (deshalb ist das Ergebnis kleiner), löscht die ursprüngliche Tabelle und benennt die neue Tabelle mit dem ursprünglichen Namen um. Aus diesem Grund sollten Sie sicherstellen, dass auf Ihrer Festplatte doppelt so viel Speicherplatz wie in der ursprünglichen Tabelle verfügbar ist (Sie benötigen wahrscheinlich weniger, da die optimierte Tabelle kleiner ist, aber es ist besser, auf Nummer sicher zu gehen).

innodb_file_per_table = ON: In diesem Modus haben alle Tabellen ihre eigene Datendatei. Die Anweisung OPTIMIZE erstellt dann eine neue Datendatei mit optimierter Speicherplatznutzung. Wenn der Vorgang abgeschlossen ist, löscht MySQL das Original und ersetzt es durch die optimierte Version (so werden am Ende die 700 GB - wahrscheinlich weniger, weil sie optimiert werden - der während des Vorgangs generierten Daten freigegeben).

innodb_file_per_table = OFF: In diesem Modus sind alle Daten in einer Datendatei enthalten: ibdata . Dieser Modus hat einen großen Nachteil, da er nicht optimiert werden kann. Während des OPTIMIZE -Prozesses wird Ihre neue Tabelle erstellt (in der Nähe von 700 GB), aber auch nach dem Löschen und Umbenennen (und dem Ende der OPTIMIZE -Phase) wird Ihre ibdata gibt die ~ 700 GB nicht frei, also wollten Sie einige Daten freigeben, stattdessen haben Sie 700 GB mehr, cool, nicht wahr?

2. ALTER TABLE

Sie können auch eine ALTER TABLE - Anweisung verwenden. Die ALTER TABLE Funktioniert genauso wie OPTIMIZE TABLE. Sie können einfach verwenden:

ALTER TABLE myTable ENGINE=InnoDB;

3. ALTER TABLE (ONLINE)

Das Problem von OPTIMIZE und ALTER TABLE Ist, dass die Tabelle während des Betriebs gesperrt wird. Sie können das Percona-Tool verwenden: pt-online-schema-change (aus dem Percona Toolkit: Link ). pt-online-schema ... bietet Mechanismen zur Optimierung der Tabelle, während die ursprüngliche Tabelle zum Lesen und Schreiben verfügbar bleibt. Ich benutze dieses Tool in der Produktion für ALTER Anweisungen auf großen Tabellen und es ist ziemlich cool.

Beachten Sie, dass alle FOREIGN KEY, Die auf Ihre Tabelle verweisen, die Dinge komplizieren können, da Sperren zu Sperren für andere Tabellen usw. führen können. Um dies zu überprüfen, fragen Sie einfach:

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

So verwende ich pt-online-schema-change:

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

Beachten Sie, dass mein Hinweis zu innodb_file_per_table Auch für diese Lösung gilt.

4. mysqldump

Die letzte Lösung besteht darin, alle Datenbanken aus einem Speicherauszug neu zu erstellen. Es dauert ewig, ist aber äußerst effizient. Beachten Sie, dass dies die einzige Lösung zur Optimierung Ihrer ibdata-Datei ist, wenn innodb_file_per_tableOFF ist.

Max.

25

Wenn Sie wenig Festplattengröße haben, würde ich vorschlagen, dass Sie genau das tun, was Max mit pt-online-schema-change (ONLINE) vorgeschlagen hat. Ich war in der gleichen Situation mit einem viel kleineren Tisch (200 GB) und habe mich dafür entschieden, gleichzeitig eine Komprimierung durchzuführen. Etwas in dieser Richtung sollte funktionieren:

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

Dies funktioniert nur, wenn Sie sich im Barracuda-Dateiformat und im COMPACT-Format der Tabelle befinden. Außerdem muss innodb_file_per_table aktiviert sein. Dies kann sich positiv auf die Größe Ihrer Tabelle auswirken, insbesondere wenn viel Text vorhanden ist und Sie kleinere KEY_BLOCK_SIZE wie 8 KB oder sogar 4 KB verwenden (der Standardwert ist 16 KB). Sie können auch in anderen Blogs überprüfen, wie viel Speicherplatz Sie durch mehrere Benchmarks zu diesem Problem gewinnen können. In der MySQL-Dokumentation werden jedoch 25% bis 50% angegeben (für mich waren es fast 90%).

Beachten Sie, dass dies auch die Leistung bei SELECTs beeinträchtigen kann (aus der MySQL-Dokumentation):

Somit kann der Pufferpool zu einem bestimmten Zeitpunkt sowohl die komprimierte als auch die nicht komprimierte Form der Seite oder nur die komprimierte Form der Seite oder keine enthalten.

MySQL muss die Daten auch dekomprimieren, wenn sie sich nicht im Pufferpool befinden. Also sei gewarnt.

Das hat in meinem Fall wirklich gut funktioniert. Ich hatte einen langen Text. Aus 200 GB wurden 26 GB. Die Leistungen wurden nicht verändert.

Weitere Informationen finden Sie unter folgenden Links:

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

1
Emeric Hunter