2012-10-08 22 views
34

¿Por qué tarda más de una hora simplemente actualizar esta tabla para agregar una columna? Esta tabla tiene 15M filas. Tiene 2 índices y una clave principal de clave única. La consulta ALTER TABLE ha estado en el estado "copy to tmp table" durante 1 hora y 15 minutos.MySQL muy lento para la consulta de la tabla alterno

ALTER TABLE `frugg`.`item_catalog_map` 
ADD COLUMN `conversion_url` TEXT NULL DEFAULT NULL 

Tabla:

mysql> describe item_catalog_map; 
+------------------------+---------------+------+-----+---------+-------+ 
| Field     | Type   | Null | Key | Default | Extra | 
+------------------------+---------------+------+-----+---------+-------+ 
| catalog_unique_item_id | varchar(255) | NO | PRI | NULL |  | 
| catalog_id    | int(11)  | YES | MUL | NULL |  | 
| item_id    | int(11)  | YES | MUL | NULL |  | 
| price     | decimal(10,2) | YES |  | 0.00 |  | 
+------------------------+---------------+------+-----+---------+-------+ 

mysql> show index from item_catalog_map; 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table   | Non_unique | Key_name    | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
| item_catalog_map |   0 | PRIMARY    |   1 | catalog_unique_item_id | A   | 15485115 |  NULL | NULL |  | BTREE  |   | 
| item_catalog_map |   1 | IDX_ACD6184FCC3C66FC |   1 | catalog_id    | A   |   18 |  NULL | NULL | YES | BTREE  |   | 
| item_catalog_map |   1 | IDX_ACD6184F126F525E |   1 | item_id    | A   | 15485115 |  NULL | NULL | YES | BTREE  |   | 
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+ 
+1

Puede ser este hilo con una pregunta similar que te ayudará ... http: //stackoverflow.com/questions/1359097/mysql-alter-table-on-very-large-table-is-it-safe-to -run-it –

+1

Ir a través de este hilo también ... http: //stackoverflow.com/questions/5677932/optimize-mysql-for-faster-alter-table-add-column –

+0

Sería genial si hubiera algún tipo de la barra de progreso, mensaje de estado o, como mínimo, un cursor giratorio, LOL. Especialmente porque la "columna de modificación" ha dejado mi sitio fuera de línea. –

Respuesta

45

El rendimiento de ALTER TABLE de MySQL puede convertirse en un problema con tablas muy grandes. MySQL realiza la mayoría de las alteraciones creando una tabla vacía con la nueva estructura deseada, insertando todos los datos de la tabla anterior en la nueva y eliminando la tabla anterior. Esto puede llevar mucho tiempo, especialmente si tiene poca memoria y la tabla es grande y tiene muchos índices. Muchas personas tienen experiencia con operaciones ALTER TABLE que han tardado horas o días en completarse.

De todos modos, si es necesario proceder con la modificación de tabla, tal vez los siguientes recursos podrían ayudarle a:

+3

Si lleva tanto tiempo hay algo mal con su sistema de almacenamiento, no es algo de MySQL. – AndreKR

+0

estoy alterando de varchar a texto en una tabla de 30 filas, he estado esperando durante 20 minutos y todavía estoy en proceso. Qué puede ser ? – kommradHomer

+0

VARCHAR se almacena en la tabla, mientras que el texto se almacena por separado y la referencia se almacena en la tabla. Entonces ellos son muy diferentes. Supongo que se solicitó el cambio porque tiene un varchar muy grande y desea permitir valores mucho más grandes. En este caso, necesita mover todos los valores. – techdude

7

la tabla tiene 15 millones filas, lo cual es algo. ALTER TABLE implica copiar todos los datos de la tabla y recrear los índices. Como primera medida intente copiar el archivo de datos (item_catalog_map.MYD si es MyISAM) en su sistema de archivos y vea cuánto tiempo lleva. Este es el momento en el que ALTER TABLE hará tomar al menos.

5

Para minimizar el bloqueo de la gran tabla que quiero modificar, hago lo siguiente:

  • Crea una nueva tabla vacía basada en la tabla existente y modifica esta nueva tabla vacía.
  • Realice un mysqldump de la tabla grande de manera que tenga una instrucción de inserción completa por registro en la tabla grande (modificadores -c y -skip-extended-insert)
  • Importe este mysqldump a una base de datos diferente (vacía) con el vacío rebautizado large_table.
  • Tome un mysqldump de esta nueva tabla de cambio de nombre de la otra base de datos y la importación en la base de datos original
  • large_table Cambiar nombre y large_table_new en la base de datos original.

    mysql> create table DATABASE_NAME.LARGE_TABLE_NEW like DATABASE_NAME.LARGE_TABLE; 
    mysql> alter table DATABASE_NAME.LARGE_TABLE_NEW add column NEW_COLUMN_NAME COL_DATA_TYPE(SIZE) default null; 
    
    $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p DATABASE_NAME LARGE_TABLE > LARGE_TABLE.sql 
    
    mysql> create table test.LARGE_TABLE like DATABASE_NAME.LARGE_TABLE; 
    
    $ mysql -u root -p -D test < LARGE_TABLE.sql 
    
    mysql> rename table test.LARGE_TABLE to test.LARGE_TABLE_NEW; 
    
    $ mysqldump -c --no-create-info --skip-extended-insert --no-create-db -u root -p test LARGE_TABLE_NEW > LARGE_TABLE_NEW.sql 
    
    $ mysql -u root -p -D DATABASE_NAME < LARGE_TABLE_NEW.sql 
    
    mysql> rename table DATABASE_NAME.LARGE_TABLE to DATABASE_NAME.LARGE_TABLE_OLD, DATABASE_NAME.LARGE_TABLE_NEW to DATABASE_NAME.LARGE_TABLE; 
    
7

Las herramientas Percona son un salvavidas para estas cosas w/grandes mesas.

http://www.percona.com/doc/percona-toolkit/2.1/pt-online-schema-change.html

que básicamente:

  1. crear tabla duplicada
  2. crear gatillo para sincronizar las tablas
  3. copia masiva de datos
  4. verificar
  5. mesas de intercambio

Toma para siempre, pero a quién le importa porque esto significa que puede cambiar las columnas sin tiempo de inactividad.

+1

nada puede ayudar si tiene claves externas en sus tablas, porque no puede cambiar el nombre atómico de dos tablas – kommradHomer

14

Si no le importa el tiempo de inactividad, mi sugerencia es utilizar tres declaraciones ALTER TABLE separadas. La primera instrucción elimina todos los índices secundarios existentes. La segunda declaración aplica todos los cambios relacionados con la columna. La última declaración agrega índices secundarios caídos y aplica otros cambios de índice.

Otros dos consejos:

  1. aplicarán, antes de los cambios del índice, ejecute los siguientes dos comandos y cambiar los valores de nuevo a 1 después de terminar el cambio de índice.

    SET unique_checks=0; 
    SET foreign_key_checks=0; 
    
  2. Al crear varios índices secundarios, los puso en una declaración ALTER TABLE en lugar de múltiples separados ALTER TABLE declaraciones.

La siguiente imagen muestra la diferencia en el rendimiento. El acercamiento 1 es su acercamiento y el acercamiento 2 es mi manera. El enfoque 2 toma aproximadamente 3,47% de tiempo comparando con el enfoque 1 para una tabla de 50 m. La solución solo funciona para MySQL (> = 5.5) Motor InnoDB.

enter image description here

0

caso de alterar varias columnas a la vez que podría tomar más tiempo de lo esperado. En cambio, intente alterar una vez la columna a la vez. No encuentro el aspecto técnico de eso, pero experimenté el problema y lo supere.