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 mytop
to 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.
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.
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
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;