У меня есть такая большая таблица с тремя столбцами как таковая:

+-----+-----+----------+
| id1 | id2 | associd  |
+-----+-----+----------+
|   1 |  38 | 73157604 |
|   1 | 112 | 73157605 |
|   1 | 113 | 73157606 |
|   1 | 198 | 31936810 |
|   1 | 391 | 73157607 |
+-----+-----+----------+

Это продолжается для 38-метровых рядов. Проблема в том, что я хочу удалить столбец «associd», но запуск ALTER TABLE table_name DROP COLUMN associd; просто занимает слишком много времени. Я хотел сделать что-то вроде: ALTER TABLE table_name SET UNUSED associd; и ALTER TABLE table_name DROP UNUSED COLUMNS CHECKPOINT 250;, что, по-видимому, ускоряет процесс, но это невозможно в MySQL?

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

28
nico 19 Апр 2014 в 22:23

3 ответа

Лучший ответ

Все, что вы делаете, потребует чтения и записи 38-метровых строк, так что ничего не будет по-настоящему быстро. Вероятно, самый быстрый способ - это поместить данные в новую таблицу:

create table newTable as
    select id1, id2
    from oldTable;

Или, если вы хотите быть уверены, что сохраняете типы и индексы:

create table newTable like oldTable;

alter table newTable drop column assocId;

insert into newTable(id1, id2)
    select id1, id2
    from oldTable;

Однако обычно быстрее удалить весь индекс в таблице перед загрузкой группы данных, а затем заново создать индексы.

38
Gordon Linoff 19 Апр 2014 в 18:31

Отказ от ответственности: этот ответ ориентирован на MySQL и может не работать для других баз данных.

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

Мы называем это движением Индианы Джонса.

Создать новую таблицу

Новая таблица с использованием старой в качестве шаблона:

create table my_table_new like my_table;

Удалите столбец в новой таблице

В новой таблице:

alter table my_table_new drop column column_to_delete;

Добавьте внешние ключи в новую таблицу

Они не генерируются автоматически в команде create table like.

Вы можете проверить фактические внешние ключи:

mysql> show create table my_table;

Затем примените их к новой таблице:

alter table my_table_new
  add constraint my_table_fk_1 foreign key (field_1) references other_table_1 (id),
  add constraint my_table_fk_2 foreign key (field_2) references other_table_2 (id)

Клонировать стол

Скопируйте все поля, кроме того, которое хотите удалить.

Я использую предложение where, чтобы иметь возможность запускать эту команду много раз, если это необходимо.

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

Также я добавил limit, потому что, если таблица слишком велика, а индексы слишком тяжелые, создание одноразового клона может снизить производительность вашей базы данных. Кроме того, если в середине процесса вы хотите отменить операцию, он должен будет откатить все уже выполненные вставки, что означает, что ваша база данных не будет восстановлена ​​мгновенно (https://dba.stackexchange.com/questions/5654/internal-reason-for-killing- долгое время-в-MySQL )

insert my_table_new select field_1, field_2, field_3 from my_table 
where id > ifnull((select max(id) from my_table_new), 0)
limit 100000; 

Поскольку я делал это несколько раз, я создал процедуру: https://gist.github.com/fguillen/ 5abe87f922912709cd8b8a8a44553fe7

Смените имя

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

rename table my_table to my_table_3;
rename table my_table_new to my_table;

Удалить старую таблицу

Перед этим убедитесь, что у вас есть резервная копия;)

drop table my_table_3

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

8
Wilianto Indrawan 17 Фев 2021 в 10:19

Лучшее решение в этом случае в MySQL:

1) измените таблицу Engine на MyISAM

2) измените все, что хотите (удалить столбец, изменить тип данных и т. Д.)

3) измените его обратно на InnoDB

В этом случае СУБД не будет блокировать / разблокировать на каждой итерации записи.

Однако обратите внимание, что это решение было бы хорошо, если у вас есть несколько вещей, которые вы хотите изменить в своей таблице / базе данных, потому что, как только вы вернете его обратно к InnoDB, это займет столько же времени, чтобы удалить один столбец. Поэтому рассматривайте это решение только в том случае, если вам нужно изменить несколько вещей в своей базе данных.

0
Alan Deep 18 Окт 2018 в 03:22