Was ist ein guter Weg, um einer großen InnoDB-Tabelle einen PRIMARY KEY hinzuzufügen?


8

Ich habe eine Tabelle mit ungefähr 30 Millionen Zeilen in MySQL 5.5 unter Verwendung der InnoDB-Speicher-Engine. Diese Tabelle verfügt über einen Fremdschlüssel, der mit einer anderen Tabelle mit etwa 3 Millionen Zeilen verknüpft ist.

Ich möchte der größeren Tabelle einen Primärschlüssel hinzufügen, bin mir aber nicht sicher, wie ich am besten vorgehen soll. Es gibt keine vorhandene Spalte (oder Spaltengruppe), die ich dafür verwenden kann. Wie soll ich vorgehen?

Ich habe einige Verweise auf eine interne InnoDB-Datensatz-ID gesehen, aber nicht gefunden, ob darauf zugegriffen werden kann.

Andernfalls muss ich möglicherweise die Daten sichern und neu laden und die ID manuell hinzufügen.

Vielen Dank.


Ist es eine Kombination von Schlüsseln in der Tabelle, die natürlich einzigartig ist? In diesem Fall kann ein mehrspaltiger Primärschlüssel sinnvoll sein.
Justin Dearing

Leider war ein solcher zusammengesetzter Schlüssel nicht möglich. Ansonsten stimme ich zu, dass das Sinn machen würde. Ich habe den Beitrag bearbeitet, um zu verdeutlichen, dass dies nicht möglich war.
Wodin

Antworten:


7

Dies mag der falsche Weg sein, aber ..

Könntest du nicht einfach die Tabellenstruktur ändern?

Fügen Sie der Tabelle eine Primärschlüsselspalte hinzu

dann...

Schreiben Sie ein schnelles Skript, um die gesamte Tabelle durchzugehen

Hinzufügen eines automatisch inkrementierenden Werts zur neuen Spalte?


2
Danke für den Vorschlag. Ich denke, ich müsste die Spalte als Nicht-Primärschlüssel hinzufügen und anschließend in einen Primärschlüssel konvertieren, aber ich habe gerade beim Testen einer kleinen Tabelle versehentlich festgestellt, dass eine AUTO_INCREMENT-Spalte (als Primärschlüssel) hinzugefügt wird. füllt automatisch die IDs aus. Ich ging davon aus, dass es mir nur einen Fehler geben würde, also denke ich, dass das die Antwort ist.
Wodin

Wenn die Datenbank stark ausgelastet ist, sollten Sie sie an einer unkritischen Tabelle testen, um sicherzustellen, dass sie nicht lange
Patrick

@Patrick, danke für den Hinweis zur Vorsicht. Die Datenbank wird derzeit nicht verwendet, und ich gehe davon aus, dass dies die Tabelle für lange Zeit sperren wird.
Wodin

1
Ich habe ALTER TABLE blah ADD id INT NOT NULL AUTO_INCREMENT PRIMARY KEY;es getan und es hat 2 Stunden und 18 Minuten gedauert :) Ich habe während dieser Zeit nicht versucht, an den Tisch zu schreiben, aber das Lesen hat gut funktioniert.
Wodin

1
@Wodin wow, das ist eine lange Zeit für einen alter table Befehl. Ich bin froh, dass es für dich geklappt hat.
Patrick

3

So würde ich das angehen:

  1. Erstellen Sie eine neue Tabelle mit der gewünschten Struktur, einschließlich Ihres PRIMARY KEY mit AUTO_INCREMENT und wahrscheinlich eines weiteren indizierten Feldes.
  2. Nehmen Sie sich eine Ausfallzeit, um den gesamten Datenverkehr zu stoppen.
  3. Bestätigen Sie, dass Sie eine legitime Sicherung Ihrer Daten haben.
  4. Kopieren Sie alle Ihre Zeilen aus Ihrer vorhandenen Tabelle in die Zieltabelle, indem Sie die AUTO INCREMENT verwenden, um Ihre IDs zu erstellen. * zB INSERT INTO target_table (col1, col2 usw.) SELECT (col1, col2 usw.) FROM origin_table; *
  5. Testen Sie, ob die Daten in der neuen Tabelle korrekt sind.
  6. Benennen Sie die alte Tabelle in origin_table_BAK um.
  7. RENAME target_table to origin_table.
  8. Rauchtest Ihrer Anwendung.
  9. Offen für den Verkehr.
  10. Löschen Sie nach Ihrer nächsten Sicherung origin_table_BAK.

* Hinweis: Wenn die Ursprungstabelle InnoDB ist, bleiben Fremdschlüsseleinschränkungen erhalten und überleben die Umbenennung. Sie müssen also eine Änderung vornehmen, um dies zu beheben.


3
Wenn Sie es live machen müssen, führen Sie die Schritte 6 und 7 in einem einzigen RENAME aus, um es atomar zu machen. RENAME TABLE real_name TO alt, neu TO real_name;
Rick James
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.