简体   繁体   English

ALTER TABLE ADD COLUMN 需要很长时间

[英]ALTER TABLE ADD COLUMN takes a long time

I was just trying to add a column called "location" to a table (main_table) in a database.我只是想将一个名为“location”的列添加到数据库中的表 (main_table) 中。 The command I run was我运行的命令是

ALTER TABLE main_table ADD COLUMN location varchar (256);

The main_table contains > 2,000,000 rows. main_table 包含 > 2,000,000 行。 It keeps running for more than 2 hours and still not completed.它持续运行了2个多小时,仍然没有完成。

I tried to use mytop to monitor the activity of this database to make sure that the query is not locked by other querying process, but it seems not.我尝试使用mytop来监控这个数据库的活动,以确保查询没有被其他查询进程锁定,但似乎没有。 Is it supposed to take that long time?应该需要那么长时间吗? Actually, I just rebooted the machine before running this command.实际上,我只是在运行此命令之前重新启动了机器。 Now this command is still running.现在这个命令仍在运行。 I am not sure what to do.我不知道该怎么做。

Your ALTER TABLE statement implies mysql will have to re-write every single row of the table including the new column.您的ALTER TABLE语句意味着 mysql 将不得不重写表的每一行,包括新列。 Since you have more than 2 million rows, I would definitely expect it takes a significant amount of time, during which your server will likely be mostly IO-bound.由于您有超过 200 万行,我肯定会期望它花费大量时间,在此期间您的服务器可能主要受 IO 限制。 You'd usually find it's more performant to do the following:您通常会发现执行以下操作会更高效:

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;

This way you add the column on the empty table, and basically write the data in that new table that you are sure no-one else will be looking at without locking as much resources.通过这种方式,您可以在空表上添加列,并基本上将数据写入该新表中,您确信没有其他人会在不锁定尽可能多的资源的情况下查看这些数据。

I think the appropriate answer for this is using a feature like pt-online-schema-change or gh-ost .我认为对此的适当答案是使用pt-online-schema-changegh-ost 之类的功能

We have done migration of over 4 billion rows with this, though it can take upto 10 days, with less than a minute of downtime.我们已经用这个完成了超过 40 亿行的迁移,尽管它可能需要长达 10 天的时间,停机时间不到一分钟。

Percona works in a very similar fashion as above Percona 的工作方式与上述非常相似

  • Create a temp table创建临时表
  • Creates triggers on the first table (for inserts, updates, deletes) so that they are replicated to the temp table在第一个表上创建触发器(用于插入、更新、删除),以便将它们复制到临时表
  • In small batches, migrate data小批量迁移数据
  • When done, rename table to new table, and drop the other table完成后,将表重命名为新表,并删除另一个表

Alter table takes a long time with a big data like in your case, so avoid to use it in such situations, and use some code like this one:像您这样的大数据,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;

You can speed up the process by temporarily turning off unique checks and foreign key checks.您可以通过暂时关闭唯一检查和外键检查来加快进程。 You can also change the algorithm that gets used.您还可以更改使用的算法。

If you want the new column to be at the end of the table, then you should use algorithm=instant :如果您希望新列位于表的末尾,则应使用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;

Otherwise, if you need the column to be in a specific location, use algorithm=inplace :否则,如果您需要该列位于特定位置,请使用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;

For reference, it took my PC about 2 minutes to alter a table with 20 million rows using the inplace algorithm.作为参考,我的 PC 用了大约 2 分钟的时间使用就地算法更改一个包含 2000 万行的表。 If you're using a program like Workbench, then you may want to increase the default timeout period in your settings before starting the operation.如果您使用的是 Workbench 之类的程序,那么您可能希望在开始操作之前增加设置中的默认超时时间。

If you find that the operation is hanging indefinitely, then you may need to look through the list of processes and kill whatever process has a lock on the table.如果您发现操作无限期挂起,那么您可能需要查看进程列表并杀死表上有锁定的任何进程。 You can do that using these commands:您可以使用以下命令执行此操作:

SHOW FULL PROCESSLIST;
KILL PROCESS_NUMBER_GOES_HERE;

DB2 z/OS does a virtual add of the column instantly. DB2 z/OS 立即对列进行虚拟添加。 And puts the table into Advisory-Reorg status.并将表置于咨询重组状态。 Anything that runs before the reorg gets the default value or null if no default.在重组之前运行的任何内容都将获得默认值,如果没有默认值,则为 null。 When updates are done, they expand the rows updated.更新完成后,它们会展开更新的行。 Inserts are done expanded.插入已完成扩展。 The next reorg expands every unexpanded row and assigns the default value to anything it expands.下一次重组将扩展每个未扩展的行,并将默认值分配给它扩展的任何内容。

Only a real database handles this well.只有真正的数据库才能很好地处理这个问题。 DB2 z/OS. DB2 z/OS。

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

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