Ich habe eine InnoDB-Tabelle, die ich ändern möchte. Die Tabelle enthält ~ 80 Millionen Zeilen und beendet einige Indizes.
Ich möchte den Namen einer der Spalten ändern und ein paar weitere Indizes hinzufügen.
- Was ist der schnellste Weg, dies zu tun (vorausgesetzt, ich könnte sogar Ausfallzeiten erleiden - der Server ist ein nicht verwendeter Slave)?
- Ist eine "Ebene"
alter table
die schnellste Lösung?
Zu diesem Zeitpunkt ist alles, was mich interessiert, Geschwindigkeit :)
mysql
innodb
alter-table
ddl
Ran
quelle
quelle
SHOW CREATE TABLE tblname\G
zeigen Sie die Spalte an, die geändert werden muss, den Datentyp der Spalte und den neuen Namen für die Spalte.sent_at
und um es ein paar weitere Indizes hinzuzufügenAntworten:
Eine sichere Möglichkeit, eine ALTER TABLE zu beschleunigen, besteht darin, unnötige Indizes zu entfernen
Hier sind die ersten Schritte zum Laden einer neuen Version der Tabelle
Bitte beachten Sie Folgendes:
Ich habe source_persona_index gelöscht, da dies die erste Spalte in 4 anderen Indizes ist
Ich habe target_persona_index gelöscht, weil es die erste Spalte in 2 anderen Indizes ist
Ich habe target_persona_relation_type_index gelöscht, da sich die ersten beiden Spalten auch in target_persona_relation_type_message_id_index befinden
OK Das sorgt für unnötige Indizes. Gibt es Indizes mit geringer Kardinalität? Hier ist der Weg, um das festzustellen:
Führen Sie die folgenden Abfragen aus:
Ihrer Frage zufolge gibt es ungefähr 80.000.000 Zeilen. Als Faustregel gilt, dass das MySQL Query Optimizer keinen Index verwendet, wenn die Kardinalität der ausgewählten Spalten größer als 5% der Tabellenzeilenanzahl ist. In diesem Fall wären das 4.000.000.
COUNT(DISTINCT sent_at)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX sent_at_index;
COUNT(DISTINCT message_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX message_id_index;
COUNT(DISTINCT target_object_id)
> 4.000.000ALTER TABLE s_relations_new DROP INDEX target_object_index;
Sobald der Nutzen oder die Nutzlosigkeit dieser Indizes festgestellt wurde, können Sie die Daten neu laden
Das war's, richtig? NOPE !!!
Wenn Ihre Website die ganze Zeit aktiv war, werden beim Laden von s_relations_new möglicherweise INSERTs gegen s_relations ausgeführt. Wie können Sie diese fehlenden Zeilen abrufen?
Suchen Sie die maximale ID in s_relations_new und hängen Sie alles nach dieser ID aus s_relations an. Um sicherzustellen, dass die Tabelle eingefroren ist und nur für dieses Update verwendet wird, müssen Sie eine kleine Ausfallzeit haben, um die letzten Zeilen zu erhalten, die in s_relation_new eingefügt wurden. Folgendes tun Sie:
Starten Sie mysql im Betriebssystem neu, damit sich nur root @ localhost anmelden kann (deaktiviert TCP / IP):
Melden Sie sich als Nächstes bei MySQL an und laden Sie die letzten Zeilen:
Starten Sie dann MySQL normal neu
Wenn Sie MySQL nicht herunterfahren können, müssen Sie s_relations ködern und umschalten. Melden Sie sich einfach bei MySQL an und gehen Sie wie folgt vor:
Versuche es !!!
CAVEAT: Sobald Sie mit dieser Operation zufrieden sind, können Sie den alten Tisch so schnell wie möglich löschen:
quelle
Die richtige Antwort hängt von der Version der verwendeten MySQL-Engine ab.
Bei Verwendung von 5.6+ werden Umbenennungen und das Hinzufügen / Entfernen von Indizes online durchgeführt , dh ohne alle Daten der Tabelle zu kopieren.
Verwenden Sie
ALTER TABLE
es einfach wie gewohnt, es ist meistens sofort für Umbenennungen und Indexverluste und relativ schnell für das Hinzufügen von Indizes (so schnell wie das einmalige Lesen der gesamten Tabelle).Wenn Sie 5.1+ verwenden und das InnoDB-Plugin aktiviert ist, ist das Hinzufügen / Entfernen von Indizes auch online. Ich bin mir nicht sicher über Umbenennungen.
Wenn Sie eine ältere Version verwenden,
ALTER TABLE
ist dies immer noch die schnellste - wird aber wahrscheinlich schrecklich langsam sein, da alle Ihre Daten erneut in eine temporäre Tabelle unter der Haube eingefügt werden.Endlich Zeit für das Entlarven von Mythen. Leider habe ich hier nicht genug Karma, um Antworten zu kommentieren, aber ich halte es für wichtig, die am häufigsten gewählte Antwort zu korrigieren. Das ist falsch :
Es ist eigentlich umgekehrt .
Indizes sind nützlich, um wenige Zeilen auszuwählen. Daher ist es wichtig, dass sie eine hohe Kardinalität aufweisen. Dies bedeutet, dass viele unterschiedliche Werte und statistisch wenige Zeilen denselben Wert haben.
quelle
RENAME TABLE
sofort (wie erwartet), aberCHANGE COLUMN
um den Primärschlüssel umzubenennen, wurde eine vollständige Kopie erstellt ... 7 Stunden! Möglicherweise nur, weil es der Primärschlüssel war? Nicht gut.Ich hatte das gleiche Problem mit Maria DB 10.1.12. Nachdem ich die Dokumentation gelesen hatte, stellte ich fest, dass es eine Option gibt, die Operation "an Ort und Stelle" auszuführen, wodurch die Kopie der Tabelle entfernt wird. Mit dieser Option ist die Änderungstabelle sehr schnell. In meinem Fall war es:
das ist sehr schnell. Ohne die Algorithmusoption würde es niemals enden.
https://mariadb.com/kb/en/mariadb/alter-table/
quelle
Für die Spaltenumbenennung
sollte in Ordnung sein und keine Ausfallzeiten mit sich bringen.
Für die Indizes sperrt die Anweisung CREATE INDEX die Tabelle. Wenn es ein unbenutzter Sklave ist, wie Sie erwähnt haben, ist das kein Problem.
Eine andere Möglichkeit wäre, eine brandneue Tabelle mit den richtigen Spaltennamen und Indizes zu erstellen. Dann könnten Sie alle Daten darin kopieren und dann eine Reihe von ausführen
Dies würde die Ausfallzeit auf Kosten der vorübergehenden Nutzung des doppelten Speicherplatzes minimieren.
quelle
Ich habe auch dieses Problem und habe dieses SQL verwendet:
Ich hoffe es könnte jemandem helfen
Grüße,
Wille
quelle