2012-10-19 15 views
8

Ho un database MySQL di dimensioni pari a circa 17   GB e ha 38 milioni di voci. Al momento, ho bisogno di aumentare entrambe le dimensioni di una colonna (da varchar 40 a varchar 80) e aggiungere più colonne.Come posso modificare in modo efficiente una struttura di tabelle MySQL su una tabella con milioni di voci?

Molti dei campi sono indicizzati tra cui quello che ho bisogno di cambiare. Fa parte di una coppia unica che è necessaria per il funzionamento delle applicazioni. Nel tentativo di apportare la modifica solo ieri, la query ha funzionato per quasi quattro ore senza terminare, quando ho deciso di interrompere l'interruzione e di ripristinare il servizio.

Qual è il modo più efficiente per apportare modifiche a qualcosa di queste dimensioni?

Molte di queste voci sono anche vecchie e se c'è un buon modo per ordinare le voci di separazione, ma sono ancora disponibili per risolvere questo problema rendendo la tabella una dimensione molto più gestibile.

+0

interessante. Seguo questa domanda. – Gianmarco

risposta

2

Con MySQL 5.1 e di nuovo con 5.5 alcune istruzioni di alterazione sono state migliorate per modificare la struttura senza riscrivere l'intera tabella (http://dev.mysql.com/doc/refman/5.5/en/alter-table.html - ricerca sul posto). La disponibilità di questo però varia in base al tipo di modifica che si sta apportando e al motore in uso, il maggior valore viene fornito da InnoDB Plugin. In caso di modifiche specifiche, l'intera tabella verrà riscritta.

Quando riscontriamo questi problemi, in genere cerchiamo di sfruttare i database di replica. Finché si aggiunge e non si rimuove, è possibile eseguire prima il DDL contro la replica e quindi pianificare una breve interruzione per promuovere la replica nel ruolo principale. Se ti capita di essere su RDS, questo è anche uno dei loro usi suggeriti per le loro istanze di replica http://aws.amazon.com/about-aws/whats-new/2012/10/11/amazon-rds-mysql-rr-promotion/.

Alcune altre alternative includono:

  • Selezionando un sottoinsieme di record in una nuova tabella con la struttura desiderata (uso INTO OUTFILE per evitare un blocco di tabella). Una volta completato, è possibile pianificare una finestra di manutenzione e REPLACE INTO o UPDATE tutti i record modificati nella tabella di origine dalla copia iniziale dei dati. Una volta completato l'aggiornamento, un RENAME TABLE... di entrambe le tabelle esegue il wrapping delle modifiche.
  • Utilizzo di uno strumento come il cambio di schema pt-online di Percona: http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html. Questo strumento funziona con i trigger, quindi se hai già trigger sui tavoli che vuoi modificare, questo potrebbe non essere adatto alle tue esigenze.
3

Creare una nuova tabella con la nuova struttura desiderata con un nome diverso ad esempio NewTable.

Poi inserire i dati in questa nuova tabella dalla vecchia tabella utilizzando la seguente query:

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

Dopo aver fatto questo, è possibile eliminare la vecchia tabella e rinominare la nuova tabella al nome originale

DROP TABLE `OldTable`; 
RENAME TABLE `NewTable` TO `OldTable` ; 

Ho provato questo approccio su un tavolo molto grande ed è molto più veloce di modificare il tavolo.

6

Avete alcune scelte.

In ogni caso, è necessario eseguire un backup prima di eseguire questa operazione.

Una possibilità è quella di portare il vostro servizio offline e farlo sul posto, come avete provato. Se lo fai, dovresti disabilitare i controlli chiave e i vincoli.

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; 

Ciò consente all'operazione ALTER TABLE di andare più veloce. Rigenererà gli indici tutti insieme quando ENABLE KEYS.

Un'altra possibilità consiste nel creare una nuova tabella con il nuovo schema desiderato, quindi disabilitare i tasti sulla nuova tabella, quindi fare come suggerito da @Bader e inserire il contenuto della vecchia tabella.

Dopo aver creato la nuova tabella, riattiverai le chiavi, quindi rinomina la vecchia tabella con un nome come "old_bigtable", quindi rinomina la nuova tabella in "bigtable".

È possibile che sia possibile mantenere il servizio online mentre si sta compilando il nuovo tavolo. Ma potrebbe funzionare male.

Una terza possibilità consiste nel scaricare la tabella gigante (in un file flat) e quindi caricarla in una nuova tabella con il nuovo layout. Questa è praticamente la seconda possibilità, tranne per il fatto che si ottiene un backup della tabella gratuitamente. È possibile rendere questo andare abbastanza veloce con SELECT DATA INTO OUTFILE e LOAD DATA INFILE. Per fare ciò è necessario avere accesso al file system della propria macchina server.

In tutti i casi, disabilitare, quindi riattivare, i vincoli e le chiavi per far andare rapidamente le cose.

+1

il primo suona come quello che voglio Penso che tenterò di ruotare su qualche ora precedente all'istanza di amzaon rds e tentare questo prima di provare un'altra interruzione. – marioatlp

+2

Dopo aver avuto il tempo di lavorare su questo fine settimana, il problema con questo metodo è semplicemente che innodb non consente di disabilitare le chiavi. – marioatlp

Problemi correlati