繁体   English   中英

ALTER TABLE ADD COLUMN 需要很长时间

[英]ALTER TABLE ADD COLUMN takes a long time

我只是想将一个名为“location”的列添加到数据库中的表 (main_table) 中。 我运行的命令是

ALTER TABLE main_table ADD COLUMN location varchar (256);

main_table 包含 > 2,000,000 行。 它持续运行了2个多小时,仍然没有完成。

我尝试使用mytop来监控这个数据库的活动,以确保查询没有被其他查询进程锁定,但似乎没有。 应该需要那么长时间吗? 实际上,我只是在运行此命令之前重新启动了机器。 现在这个命令仍在运行。 我不知道该怎么做。

您的ALTER TABLE语句意味着 mysql 将不得不重写表的每一行,包括新列。 由于您有超过 200 万行,我肯定会期望它花费大量时间,在此期间您的服务器可能主要受 IO 限制。 您通常会发现执行以下操作会更高效:

CREATE TABLE main_table_new LIKE main_table;
ALTER TABLE main_table_new ADD COLUMN location VARCHAR(256);
INSERT INTO main_table_new SELECT *, NULL FROM main_table;
RENAME TABLE main_table TO main_table_old, main_table_new TO main_table;
DROP TABLE main_table_old;

通过这种方式,您可以在空表上添加列,并基本上将数据写入该新表中,您确信没有其他人会在不锁定尽可能多的资源的情况下查看这些数据。

我认为对此的适当答案是使用pt-online-schema-changegh-ost 之类的功能

我们已经用这个完成了超过 40 亿行的迁移,尽管它可能需要长达 10 天的时间,停机时间不到一分钟。

Percona 的工作方式与上述非常相似

  • 创建临时表
  • 在第一个表上创建触发器(用于插入、更新、删除),以便将它们复制到临时表
  • 小批量迁移数据
  • 完成后,将表重命名为新表,并删除另一个表

像您这样的大数据,Alter table 需要很长时间,因此请避免在这种情况下使用它,并使用如下代码:

select main_table.*, 
  cast(null as varchar(256)) as null_location, -- any column you want accepts null
  cast('' as varchar(256)) as not_null_location, --any column doesn't accept null
  cast(0 as int) as not_null_int, -- int column doesn't accept null
into new_table 
from main_table;

drop table main_table;
rename table new_table TO main_table;

您可以通过暂时关闭唯一检查和外键检查来加快进程。 您还可以更改使用的算法。

如果您希望新列位于表的末尾,则应使用algorithm=instant

SET unique_checks = 0;
SET foreign_key_checks = 0;
ALTER TABLE main_table ADD location varchar(256), algorithm=instant;
SET unique_checks = 1;
SET foreign_key_checks = 1;

否则,如果您需要该列位于特定位置,请使用algorithm=inplace

SET unique_checks = 0;
SET foreign_key_checks = 0;
ALTER TABLE main_table ADD location varchar(256) AFTER othercolumn, algorithm=inplace;
SET unique_checks = 1;
SET foreign_key_checks = 1;

作为参考,我的 PC 用了大约 2 分钟的时间使用就地算法更改一个包含 2000 万行的表。 如果您使用的是 Workbench 之类的程序,那么您可能希望在开始操作之前增加设置中的默认超时时间。

如果您发现操作无限期挂起,那么您可能需要查看进程列表并杀死表上有锁定的任何进程。 您可以使用以下命令执行此操作:

SHOW FULL PROCESSLIST;
KILL PROCESS_NUMBER_GOES_HERE;

DB2 z/OS 立即对列进行虚拟添加。 并将表置于咨询重组状态。 在重组之前运行的任何内容都将获得默认值,如果没有默认值,则为 null。 更新完成后,它们会展开更新的行。 插入已完成扩展。 下一次重组将扩展每个未扩展的行,并将默认值分配给它扩展的任何内容。

只有真正的数据库才能很好地处理这个问题。 DB2 z/OS。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM