Una forma segura de acelerar una ALTER TABLE es eliminar índices innecesarios
Estos son los pasos iniciales para cargar una nueva versión de la tabla.
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
;
Tenga en cuenta lo siguiente:
Descarté source_persona_index porque es la primera columna en otros 4 índices
- unique_target_persona
- unique_target_object
- source_and_target_object_index
- source_target_persona_index
Descarté target_persona_index porque es la primera columna en otros 2 índices
- target_persona_relation_type_index
- target_persona_relation_type_message_id_index
Descarté target_persona_relation_type_index porque las primeras 2 columnas también están en target_persona_relation_type_message_id_index
OK Eso se encarga de índices innecesarios. ¿Hay algún índice que tenga baja cardinalidad? Aquí está la forma de determinar eso:
Ejecute las siguientes consultas:
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;
Según su pregunta, hay alrededor de 80,000,000 de filas. Como regla general, MySQL Query Optimizer no usará un índice si la cardinalidad de las columnas seleccionadas es mayor que el 5% del recuento de filas de la tabla. En este caso, eso sería 4,000,000.
- Si
COUNT(DISTINCT sent_at)
> 4,000,000
- entonces
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Si
COUNT(DISTINCT message_id)
> 4,000,000
- entonces
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Si
COUNT(DISTINCT target_object_id)
> 4,000,000
- entonces
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
Una vez que se ha determinado la utilidad o inutilidad de esos índices, puede volver a cargar los datos.
#
# 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;
Eso es todo, ¿verdad? NO !!!
Si su sitio web ha estado activo todo este tiempo, puede haber INSERTs ejecutándose contra s_relations durante la carga de s_relations_new. ¿Cómo puedes recuperar esas filas que faltan?
Busque la identificación máxima en s_relations_new y agregue todo después de esa ID de s_relations. Para garantizar que la tabla se congele y se use solo para esta actualización, debe tener un poco de tiempo de inactividad para obtener las últimas filas que se insertaron en s_relation_new. Aquí está lo que haces:
En el sistema operativo, reinicie mysql para que nadie más pueda iniciar sesión pero root @ localhost (deshabilita TCP / IP):
$ service mysql restart --skip-networking
A continuación, inicie sesión en mysql y cargue esas últimas filas:
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;
Luego, reinicie mysql normalmente
$ service mysql restart
Ahora, si no puede eliminar mysql, tendrá que hacer un cebo y activar s_relations. Simplemente inicie sesión en mysql y haga lo siguiente:
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;
Darle una oportunidad !!!
PRECAUCIÓN: una vez que esté satisfecho con esta operación, puede abandonar la tabla anterior lo antes posible:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
la columna que debe modificarse, el tipo de datos de la columna y el nuevo nombre de la columna.