sql查询多一个字段 数据增加了几十倍是什么原因_Mysql Online DDL之VARCHAR字段扩容探索...

从mysql5.6开始以后的版本,支持Online DDL,这个功能是mysql梦寐以求的功能,要知道在mysql5.6以前的版本,做DDL变更,可是会锁表,业务无法做DML操作,只能查询,其中痛苦,只有经历过的同学才会知道。

20d81dff98da84411fbc9f9da4e60c39.png

本文只探索Mysql5.7版本的 Online DDL之VARCHAR字段扩容操作,以前在生产做VARCHAR字段扩容时,发现有时候扩容操作非常快,基本在秒级就返回了,有时候扩容,要好几十秒,甚至好几分钟才返回,当时以为是业务表数据量导致的,后来注意到2个数据量差不多的表,做VARCHAR字段扩容操作,执行时间相差好几十倍时,才发现原来不仅仅是数据量的原因。

下面就来验证一下,首先用sysbench模拟出一张10000000条记录的表,sysbench安装很简单,这里就不做介绍了,不会的同学,可以在网上搜索一下

mysql> select count(*) from sbtest1;+----------+| count(*) |+----------+| 10000000 |+----------+1 row in set (2.44 sec)

首先,修改字段c3从varchar(10)变成varchar(11),如下所示

mysql>  alter table sbtest1 modify c3 varchar(11) not null default '';Query OK, 0 rows affected (0.32 sec)Records: 0  Duplicates: 0  Warnings: 0

可以看到耗时320毫秒,秒级返回的。再看看将字段c3从varchar(11)变成varchar(100),如下所示

mysql>  alter table sbtest1 modify c3 varchar(100) not null default '';Query OK, 10000000 rows affected (9 min 41.85 sec)Records: 10000000  Duplicates: 0  Warnings: 0

为什么会这样呢,同一个表,从长度10到11,秒级返回,变成100时,执行时间竟然变成9分41秒,这时间也差的太多了。

7e3c1c978f1e02d18ea2031bd15df109.png

于是去看了一下官方文档,看看是什么原因,原来varchar的字段,如果所占用的字节小于256时,用一个字节记录占用字段长度,并且修改字段长度时,默认的算法是inplace,允许并发DML,此时只需要修改表的元数据信息,即可完成字段长度变更。

在这里需要注意,如果你的表的字符集是utf8,那么varchar(1)是占用3个字节长度,utf8mb4,那么varchar(1)是占用4个字节长度,也即是说当数据库字符集为uft8时,列定义少于85,数据库字符集为uft8mb4时,列定义少于63,字段长度扩容时,算法是inplace,此时只需要修改表的元数据信息,秒级完成字段扩容。

可是当字段占用字节数超过255时,mysql会采用两个字节记录占用字段长度,这个时候,页内头部存储信息发生改变了,就只能采取copy算法去做字段长度扩容了。

[mysql@localhost sbtest]$ du -sm *1       db.opt1       sbtest1.frm2944    sbtest1.ibd1       #sql-9212_6.frm2648    #sql-9212_6.ibd

采用copy算法,可以看到生成了一个临时表(#sql-9212_6.ibd),因为要将原来老表的所有数据全部拷贝到新表中,所以时间会非常长。

61d5e8924fc60276478cb20e18edfa0c.png

在这里再多说一句,Mysql Online DDL是如何做到并发DML的,原来在做DDL期间,mysql会记录所有在此表上所有的DML操作,并将日志写到一个内存区域里,这个内存区域大小由innodb_online_alter_log_max_size控制,其默认大小为128M,如果产生的日志超出该容量大小,则会抛出类似如下的异常提示:

Error:1799SQLSTATE:HY000(ER_INNODB_ONLINE_LOG_TOO_BIG)Message: Creating index 'idx_aaa' required more than 'innodb_online_alter_log_max_size' bytes of modification log. Please try again.

导致你的DDL语句执行失败,如果想继续执行DDL语句,则需要调整innodb_online_alter_log_max_size参数,比较繁忙的数据库,此参数建议调整为512M。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值