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

MySQL online ddl扩展字段长度

IT那活儿 2022-12-22
1700

点击上方“IT那活儿”公众号,关注后了解更多内容,不管IT什么活儿,干就完了!!!


问 题

从MySQL5.5开始支持online ddl,5.6版本更加完善,一直到MySQL8.0版本,支持了更多alter table语句通过online ddl快速的执行,在执行效率、降低锁表时间以及IO消耗上有了很大的提升。

在日常运维MySQL时,ddl执行的最多的大概就是扩展varchar字段长度的情况,但是面对一定数据量的表,在执行时间上有时很快,有时执行起来很慢,这是什么原因?


测 试

2.1 创建表t1
表字符集为utf8mb4。
插入一些测试数据:
2.2 执行ddl命令
首先,name字段长度由30扩展至50。
再把name字段长度由50扩展至90。
可以看到两次ddl的执行时间差异很大, 造成差异的原因是什么呢?

通过MySQL官方文档得知,这跟varchar的字段所占用的字节数有关。

  • 当占用字节数为0-255字节时(注意是字节,不是字符),需要用一个字节记录字段的长度;
  • 当占用256及以上的字节时,需要用两个字节记录字段的长度;
  • 添加字段长度时,如果添加前后长度都在0-255范围内,或者大于等于256范围内,可以通过inplace的算法进行online ddl,如果是从0-255范围跨到大于等于256 ,就不支持online ddl,只能通过copy的算法进行ddl,所以执行较慢。MySQL会自动根据是否支持online ddl自动处理,所以才会出现扩展varchar字段长度执行有时很快,有时很慢的情况。
通过上面的例子分析,varchar(30) 占用了30个字符,字符集为utf8mb4每个字符4个字节,共占用120个字节,varchar(50) 占用了200个字节,而varchar(90)占用了360个字节,varchar(30)到varchar(50)不涉及跨字节范围,而从varchar(50)到varchar(90)则涉及到跨字节范围,所以后者不能通过online ddl执行语句,只能通过原始的方式去copy表执行,速度较慢。
2.3 验证结论
通过显示指定inplace的方式,更加明显的看出,当涉及到跨字节范围时,MySQL会报错提示使用copy的方式执行alter table语句。通过使用copy的方式跨话字节范围后,再次指定inplace 的方式,又可以进行online ddl了。
测试结论:
  • 在创建表时,如果字段的字节长度不会超过256字节,那么建议varchar的字节长度创建时小于256字节;
  • 如果字符串的长度超过200字节,那么varchar的字节长度建议超过256字节。
依据本例,varchar(30)为占用120字节,如果确定不会超过256字节,可以根据实际需求创建小于等于varchar(63);如果预估数据可能会超过256字节,就不要创建低于varchar(64)的,这样方便以后字段扩展进行使用online ddl。
当然,不建议为了方便online ddl操作,将所有的字段长度都超过256字节,因为MySQL在加载内存临时表的时候,会将字段定义的所有的长度加载到内存中,而不是实际的长度,同样又会造成资源消耗。



本文作者:吴 昊(上海新炬中北团队)

本文来源:“IT那活儿”公众号

文章转载自IT那活儿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论