暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

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

原创 薛晓刚 2024-01-29
224

从前有些开发人员问我,如果在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位,则需要考虑会发生表重构的可能。

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

 编辑

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论