简体   繁体   English

为什么添加 AUTO_INCREMENT 需要这么长时间?

[英]Why does adding AUTO_INCREMENT take so long?

Say I have a table说我有一张桌子

CREATE TABLE `tab_sample` (
  `id` bigint(20) NOT NULL,
  `something` char(2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

I would like to turn it into我想把它变成

CREATE TABLE `tab_sample` (
  `id` bigint(20) NOT NULL,
  `something` char(2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

But

ALTER TABLE `tab_sample` MODIFY
  id bigint(20) NOT NULL AUTO_INCREMENT;

takes forever if the table is big, because for some reason, MYSQL decides to have to rewrite the whole thing (copying to temp table first, ...).如果表很大,则需要永远,因为出于某种原因,MYSQL 决定必须重写整个事情(首先复制到临时表,...)。

Is there a better way to do it?有没有更好的方法来做到这一点? In the end, this should really just change a rule for the default value of id , shouldn't it?最后,这真的应该只是更改id的默认值的规则,不是吗?

You're expecting the change to be a metadata-only change, but it won't be.您期望更改是仅限元数据的更改,但事实并非如此。

You can test this by requesting the alter be done as an inplace change, and seeing the error when the request cannot be satisfied.您可以通过请求将更改作为就地更改完成并在无法满足请求时查看错误来测试这一点。

mysql> alter table tab_sample modify id bigint not null auto_increment, algorithm=inplace;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

InnoDB has a limited subset of types of ALTER TABLE that can be done as inplace or metadata-only changes. InnoDB 具有有限的 ALTER TABLE 类型子集,可以作为就地更改或仅元数据更改来完成。 See https://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.htmlhttps://dev.mysql.com/doc/refman/5.6/en/innodb-online-ddl-operations.html

The alter you are requesting probably counts as "Changing the column data type" even though you're not changing the type but only changing the AUTO_INCREMENT option.即使您没有更改类型而只更改 AUTO_INCREMENT 选项,您请求的更改也可能算作“更改列数据类型”。


I think MySQL must do a table-copy for the edge case when your id column contains NULL or 0. In that case, MySQL will generate a new auto-increment value and replace the NULL or 0.我认为当您的id列包含 NULL 或 0 时,MySQL 必须为边缘情况进行表复制。在这种情况下,MySQL 将生成一个新的自动增量值并替换 NULL 或 0。

mysql> insert into tab_sample (id) values (10),(20),(30),(0)

mysql> ALTER TABLE `tab_sample` MODIFY   id bigint(20) NOT NULL AUTO_INCREMENT;
Query OK, 4 rows affected (0.06 sec)

mysql> select * from tab_sample;
+----+-----------+
| id | something |
+----+-----------+
|  1 | NULL      |
| 10 | NULL      |
| 20 | NULL      |
| 30 | NULL      |
+----+-----------+

See my 0 got changed to a 1 by the auto-increment.看到我的 0 被自动增量更改为 1。

Other edge case: the column may not have been a unique key, so it may have contained many rows with 0 or NULL, and they all would be given new id's.其他边缘情况:该列可能不是唯一键,因此它可能包含许多带有 0 或 NULL 的行,并且它们都将被赋予新的 id。

mysql> create table tab_sample2 ( id bigint, key(id));
Query OK, 0 rows affected (0.04 sec)

mysql> insert into tab_sample2 values (10),(20),(30),(0),(0),(0),(NULL),(NULL),(NULL);
Query OK, 9 rows affected (0.02 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> alter table tab_sample2 modify column id bigint auto_increment;
Query OK, 9 rows affected (0.06 sec)
Records: 9  Duplicates: 0  Warnings: 0

mysql> select * from tab_sample2;
+----+
| id |
+----+
| 10 |
| 20 |
| 30 |
| 31 |
| 32 |
| 33 |
| 34 |
| 35 |
| 36 |
+----+

MySQL doesn't know how many rows in the table will need new id values. MySQL 不知道表中有多少行需要新的 id 值。 It could be every row in the table.它可以是表中的每一行。 So to be safe, it will just do a table-copy and fill in auto-inc values on as many rows as needed.因此,为了安全起见,它只会进行表复制并根据需要在尽可能多的行上填写 auto-inc 值。

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

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