Hinzufügen eines Index zu großen MySQL-Tabellen

13

Ich habe einen tisch

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) vorzeichenlos NICHT NULL AUTO_INCREMENT,
installmentint (10) vorzeichenlos NICHT NULL,
on_dateDatum NICHT NULL,
actual_dateDatum STANDARD NULL,
payment_typeint (11) NICHT NULL,
scheduled_principal_outstandingdezimal (65,0) NICHT NULL,
scheduled_principal_duedezimal (65,0) NICHT NULL,
scheduled_interest_outstandingdezimal (65,0) NICHT NULL,
scheduled_interest_duedezimal (65,0) NICHT NULL,
currencyint (11) NICHT NULL,
updated_atDatum / Uhrzeit NICHT NULL STANDARD '2013-01-06 14:29:16',
created_atDatum / Uhrzeit NICHT NULL STANDARD ' 2013-01-06 14:29:16 ',
loan_base_schedule_idint (10) vorzeichenlos NICHT NULL,
lending_idint (10) vorzeichenlos NICHT NULL,
rescheduletinyint (1) STANDARD' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
TASTE index_bslt_lending(lending_id),
KEY index_bslt_actualdate( actual_date),
KEY index_bslt_spsila ( loan_base_schedule_id, scheduled_principal_due, scheduled_interest_due, actual_date),
KEY index_bslt_ondate( on_date),
KEY index_bslt_oa( on_date, actual_date),
KEY index_bslt_ol( on_date, loan_base_schedule_id),
KEY index_bslt_oli( on_date, lending_id)
) ENGINE = InnoDB AUTO_INCREMENT = 30410126 STANDARD charset = UTF - 8 |

Jetzt hat diese Tabelle 30 Millionen Datensätze. Ich muss noch zwei weitere Indizes hinzufügen, und es dauert Jahre, um sie hinzuzufügen.

alter table base_schedule_line_items add index index_bslt_sla (Scheduled_Principal_Due, Actual_date, Lending_id);
alter table base_schedule_line_items add index index_bslt_ssla (Scheduled_Principal_Due, Scheduled_ Interest_Due, Lending_id, Actual_Date);

Ich habe die unten angegebene Abfrage verwendet, um die Größe der Tabelle zu ermitteln

SELECT table_name AS "Tables", round (((data_length + index_length) / 1024/1024), 2) "Size in MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

Das Ergebnis kam als

base_schedule_line_items | 20111.00

Ich habe dies nur verwendet, um die Datenlänge zu berechnen und die Indexlänge wegzulassen

SELECT table_name AS "Tables", round (((data_length) / 1024/1024), 2) "Size in MB" FROM information_schema.TABLES WHERE table_schema = "my_database_name";

und Ergebnis war

base_schedule_line_items | 9497,00

Die Indizes

KEY index_bslt_actualdate (actual_date),
KEY index_bslt_spsila (loan_base_schedule_id, Scheduled_principal_due, Scheduled_interest_due, actual_date),
KEY index_bslt_ondate (on_date),
KEY index_bslt_oa (on_date, actual_date),
loaned_loled
index_oa (on_oa

wurden von mir hinzugefügt, aber ich bin nicht sicher oder zu welchem ​​Zweck andere Indizes hinzugefügt wurden. Dies ist eine ziemlich große Anwendung. Jetzt muss ich diese beiden oben genannten Indizes hinzufügen, da sie mir beim Extrahieren eines Berichts mit einer select-Anweisung helfen und ich es sehr schwierig finde, sie hinzuzufügen. Jede Hilfe wäre sehr dankbar

user2294477
quelle

Antworten:

16

Das Ändern großer Tische erfolgt in Phasen:

  1. Erstellen Sie eine neue Tabelle mit erforderlichen Feldern und Indizes, z. B. in der Test-DB (nur Struktur).
  2. Sichern Sie die Daten aus der vorhandenen Tabelle und laden Sie diese in die neu erstellte Tabelle im Test-DB
  3. Kündigen Sie jetzt Ihre Ausfallzeit an :)
  4. Tauschen Sie die Tabellen durch Umbenennen aus. RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;Dies ist eine atomare Operation, die einen Bruchteil einer Sekunde dauert.
  5. Laden Sie die zusätzlichen Datensätze in die neu erstellte Tabelle (die Datensätze, die nach dem Dump und dann Laden kamen). Dieser Schritt kann vor Schritt 3 ausgeführt werden, um Ausfallzeiten zu reduzieren.
  6. Und Ihr System ist zurück

Einige Anmerkungen:

  1. Sie müssen das Informationsschema nicht direkt so treffen, versuchen Sie es mit SHOW TABLE STATUS from db like 'table_name'
  2. Die Geschwindigkeit der Änderungstabelle ist mehr oder weniger mit der E / A-Geschwindigkeit verknüpft. Das letzte Mal, als wir einen direkten Alter-Tisch (ohne die obigen Schritte) ausführten, hatten wir eine Tischgröße von 40 GB +, die ungefähr 4 Stunden dauerte. Wenn Ihre 20-GB-Daten Jahre dauern, arbeiten Sie an einem veralteten Computer.
  3. Das Ablegen der unerwünschten Indizes wie index_bslt_ondate, index_base_schedule_line_items_loan_base_schedulebei einigen anderen Indizes hat auch die am weitesten links stehende Spalte als indizierte Spalte

Bitte lassen Sie mich wissen, wenn Sie Erläuterungen zu einem dieser Schritte benötigen.

Bearbeiten: Ein einfaches Python-Skript zur Automatisierung des Prozesses https://github.com/georgecj11/hotswap_mysql_table.git

georgecj11
quelle
10

Sie können ein Tool wie pt-online-schema-change verwenden , um den Index hinzuzufügen, ohne Ihre Anwendung zu blockieren. Die Grundlogik ist wie folgt:

  • Erstellen Sie eine leere Kopie der Tabelle mit dem neuen Index
  • Hinzufügen von Triggern zur vorhandenen Tabelle, damit alle Änderungen, die die Tabelle betreffen, auf die Kopie der Tabelle angewendet werden *
  • Kopieren Sie die Zeilen aus der alten Tabelle in die neue
  • Sobald der Kopiervorgang abgeschlossen ist, tauschen Sie die Tabellen aus
  • Lass den alten Tisch fallen

* Das Tool funktioniert nicht, wenn Auslöser in der Tabelle vorhanden sind

Das Wechsel- und Ablageverhalten kann basierend auf den an das Tool übergebenen Optionen angepasst werden.

Außerdem gibt es Probleme mit Fremdschlüsseln. Lesen Sie daher unbedingt die Dokumentation des Tools, um zu verstehen, was es tut.

Und natürlich ist es ratsam, eine Sicherungskopie der Tabelle zu erstellen, um sie bei Bedarf wiederherstellen zu können.

Derek Downey
quelle