MySQL очень медленный для запроса alter table

почему требуется больше часа, чтобы просто обновить эту таблицу, чтобы добавить столбец? Эта таблица имеет 15М строк. Он имеет 2 индекса и один ключевой первичный ключ. Запрос ALTER TABLE находится в состоянии "копировать в таблицу tmp"в течение 1 часа 15 минут.

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

стол:

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      |         |
+------------------+------------+----------------------+--------------+------------------------+-----------+-------------+----------+--------+------+------------+---------+

6 ответов


производительность ALTER TABLE MySQL может стать проблемой с очень большими таблицами. MySQL выполняет большинство изменений путем создания пустой таблицы с желаемой новой структурой, вставки всех данных из старой таблицы в новую и удаления старой таблицы. Это может занять очень много времени, особенно если у вас мало памяти, а таблица большая и имеет много индексов. Многие люди имеют опыт работы с операциями ALTER TABLE, которые заняли часы или дни полный.

в любом случае, если вам нужно продолжить работу с alter table, возможно, Вам помогут следующие ресурсы:


если вы не заботитесь о времени простоя, мое предложение использует три разделенных ALTER TABLE заявления. Первая инструкция удаляет все существующие вторичные индексы. Второй оператор применяет все изменения, связанные со столбцами. Последняя инструкция добавляет отброшенные вторичные индексы обратно и применяет другие изменения индекса.

еще два совета:

  1. перед применением изменений индекса выполните два следующих оператора и измените значения обратно на 1 после завершения изменение индекса.

    SET unique_checks=0;
    SET foreign_key_checks=0;
    
  2. при создании нескольких вторичных индексов поместите их в один ALTER TABLE заявление, а не несколько, разделенных ALTER TABLE заявления.

на следующем рисунке показана разница в производительности. Подход 1 подход 2 подход и мой путь. подход 2 занимает около 3,47% времени по сравнению с подходом 1 для таблицы 50m. решение работает только для MySQL (>=5.5) InnoDB двигатель.

enter image description here


инструменты Фирконом являются палочкой-выручалочкой на этот хлам Вт/ большие столы.

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

Они в основном:

  1. создать дубликат таблицы
  2. создать триггер для таблицы синхронизации
  3. массовое копирование данных
  4. проверка
  5. таблицы замены

длится вечно, но кто заботится, потому что это означает, что вы можете изменить столбцы без простоев.


ваша таблица имеет 15 миллионов строк, что является чем-то. ALTER TABLE включает копирование всех данных из таблицы и воссоздание индексов. В качестве первого измерения попробуйте скопировать файл данных (item_catalog_map.MYD, если это MyISAM) в вашей файловой системе и посмотреть, сколько времени это займет. Это время, когда ALTER TABLE будет по крайней мере принять.


для минимизации блокировки большой таблицы, которую я хочу изменить, я делаю следующее:

  • создайте новую пустую таблицу на основе существующей таблицы и измените эту новую пустую таблицу.
  • сделайте mysqldump большой таблицы таким, чтобы он имел один полный оператор вставки на запись в большой таблице (переключатели-c и --skip-extended-insert)
  • импортируйте этот mysqldump в другую (пустую) базу данных с пустым переименованным большой стол.
  • возьмите mysqldump этой новой таблицы переименования из другой базы данных и импортируйте ее в исходную базу данных
  • переименовать large_table и large_table_new в исходной базе данных.

    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;
    

Если вы измените сразу несколько столбцов, это может занять больше времени, чем вы ожидаете. Вместо этого попробуйте изменить один столбец за раз. Я не нахожу технической стороны этого, но я испытал проблему и прошел через нее.