Un modo sicuro per accelerare una tabella ALTER è rimuovere gli indici non necessari
Ecco i passaggi iniziali per caricare una nuova versione della tabella
CREATE TABLE s_relations_new LIKE s_relations;
#
# Drop Duplicate Indexes
#
ALTER TABLE s_relations_new
DROP INDEX source_persona_index,
DROP INDEX target_persona_index,
DROP INDEX target_persona_relation_type_index
;
Si prega di notare quanto segue:
Ho lasciato source_persona_index perché è la prima colonna in altri 4 indici
- unique_target_persona
- unique_target_object
- source_and_target_object_index
- source_target_persona_index
Ho eliminato target_persona_index perché è la prima colonna in altri 2 indici
- target_persona_relation_type_index
- target_persona_relation_type_message_id_index
Ho eliminato target_persona_relation_type_index perché le prime 2 colonne sono anche in target_persona_relation_type_message_id_index
OK Questo si occupa di indici non necessari. Esistono indici con cardinalità bassa? Ecco il modo per determinare che:
Esegui le seguenti query:
SELECT COUNT(DISTINCT sent_at) FROM s_relations;
SELECT COUNT(DISTINCT message_id) FROM s_relations;
SELECT COUNT(DISTINCT target_object_id) FROM s_relations;
Secondo la tua domanda, ci sono circa 80.000.000 di righe. Come regola generale, lo Strumento per ottimizzare le query MySQL non utilizzerà un indice se la cardinalità delle colonne selezionate è maggiore del 5% del conteggio delle righe della tabella. In questo caso, sarebbe 4.000.000.
- Se
COUNT(DISTINCT sent_at)
> 4.000.000
- poi
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Se
COUNT(DISTINCT message_id)
> 4.000.000
- poi
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Se
COUNT(DISTINCT target_object_id)
> 4.000.000
- poi
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
Una volta determinata l'utilità o l'inutilità di tali indici, è possibile ricaricare i dati
#
# Change the Column Name
# Load the Table
#
ALTER TABLE s_relations_new CHANGE sent_at sent_at_new int(11) DEFAULT NULL;
INSERT INTO s_relations_new SELECT * FROM s_relations;
Esatto, vero? NO !!!
Se il tuo sito Web è stato attivo per tutto questo tempo, potrebbero esserci INSERT in esecuzione contro s_relations durante il caricamento di s_relations_new. Come puoi recuperare quelle righe mancanti?
Vai a trovare l'id massimo in s_relations_new e aggiungi tutto dopo quell'ID da s_relations. Per garantire che la tabella sia congelata e utilizzata solo per questo aggiornamento, è necessario avere un po 'di tempo di inattività per ottenere quelle ultime righe che sono state inserite in s_relation_new. Ecco cosa fai:
Nel sistema operativo, riavviare mysql in modo che nessun altro possa accedere tranne root @ localhost (disabilita TCP / IP):
$ service mysql restart --skip-networking
Quindi, accedi a mysql e carica le ultime righe:
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Quindi, riavvia mysql normalmente
$ service mysql restart
Ora, se non riesci a smontare mysql, dovrai fare un esca-e-cambiare su s_relations. Accedi a mysql e procedi come segue:
mysql> ALTER TABLE s_relations RENAME s_relations_old;
mysql> SELECT MAX(id) INTO @maxidnew FROM s_relations_new;
mysql> INSERT INTO s_relations_new SELECT * FROM s_relations_old WHERE id > @maxidnew;
mysql> ALTER TABLE s_relations_new RENAME s_relations;
Provaci !!!
CAVEAT: una volta che sei soddisfatto di questa operazione, puoi lasciare il vecchio tavolo al più presto:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
, mostra la colonna che deve essere cambiata, il tipo di dati della colonna e il nuovo nome per la colonna.