Aggiunta di indice a tabelle mysql di grandi dimensioni


13

Ho un tavolo

| base_schedule_line_items | CREATE TABLE base_schedule_line_items(
idint (10) unsigned NOT NULL AUTO_INCREMENT,
installmentint (10) unsigned NOT NULL,
on_datedata NOT NULL,
actual_datedata DEFAULT NULL,
payment_typeint (11) NOT NULL,
scheduled_principal_outstandingdecimale (65,0) NOT NULL,
scheduled_principal_duedecimale (65,0) NOT NULL,
scheduled_interest_outstandingdecimale (65,0) NOT NULL,
scheduled_interest_duedecimale (65,0) NOT NULL,
currencyint (11) NOT NULL,
updated_atdatetime NOT NULL DEFAULT '2013-01-06 14:29:16',
created_atdatetime NOT NULL DEFAULT ' 06/01/2013 14:29:16 ',
loan_base_schedule_idint (10) unsigned NOT NULL,
lending_idint (10) unsigned NOT NULL,
rescheduletinyint (1) DEFAULT' 0 ',
PRIMARY KEY ( id),
KEY index_base_schedule_line_items_loan_base_schedule ( loan_base_schedule_id), KEY index_bslt_spd( scheduled_principal_due),
KEY 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 = 30.410.126 DI DEFAULT CHARSET = utf8 |

Ora questa tabella contiene 30 milioni di record, devo aggiungere altri due indici a questo ed è come se ci volessero anni per aggiungerlo.

alter table base_schedule_line_items aggiungi index index_bslt_sla (schedule_principal_due, actual_date, lending_id);
alter table base_schedule_line_items aggiungi index index_bslt_ssla (schedule_principal_due, pianificato_interesse_due, lending_id, actual_date);

Ho usato la query sotto menzionata per scoprire la dimensione della tabella

SELEZIONA table_name AS "Tabelle", rotondo (((data_length + index_length) / 1024/1024), 2) "Dimensione in MB" DA information_schema.TABLES DOVE table_schema = "my_database_name";

Il risultato è emerso come

base_schedule_line_items | 20.111,00

L'ho usato solo per calcolare la lunghezza dei dati e tralasciare la lunghezza dell'indice

SELEZIONA table_name AS "Tabelle", rotondo (((data_length) / 1024/1024), 2) "Dimensione in MB" DA information_schema.TABLES DOVE table_schema = "my_database_name";

e il risultato è stato

base_schedule_line_items | 9.497,00

Gli indici

Index_bslt_actualdate KEY (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)

sono stati aggiunti da me, ma non sono sicuro o per quale scopo siano stati aggiunti altri indici. Questa è un'applicazione abbastanza grande. Ora devo aggiungere quei due indici sopra menzionati perché mi aiutano a estrarre un rapporto usando un'istruzione select e trovo molto difficile aggiungerli. Qualsiasi aiuto sarebbe molto apprezzato

Risposte:


16

L'attività di modifica delle tabelle di grandi dimensioni viene eseguita in fasi:

  1. Crea una nuova tabella con i campi obbligatori e indicizza gli indici nel DB di test (solo struttura)
  2. Scaricare i dati dalla tabella esistente e caricare gli stessi nella tabella appena creata nel DB di prova
  3. Ora annuncia i tuoi tempi di inattività :)
  4. Scambia le tabelle rinominando - RENAME table ur_db.table_name to test.temp, test.table_name to ur_db.table_name, test.temp to test.table_name;Questa è un'operazione atomica che richiede una frazione di secondo.
  5. Carica i record extra nella tabella appena creata (i record che sono arrivati ​​dopo il dumping e il caricamento). Questo passaggio può essere eseguito prima del passaggio: 3 anche una volta per ridurre i tempi di fermo.
  6. E il tuo sistema è tornato

Alcune note:

  1. Non è necessario colpire lo schema informativo direttamente in questo modo, provare a utilizzare SHOW TABLE STATUS from db like 'table_name'
  2. La velocità della tabella di modifica è più o meno legata alla velocità I / O. L'ultima volta che abbiamo eseguito una tabella di modifica diretta (senza i passaggi precedenti), avevamo una dimensione della tabella di 40 GB + che ha richiesto circa 4 ore. Se i tuoi dati da 20 GB richiedono anni, stai lavorando su una macchina obsoleta.
  3. Anche la caduta degli indici indesiderati index_bslt_ondate, index_base_schedule_line_items_loan_base_schedulecome alcuni altri indici ha la colonna più a sinistra come colonna indicizzata

Per favore fatemi sapere se avete bisogno di chiarimenti su uno di questi passaggi.

Modifica: un semplice script Python per automatizzare il processo https://github.com/georgecj11/hotswap_mysql_table.git


10

È possibile utilizzare uno strumento come pt-online-schema-change per aggiungere l'indice senza bloccare l'applicazione. La logica di base è la seguente:

  • crea una copia vuota della tabella con il nuovo indice
  • aggiungi i trigger alla tabella esistente in modo che eventuali modifiche apportate alla tabella vengano applicate alla copia della tabella *
  • inizia a copiare le righe dalla vecchia tabella alla nuova
  • una volta completata la copia, scambiare le tabelle
  • lascia cadere il vecchio tavolo

* Lo strumento non funziona se nella tabella sono presenti trigger

Il comportamento di scambio e rilascio può essere regolato in base alle opzioni passate allo strumento.

Inoltre, ci sono problemi con le chiavi esterne, quindi assicurati di leggere la documentazione dello strumento per comprendere appieno cosa sta facendo.

E, naturalmente, è consigliabile assicurarsi di disporre di un backup della tabella per poterlo ripristinare se necessario.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.