Один вірний спосіб пришвидшити 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 інших індексах
- унікальний_target_persona
- унікальний_target_object
- source_and_target_object_index
- source_target_persona_index
Я скинув target_persona_index, оскільки це перший стовпець у двох інших індексах
- 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 не буде використовувати індекс, якщо кардинальність вибраних стовпців перевищує 5% від кількості рядків таблиці. У цьому випадку це було б 4 мільйони.
- Якщо
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;
Спробувати !!!
CAVEAT: Після того, як ви будете задоволені цією операцією, ви можете кинути стару таблицю якнайшвидше:
mysql> DROP TABLE s_relations_old;
SHOW CREATE TABLE tblname\G
Покажіть, будь ласка , стовпець, який потрібно змінити, тип даних стовпця та нову назву стовпця.