web-dev-qa-db-fra.com

ALTER TABLE ADD COLUMN prend beaucoup de temps

J'essayais simplement d'ajouter une colonne appelée "location" à une table (main_table) d'une base de données. La commande que j'ai lancée était

ALTER TABLE main_table ADD COLUMN location varchar (256);

La table principale contient plus de 2 000 000 de lignes. Il continue à fonctionner pendant plus de 2 heures et n'est toujours pas terminé. 

J'ai essayé d'utiliser mytopto pour surveiller l'activité de cette base de données afin de m'assurer que la requête n'est pas verrouillée par un autre processus de requête, mais il semble que non. Est-ce censé prendre autant de temps? En fait, je viens de redémarrer la machine avant d'exécuter cette commande. Maintenant, cette commande est toujours en cours d'exécution. Je ne sais pas quoi faire. 

57
fanchyna

Votre déclaration ALTER TABLE implique que mysql devra réécrire chaque ligne de la table, y compris la nouvelle colonne. Étant donné que vous avez plus de 2 millions de lignes, je m'attendrais certainement à ce que cela prenne un temps considérable, au cours duquel votre serveur sera probablement principalement lié à l'IO. Vous trouverez généralement plus performant de faire ce qui suit:

CREATE TABLE main_table_new LIKE main_table;
ALTER TABLE main_table_new ADD COLUMN location varchar(256);
INSERT INTO main_table_new (fields_in_main_table) SELECT * FROM main_table;
RENAME TABLE main_table TO main_table_old, main_table_new TO main_table;
DROP TABLE main_table_old;

De cette manière, vous ajoutez la colonne à la table vide et écrivez les données de cette nouvelle table que vous êtes certain de ne regarder personne d'autre sans verrouiller autant de ressources.

163
Romain

Je pense que la solution appropriée consiste à utiliser une fonctionnalité telle que pt-online-schema-change ou gh-ost

Nous avons effectué une migration de plus de 4 milliards de lignes avec cela, bien que cela puisse prendre jusqu'à 10 jours, avec moins d’une minute de temps mort. 

Percona fonctionne de la même manière que ci-dessus

  • Créer une table temporaire
  • Crée des déclencheurs sur la première table (pour les insertions, les mises à jour, les suppressions) afin qu'ils soient répliqués dans la table temporaire
  • Migration des données en petits lots
  • Une fois terminé, renommez la table en nouvelle table et supprimez l’autre table.
21
Pratik Bothra

Modifier une table prend beaucoup de temps avec des données volumineuses comme dans votre cas, évitez donc de les utiliser dans de telles situations et utilisez du code comme celui-ci:

select main_table.*, 
  cast(null as varchar(256)) as null_location, -- any column you want accepts null
  cast('' as varchar(256)) as not_null_location, --any column doesn't accept null
  cast(0 as int) as not_null_int, -- int column doesn't accept null
into new_table 
from main_table;

drop table main_table;
rename table new_table TO main_table;
0
ZORRO_BLANCO