Один верный способ ускорить ALTER TABLE - удалить ненужные индексы
Вот начальные шаги для загрузки новой версии таблицы
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
;
Пожалуйста, обратите внимание на следующее:
Я удалил source_persona_index, потому что это первый столбец в 4 других индексах
- unique_target_persona
- unique_target_object
- source_and_target_object_index
- source_target_persona_index
Я удалил target_persona_index, потому что это первый столбец в 2 других индексах
- target_persona_relation_type_index
- target_persona_relation_type_message_id_index
Я удалил target_persona_relation_type_index, потому что первые 2 столбца также находятся в target_persona_relation_type_message_id_index
ОК Это заботится о ненужных индексах. Есть ли показатели, которые имеют низкую мощность? Вот способ определить это:
Запустите следующие запросы:
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;
По твоему вопросу там около 80 000 000 строк. Как показывает практика, MySQL Query Optimizer не будет использовать индекс, если количество элементов в выбранных столбцах превышает 5% от числа строк таблицы. В этом случае это будет 4 000 000.
- Если
COUNT(DISTINCT sent_at)
> 4 000 000
- тогда
ALTER TABLE s_relations_new
DROP INDEX sent_at_index;
- Если
COUNT(DISTINCT message_id)
> 4 000 000
- тогда
ALTER TABLE s_relations_new
DROP INDEX message_id_index;
- Если
COUNT(DISTINCT target_object_id)
> 4 000 000
- тогда
ALTER TABLE s_relations_new
DROP INDEX target_object_index;
После определения полезности или бесполезности этих индексов вы можете перезагрузить данные
#
# 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;
Вот так, верно? НЕТ !!!
Если ваш сайт работал все это время, возможно, во время загрузки s_relations_new могут выполняться команды INSERT для s_relations. Как вы можете восстановить эти пропущенные строки?
Найдите максимальный идентификатор в s_relations_new и добавьте все после этого идентификатора из s_relations. Чтобы убедиться, что таблица заморожена и используется только для этого обновления, у вас должно быть небольшое время простоя ради получения тех последних строк, которые были вставлены в s_relation_new. Вот что ты делаешь:
В ОС перезапустите mysql, чтобы никто другой не мог войти в систему, кроме root @ localhost (отключает TCP / IP):
$ service mysql restart --skip-networking
Затем войдите в MySQL и загрузите последние строки:
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;
Затем перезапустите MySQL нормально
$ service mysql restart
Теперь, если вы не можете избавиться от mysql, вам придется использовать s_relations. Просто войдите в MySQL и сделайте следующее:
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;
Попробуйте!
ПРЕДОСТЕРЕЖЕНИЕ: Как только вы будете удовлетворены этой операцией, вы можете отказаться от старой таблицы при первой же возможности:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
, покажите столбец, который необходимо изменить, тип данных столбца и новое имя столбца.