MySQL 8.0 Online DDL快速加列的相关总结


Posted in MySQL onJune 02, 2021

问题描述

前几天同事问了我一个问题:业务A从MySQL迁移到MongoDB的原因是什么?

说实话,这个问题还真不好回答,为什么要迁移,一定是遇到了某种瓶颈,可能是数据量也可能是数据类型等,于是我咨询了一下业务,最终得到了答案:这个业务中的某些表,要频繁的加字段。mongodb中加字段的成本几乎没有,而MySQL低版本中加字段的成本还是挺高的。

那么常用的MySQL添加字段的方法有哪些呢?这里我简单列举一下:

1、percona的pt-osc工具

2、github开源项目gh-ost工具

3、MySQL原生Online DDL

MySQL Online DDL加列的历史方法

01 Copy方法

MySQL5.5版本及之前的加列方法:Copy

它的执行示意图如下:

MySQL 8.0 Online DDL快速加列的相关总结

我们有一个原表A,只包含1个字段,它包含1、2、4、6这几条记录,当我们使用Copy算法加列时:

1、创建了一个新的表tmp-A,新表包含2个字段,

2、然后我们把表A的数据全部逐行拷贝到tmp-A这个新表里面,

3、然后用tmp-A表和A表做个交换,

    这样,我们的新表就包含2个字段了。同时需要注意,新表中的数据记录比原表更加紧凑了。原表中可能由于删除了3和5两条记录,使得表中间留下了空洞,或者叫空间碎片。

    可以看到,Copy算法需要拷贝一遍数据,需要额外的存储空间来存储tmp-A这个临时表。另外,在拷贝数据的过程中,表A的写入操作会丢失,也就是说,表A在alter table的过程中不能有数据更新。这可能是一个致命的缺点。

02 Inplace方法

MySQL5.6版本开始引入Online DDL,这个功能使得上面的过程变成了下面这样:

MySQL 8.0 Online DDL快速加列的相关总结

 它的过程和上面的Copy算法有些不同:

1、Online DDL过程中,从表A提取B+树,并存储到一个中间文件tmp-file,而不是中间表tmp-A

2、步骤1执行过程中,对表A的写入,都会记录到row log中

3、步骤1执行完毕后,对tmp-file应用所有的row log,得到一个与表A数据相同的数据文件

4、利用数据文件tmp-file替换表A的数据文件即可。

    这个过程中,由于row log的存在,使得在整个该表过程中,表A是可以进行增删改查的操作的,因为这些操作不会丢失。这也就是为什么把这个过程叫做Online DDL的原因。

    另外,这里需要解释下,Copy算法中生成的tmp-A临时表是在Server层面创建的,而上述Online DDL操作中的tmp-file是在插件式存储引擎Innodb内部生成的,我们把这种在Innodb内部完成的变更操作,称之为Inplace(中文表示原地),也就是不需要将数据挪动到"server层的临时表"。

MySQL8.0.12 引入的Instant方法

    MySQL8.0.12版本引入了Instant的方法,它让加列变得更加简单。instant算法添加列时不再需要 rebuild 整个表,只需要在表的 metadata 中记录新增列的基本信息即可。

    我们来看它的优势,首先我们创建一个表t1,并插入26w条数据,然后分别添加数据列col_1,col_2,col_3,并显示指定加列的算法为copy、inplace、和instant,结果如下:

[test] 23:42:45> select count(1) from t1;
 +----------+
 | count(1) |
 +----------+
 |   262144 |
 +----------+
 1 row in set (0.06 sec)
 
方案一:copy
[test] 23:43:29> alter table t1 add col_1 int,algorithm=copy;  
Query OK, 262144 rows affected (1.48 sec)
Records: 262144  Duplicates: 0  Warnings: 0

方案二:inplace
[test] 23:43:46> alter table t1 add col_2 int,algorithm=inplace; 
Query OK, 0 rows affected (0.58 sec)
Records: 0  Duplicates: 0  Warnings: 0

方案三:instant
[test] 23:44:08> alter table t1 add col_3 int,algorithm=instant; 
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

m5480:mysqlha_common@10.41.28.124 [test] 23:44:14> show create table t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `age` int DEFAULT NULL,
  `score` int DEFAULT NULL,
  `col_1` int DEFAULT NULL,
  `col_2` int DEFAULT NULL,
  `col_3` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_sco` (`score`)
) ENGINE=InnoDB AUTO_INCREMENT=458730 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
1 row in set (0.01 sec)

   从结果不难看出,执行时间上:

copy> inplace > instant

与此同时,copy算法的受影响行数是全部表,而inplace和instant的算法影响的行数都是0,说明他们是Online DDL操作。 

    最后,我们还可以通过下面的方法查看instant列的信息:

[test] 23:53:01> SELECT * FROM information_schema.innodb_tables where name like 'test/t1'\G
 *************************** 1. row ***************************
      TABLE_ID: 1079
          NAME: test/t1
          FLAG: 33
        N_COLS: 10
         SPACE: 22
    ROW_FORMAT: Dynamic
 ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single
 INSTANT_COLS: 6
1 row in set (0.00 sec)

    可以看到,test.t1这个表的instant列序号是6,代表它是这个表的第7个列(列编号从0开始)。

    当然,instant算法不支持删除普通列、无法设置列的顺序、还有一些其他的限制,详情可以查看官方文档:https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html

    但这些限制并不影响它成为一个优秀的DDL功能。 相信通过MySQL版本的不断迭代,在后面的版本中,有更多的变更操作可以用到instant这种高效的算法。

以上就是MySQL 8.0 Online DDL快速加列的相关总结的详细内容,更多关于MySQL DDL快速加列的资料请关注三水点靠木其它相关文章!

MySQL 相关文章推荐
MySQL分库分表与分区的入门指南
Apr 22 MySQL
Mysql实现主从配置和多主多从配置
Jun 02 MySQL
新手入门Mysql--sql执行过程
Jun 20 MySQL
MySQL一些常用高级SQL语句
Jul 03 MySQL
分享MySQL常用 内核 Debug 几种常见方法
Mar 17 MySQL
如何创建一个创建MySQL数据库中的datetime类型
Mar 21 MySQL
mysql使用 not int 子查询隐含陷阱
Apr 12 MySQL
深入理解mysql事务隔离级别和存储引擎
Apr 12 MySQL
mysql 获取相邻数据项
May 11 MySQL
MySQL数据库安装方法与图形化管理工具介绍
May 30 MySQL
Mysql中@和@@符号的详细使用指南
Jun 05 MySQL
MySQL索引失效十种场景与优化方案
May 08 MySQL
MySQL 常见存储引擎的优劣
Jun 02 #MySQL
Mysql文件存储图文详解
一文读懂navicat for mysql基础知识
Mysql数据库索引面试题(程序员基础技能)
MySQL CHAR和VARCHAR该如何选择
May 31 #MySQL
带你学习MySQL执行计划
May 31 #MySQL
MySQL完整性约束的定义与实例教程
You might like
shopex主机报错误请求解决方案(No such file or directory)
2011/12/27 PHP
php设计模式之简单工厂模式详解
2014/09/04 PHP
PHP操作MySQL的mysql_fetch_* 函数的常见用法教程
2015/12/25 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
2016/10/08 PHP
jquery的颜色选择插件实例代码
2008/10/02 Javascript
jquery 模式对话框终极版实现代码
2009/09/28 Javascript
Dojo 学习笔记入门篇 First Dojo Example
2009/11/15 Javascript
javascript showModalDialog 多层模态窗口实现页面提交及刷新的代码
2009/11/28 Javascript
一个收集图片的bookmarlet(js 刷新页面中的图片)
2010/05/27 Javascript
Javascript操作cookie的函数代码
2012/10/03 Javascript
js自动查找select下拉的菜单并选择(示例代码)
2014/02/26 Javascript
Jquery中的$.each获取各种返回类型数据的使用方法
2015/05/03 Javascript
JavaScript实现级联菜单的方法
2015/06/29 Javascript
基于ajax实现文件上传并显示进度条
2015/08/03 Javascript
理解javascript定时器中的setTimeout与setInterval
2016/02/23 Javascript
第二章之Bootstrap 页面排版样式
2016/04/25 Javascript
js和C# 时间日期格式转换的简单实例
2016/05/28 Javascript
Javascript中apply、call、bind的巧妙使用
2016/08/18 Javascript
JS关闭窗口时产生的事件及用法示例
2016/08/20 Javascript
微信小程序 wx.login解密出现乱码的问题解决办法
2017/03/10 Javascript
基于Vue实现tab栏切换内容不断实时刷新数据功能
2017/04/13 Javascript
微信JSAPI Ticket接口签名详解
2020/06/28 Javascript
微信小程序实现根据字母选择城市功能
2017/08/16 Javascript
js封装成插件_Canvas统计图插件编写实例
2017/09/12 Javascript
Python的组合模式与责任链模式编程示例
2016/02/02 Python
numpy判断数值类型、过滤出数值型数据的方法
2018/06/09 Python
详解Python计算机视觉 图像扭曲(仿射扭曲)
2019/03/27 Python
Django页面数据的缓存与使用的具体方法
2019/04/23 Python
python3将变量输入的简单实例
2020/08/19 Python
ECCO爱步美国官网:来自丹麦的鞋履品牌
2016/11/23 全球购物
StubHub美国:购买或出售您的门票
2019/07/09 全球购物
英国买鞋网站:Charles Clinkard
2019/11/14 全球购物
编码转换,怎样实现将GB2312编码的字符串转换为ISO-8859-1编码的字符串
2014/01/07 面试题
《周恩来的四个昼夜》观后思想汇报范文两篇
2014/09/10 职场文书
Python的flask接收前台的ajax的post数据和get数据的方法
2021/04/12 Python
Nginx虚拟主机的配置步骤过程全解
2022/03/31 Servers