即使在MySQL8上也不是所有DDL都是秒过的

从前有些开发人员问我,如果在MySQL的一个大表上加字段怎么办?我一般都让他们尽可能停应用去做。直到MySQL升级到8以后这个问题得到了大大的缓解。

MySQL8的特性借鉴了Oracle 11G的设计,将表结构放在数据字典上管理。使得可以快速增加字段。但是有些场景上我还是遇到过盲点。因为有时候字段扩长度,我觉得很慢但是相关DBA告诉我很快。有时候我觉得应该很快,但是相关DBA告诉我很慢。

后来我研究了一下,发现这个和字段的长度有关。

这里可以复现一下,构造了一个1000万的表。

mysql> select count(*) from thousand;

+----------+

| count(*) |

+----------+

| 10000000 |

+----------+

1 row in set (2.55 sec)

下面是表结构。

mysql> desc thousand;

+-------+-------------+------+-----+---------+-------+

| Field | Type        | Null | Key | Default | Extra |

+-------+-------------+------+-----+---------+-------+

| id    | int         | YES  |     | NULL    |       |

| a     | int         | YES  |     | NULL    |       |

| name  | varchar(10) | YES  |     | NULL    |       |

| time  | datetime(6) | YES  |     | NULL    |       |

+-------+-------------+------+-----+---------+-------+

4 rows in set (0.08 sec)

给这个表增加一个字段。

mysql> alter table thousand add address varchar(100);

Query OK, 0 rows affected (0.15 sec)

Records: 0  Duplicates: 0  Warnings: 0

可以看到0.1秒完成。这就是效果

mysql> alter table thousand add  QQ varchar(10)   default '0';

Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

新加字典带有默认值,可以看到30毫秒完成。这也是效果。

在Oracle11G的时候快速增加字段要求非空且要有默认值。如果仅有一个是不可以的。在MySQL8中可以看到没有非空,也没有默认值也是可以快速加字段的。

当然如果增加了,更加没有问题,可以快速增加字段。

mysql> alter table thousand add status  varchar(20)   default '0'  not null;

Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

那么来到今天的重点。把name字段从10扩大到70。看到花了将近4分钟。可见没有快速DDL的效果,这个等于重建了表。所以1000万数据花了4分钟。

mysql> alter table thousand modify name varchar(70);

Query OK, 10000000 rows affected (3 min 53.94 sec)

Records: 10000000  Duplicates: 0  Warnings: 0

把name字段从70扩大到270。

mysql> alter table thousand modify name varchar(270);

Query OK, 0 rows affected (0.02 sec)

Records: 0  Duplicates: 0  Warnings: 0

依然可以看到是20毫秒完成。

这里涉及到的问题就是,数据字典存储64位长度以下的和存储64位以上是不一样的。

从下面的实验复现一下。只要超过64位就是重建。换句话说小于64位的长度在这个区间内从小到大扩大是可以快速DDL的。大于64位的,从小小到大扩大也是可以快速DDL的。

mysql> alter table thousand add  tel varchar(20);

Query OK, 0 rows affected (0.26 sec)

Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table thousand modify  tel varchar(60);

Query OK, 0 rows affected (0.03 sec)

Records: 0  Duplicates: 0  Warnings: 0

mysql> alter table thousand modify  tel varchar(65);

Query OK, 10000000 rows affected (3 min 45.94 sec)

Records: 10000000  Duplicates: 0  Warnings: 0

mysql> alter table thousand modify  tel varchar(165);

Query OK, 0 rows affected (0.02 sec)

Records: 0  Duplicates: 0  Warnings: 0

但是就是主要如果从小于64扩大到超过64位,则需要考虑会发生表重构的可能。

当然缩小也是一样的会发生表重构的情况。

即使在MySQL8上也不是所有DDL都是秒过的_第1张图片

你可能感兴趣的:(数据库)