Un moyen sûr d'accélérer une ALTER TABLE est de supprimer les index inutiles
Voici les étapes initiales pour charger une nouvelle version du tableau
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
;
Veuillez noter ce qui suit:
J'ai laissé tomber source_persona_index car c'est la première colonne de 4 autres index
- unique_target_persona
- unique_target_object
- source_and_target_object_index
- source_target_persona_index
J'ai supprimé target_persona_index car c'est la première colonne de 2 autres index
- target_persona_relation_type_index
- target_persona_relation_type_message_id_index
J'ai supprimé target_persona_relation_type_index car les 2 premières colonnes se trouvent également dans target_persona_relation_type_message_id_index
OK Cela prend en charge les index inutiles. Y a-t-il des index à faible cardinalité? Voici la façon de déterminer que:
Exécutez les requêtes suivantes:
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;
Selon votre question, il y a environ 80 000 000 lignes. En règle générale, MySQL Query Optimizer n'utilisera pas d'index si la cardinalité des colonnes sélectionnées est supérieure à 5% du nombre de lignes de table. Dans ce cas, ce serait 4 000 000.
- Si
COUNT(DISTINCT sent_at)
> 4 000 000
- puis
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Si
COUNT(DISTINCT message_id)
> 4 000 000
- puis
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Si
COUNT(DISTINCT target_object_id)
> 4 000 000
- puis
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
Une fois l'utilité ou l'inutilité de ces index déterminées, vous pouvez recharger les données
#
# 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;
C'est ça, non? NAN !!!
Si votre site Web a été mis en place pendant tout ce temps, des INSERT peuvent s'exécuter sur s_relations lors du chargement de s_relations_new. Comment pouvez-vous récupérer ces lignes manquantes?
Allez trouver l'ID maximum dans s_relations_new et ajoutez tout après cet ID dans s_relations. Pour vous assurer que la table est figée et utilisée uniquement pour cette mise à jour, vous devez disposer d'un petit temps d'arrêt afin d'obtenir les dernières lignes insérées dans s_relation_new. Voici ce que vous faites:
Dans l'OS, redémarrez mysql pour que personne d'autre ne puisse se connecter mais root @ localhost (désactive TCP / IP):
$ service mysql restart --skip-networking
Ensuite, connectez-vous à mysql et chargez ces dernières lignes:
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;
Ensuite, redémarrez mysql normalement
$ service mysql restart
Maintenant, si vous ne pouvez pas supprimer mysql, vous devrez faire un appât et basculer sur s_relations. Connectez-vous simplement à mysql et procédez comme suit:
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;
Essaie !!!
CAVEAT: Une fois que vous êtes satisfait de cette opération, vous pouvez déposer l'ancienne table à votre convenance:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
indiquer la colonne à modifier, le type de données de la colonne et le nouveau nom de la colonne.