2012-10-19 3 views
8

Ich habe eine MySQL Datenbank, die bis zu etwa 17   GB Größe ist und 38 Millionen Einträge hat. Im Moment muss ich sowohl die Größe einer Spalte vergrößern (varchar 40 auf varchar 80) als auch weitere Spalten hinzufügen.Wie ändere ich effizient eine MySQL-Tabellenstruktur in einer Tabelle mit Millionen von Einträgen?

Viele der Felder sind indiziert, einschließlich der, die ich ändern muss. Es ist Teil eines einzigartigen Paares, das für die Anwendungen benötigt wird. Bei dem Versuch, die Änderung gestern vorzunehmen, lief die Abfrage fast vier Stunden lang ohne Abschluss, als ich beschloss, unseren Ausfall zu reduzieren und den Dienst einfach wieder hoch zu bringen.

Was ist der effizienteste Weg, um Änderungen an etwas dieser Größe vorzunehmen?

Viele dieser Einträge sind ebenfalls alt, und wenn es eine gute Möglichkeit gibt, Shard-Einträge zu sortieren, aber immer noch verfügbar sind, könnte dies bei diesem Problem helfen, indem man die Tabelle viel überschaubarer macht.

+0

interessant. Ich folge dieser Frage. – Gianmarco

Antwort

2

Mit MySQL 5.1 und wieder mit 5.5 wurden bestimmte alter-Anweisungen erweitert, um nur die Struktur zu ändern, ohne die gesamte Tabelle neu zu schreiben (http://dev.mysql.com/doc/refman/5.5/en/alter-table.html - Suche nach In-Place). Die Verfügbarkeit von diesem hängt jedoch von der Art der Änderung, die Sie machen, und der verwendeten Engine ab, der meiste Wert kommt von InnoDB Plugin. Im Falle Ihrer spezifischen Änderungen würde jedoch die gesamte Tabelle neu geschrieben werden.

Wenn diese Probleme auftreten, versuchen wir normalerweise, Replikatdatenbanken zu verwenden. Solange Sie hinzufügen und nicht entfernen, können Sie Ihre DDL zuerst für das Replikat ausführen und dann einen kurzen Ausfall planen, um das Replikat an die Master-Rolle zu übertragen. Wenn Sie auf RDS sind, ist dies sogar einer ihrer empfohlenen Verwendungszwecke für ihre Replikat-Instanzen http://aws.amazon.com/about-aws/whats-new/2012/10/11/amazon-rds-mysql-rr-promotion/.

Einige andere Alternativen sind:

  • mit der gewünschten Struktur eine Teilmenge von Datensätzen in eine neue Tabelle auswählen aus (Verwendung INTO OUTFILE eine Tabellensperre zu vermeiden). Nach Abschluss können Sie ein Wartungsfenster und REPLACE INTO oder UPDATE alle Datensätze planen, die seit der ersten Datenkopie in der Originaltabelle geändert wurden. Sobald die Aktualisierung abgeschlossen ist, werden die Änderungen in einem RENAME TABLE... der beiden Tabellen aufgehoben.
  • Verwenden Sie ein Tool wie Percona pt-Online-Schema-Änderung: http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html. Dieses Tool arbeitet mit Triggern. Wenn Sie also bereits Trigger für die Tabellen haben, die Sie ändern möchten, entspricht dies möglicherweise nicht Ihren Anforderungen.
3

Erstellen Sie eine neue Tabelle mit der neuen Struktur, die Sie möchten, mit einem anderen Namen, z. B. NewTable.

Dann werden die Daten in die neue Tabelle aus der alten Tabelle legen Sie die folgende Abfrage verwenden:

INSERT INTO NewTable (field1, field2, etc...) SELECT field1, field2, ... FROM OldTable 

Nachdem dies geschehen ist, können Sie die alte Tabelle löschen und die neue Tabelle

auf den ursprünglichen Namen umbenennen
DROP TABLE `OldTable`; 
RENAME TABLE `NewTable` TO `OldTable` ; 

Ich habe diesen Ansatz auf einer sehr großen Tabelle versucht und es ist viel viel schneller als die Tabelle zu ändern.

6

Sie haben eine Auswahl.

In jedem Fall sollten Sie eine Sicherungskopie machen, bevor Sie diese Dinge tun.

Eine Möglichkeit ist, Ihren Dienst offline zu nehmen und es an Ort und Stelle zu tun, wie Sie es versucht haben. Wenn Sie das tun, sollten Sie Schlüsselprüfungen und Einschränkungen deaktivieren.

ALTER TABLE bigtable DISABLE KEYS; 
SET FOREIGN_KEY_CHECKS=0; 
ALTER TABLE (whatever); 
ALTER TABLE (whatever else); 
... 
SET FOREIGN_KEY_CHECKS=1; 
ALTER TABLE bigtable ENABLE KEYS; 

Dadurch kann der ALTER TABLE-Vorgang schneller ausgeführt werden. Es wird die Indizes auf einmal neu generieren, wenn Sie KEYS AKTIVIEREN.

Eine andere Möglichkeit besteht darin, eine neue Tabelle mit dem neuen Schema zu erstellen, dann die Schlüssel in der neuen Tabelle zu deaktivieren, dann wie @Bader vorgeschlagen und den Inhalt der alten Tabelle einzufügen.

Nachdem Ihre neue Tabelle erstellt wurde, werden Sie die Schlüssel erneut aktivieren, dann benennen Sie die alte Tabelle in einen Namen wie "old_bigtable" um und benennen die neue Tabelle in "bigtable" um.

Es ist möglich, dass Sie Ihren Dienst online halten können, während Sie die neue Tabelle ausfüllen. Aber das könnte schlecht funktionieren.

Eine dritte Möglichkeit ist Ihre riesige Tabelle (in eine flache Datei) zu entladen und dann in eine neue Tabelle mit dem neuen Layout zu laden. Das ist so ähnlich wie bei der zweiten Möglichkeit, außer dass Sie eine kostenlose Tabellensicherung erhalten. Sie können dies mit SELECT DATA INTO OUTFILE und LOAD DATA INFILE ziemlich schnell machen. Dazu müssen Sie Zugriff auf das Dateisystem Ihres Server-Rechners haben.

In allen Fällen die Einschränkungen und Schlüssel deaktivieren und dann wieder aktivieren, damit die Dinge schnell ausgeführt werden.

+1

der erste klingt wie, was ich will Ich denke, ich werde versuchen, ein paar Stunden alt der amzaon rds Instanz zu drehen und versuchen, diese, bevor Sie einen anderen Ausfall versuchen. – marioatlp

+2

Nachdem wir am Wochenende Zeit hatten, daran zu arbeiten, liegt das Problem bei dieser Methode einfach darin, dass innodb Sie nicht die Schlüssel deaktivieren lässt. – marioatlp

Verwandte Themen