Mysql 从大表中删除列
我有一个较大的表,有三列:Mysql 从大表中删除列,mysql,sql,Mysql,Sql,我有一个较大的表,有三列: +-----+-----+----------+ | id1 | id2 | associd | +-----+-----+----------+ | 1 | 38 | 73157604 | | 1 | 112 | 73157605 | | 1 | 113 | 73157606 | | 1 | 198 | 31936810 | | 1 | 391 | 73157607 | +-----+-----+----------+ 这将持续3800万行
+-----+-----+----------+
| id1 | id2 | associd |
+-----+-----+----------+
| 1 | 38 | 73157604 |
| 1 | 112 | 73157605 |
| 1 | 113 | 73157606 |
| 1 | 198 | 31936810 |
| 1 | 391 | 73157607 |
+-----+-----+----------+
这将持续3800万行。问题是我想删除'associd'列,但运行altertable TABLE\u name DROP column associd代码>只需花费太长时间。我想做一些类似的事情:altertable\u name SET UNUSED associd代码>和更改表名删除未使用的列检查点250代码>然后这显然加快了过程,但是
是否有其他方法可以删除此列--可能创建一个只包含两列的新表,或者删除检查点?您所做的任何事情都需要读取和写入3800万行,因此没有什么是真正快速的。最快的方法可能是将数据放入新表中:
create table newTable as
select id1, id2
from oldTable;
alter table my_table_new drop column column_to_delete;
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)
或者,如果要确保保留类型和索引:
create table newTable like oldTable;
alter table newTable drop column assocId;
insert into newTable(id1, id2)
select id1, id2
from oldTable;
但是,在加载一组数据之前删除表上的所有索引,然后在加载后重新创建索引通常会更快。免责声明:这个答案是面向MySQL的,可能不适用于其他数据库
我认为在公认的答案中缺少了一些东西,我已经尝试在这里公开了一个在生产环境中执行此类操作的通用序列,不仅用于添加/删除列,还用于添加索引(例如)
我们称之为
创建一个新表
使用旧表作为模板的新表:
create table my_table_new like my_table;
删除新表中的列
在新表中:
create table newTable as
select id1, id2
from oldTable;
alter table my_table_new drop column column_to_delete;
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)
将外键添加到新表中
不会像
命令那样在创建表中自动生成
您可以检查实际的外键:
mysql> show create table my_table;
然后将它们应用于新表:
create table newTable as
select id1, id2
from oldTable;
alter table my_table_new drop column column_to_delete;
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
将不断有新记录,因此我们必须保持同步,直到能够更改名称为止
此外,我还添加了一个限制
,因为如果表太大,索引太重,那么进行一次性克隆可能会关闭数据库的性能。另外,如果在进程的中间要取消操作,则必须回滚所有已经完成的插入,这意味着数据库不会立即恢复()
当我多次这样做时,我创建了一个过程:
名字改了吗
确保在复制表中的最后记录后立即运行此命令。最好一次运行所有命令
rename table my_table to my_table_3;
rename table my_table_new to my_table;
删除旧表
在执行此操作之前,请确保有备份;)
免责声明:我不确定指向旧表的外键会发生什么情况。在这种情况下,MySQL的最佳解决方案是:
1) 将表Engine
更改为MyISAM
2) 更改您想做的任何事情(删除列、更改数据类型等)
3) 将其更改回InnoDB
在这种情况下,DBMS不会在每次记录迭代时锁定/解锁
但是请注意,如果您的表/数据库中有几项内容需要更改,则此解决方案会很好,因为一旦将其恢复到InnoDB
,删除一列所需的时间将相同。
因此,只有在数据库中有多个事情要改变时才考虑这个解决方案。< /P>我删除了SQL Server标记,因为问题明确地涉及MySQL。这花费了17:09分钟,这比删除列快得多(我在三小时后停止了),我很惊讶,但是我很感激它的帮助。戈登,我想知道为什么复制两列要比删除一行快。你能告诉我为什么吗?@BoratSagdiyev。对现有表的修改在锁定和锁定表的部分以及记录所有更改方面需要大量开销。创建新表更加优化。@GordonLinoff-谢谢。我在哪里可以得到更多关于这方面的信息?这是一个挑战是所有的rdbms还是只有mysql?@BoratSagdiyev。这在所有数据库中都是一个问题,而且记录得相当糟糕。基本思想是引擎可以识别“批量插入”类型的操作,但更新实际上是逐行进行的(从某种意义上说,尽管更新可以并行运行)。一个快速的Google在SQL Server上生成了这个示例:。谢谢!我在MySQL 5.5服务器上的几个非常大(5000万条记录)的表上进行在线DDL更改时遇到困难,该服务器还不支持ALGORITHM=INPLACE。在执行此操作之前,应删除指向旧表的外键,并在重命名后重新创建外键。这也需要一些时间。重命名表是原子的,所以这是真正的在线DDL更改。