MySQL:从大表中删除列

nic*_*ico 24 mysql sql phpmyadmin

我有这样一个有三列的大表:

+-----+-----+----------+
| id1 | id2 | associd  |
+-----+-----+----------+
|   1 |  38 | 73157604 |
|   1 | 112 | 73157605 |
|   1 | 113 | 73157606 |
|   1 | 198 | 31936810 |
|   1 | 391 | 73157607 |
+-----+-----+----------+
Run Code Online (Sandbox Code Playgroud)

这持续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?

是否有替代方法可以删除此列 - 可能只创建一个只包含两列的新表或者使用检查点进行删除?谢谢!

Gor*_*off 33

你做的任何事情都需要读取和写入38米的行,所以没有什么是真正的快速.可能最快的方法可能是将数据放入新表:

create table newTable as
    select id1, id2
    from oldTable;
Run Code Online (Sandbox Code Playgroud)

或者,如果您想确保保留类型和索引:

create table newTable like oldTable;

alter table newTable drop column assocId;

insert into newTable(id1, id2)
    select id1, id2
    from oldTable;
Run Code Online (Sandbox Code Playgroud)

但是,在加载一堆数据然后重新创建索引之前,通常会更快地删除表上的所有索引.

  • 这花了 17:09 分钟,这比移除列(我在三个小时后停止)要快得多,我很惊讶,但我感谢您的帮助! (2认同)
  • 戈登,我想知道为什么复制两列比只删除一行更快。你能告诉我为什么吗? (2认同)
  • @BoratSagdiyev...对现有表的修改在锁定和锁定表的部分以及记录所有更改方面需要很多开销.创建新表格更加优化. (2认同)

fgu*_*len 9

免责声明:这个答案是面向 MySQL 的,可能不适用于其他数据库。

我认为在接受的答案中缺少一些东西,我试图在这里公开我用来在生产环境中执行此类操作的通用序列,不仅用于添加/删除列,还用于添加索引。

我们称之为印第安纳琼斯运动

创建一个新表

使用旧表作为模板的新表:

create table my_table_new like my_table;
Run Code Online (Sandbox Code Playgroud)

删除新表中的列

在新表中:

alter table my_table_new drop column column_to_delete;
Run Code Online (Sandbox Code Playgroud)

将外键添加到新表中

不会在create table like命令中自动生成。

您可以检查实际的外键:

mysql> show create table my_table;
Run Code Online (Sandbox Code Playgroud)

然后将它们应用到新表:

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)
Run Code Online (Sandbox Code Playgroud)

克隆表

复制所有字段,但要删除的字段除外。

where如有必要,我使用一句话可以多次运行此命令。

因为我认为这是一个生产环境,my_table它将不断有新记录,所以我们必须保持同步,直到我们能够更改名称。

我还添加了一个,limit因为如果表太大且索引太重,则一次性克隆可能会关闭数据库的性能。另外,如果在此过程中您想取消操作,则必须回滚所有已完成的插入,这意味着您的数据库不会立即恢复(https://dba.stackexchange.com/questions/5654/内部原因杀死进程占用时间在 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; 
Run Code Online (Sandbox Code Playgroud)

由于我多次这样做,我创建了一个程序:https : //gist.github.com/fguillen/5abe87f922912709cd8b8a8a44553fe7

改名字

确保在复制表中的最后一条记录后立即运行此命令。理想情况下一次运行所有命令。

rename table my_table to my_table_3;
rename table my_table_new to my_table;
Run Code Online (Sandbox Code Playgroud)

删除旧表

在执行此操作之前,请确保您有备份;)

drop table my_table_3
Run Code Online (Sandbox Code Playgroud)

免责声明:我不确定指向旧表的外键会发生什么。