最近在研究如何给MySQL数据库的大表在线添加索引,查询了下资料,MySQL提供了online ddl功能,可以不锁表的执行DDL操作,网络上有些文章有讲解,但是都没有做基准测试。今天正好有空,就做个测试看看online DDL的实际效果。
online DDL简介
online DDL功能为表结构的更改和并发DML提供支持。此功能的优点包括:
- 几乎不影响线上DML语句的效率。
- 使用LOCK子句在DDL操作期间调整性能和并发之间的平衡。
- 与表复制方法相比,磁盘空间使用量和I / O开销更少。
参数介绍[引用1]:
ALGORITHM:
- DEFAULT:默认方式,在 MySQL 8.0中,如果未显示指定 ALGORITHM,那么会优先选择 INSTANT 算法,如果不行再使用 INPLACE 算法,如果不支持 INPLACE 算法则使用 COPY 的方式完成。(8.0以上版本)
- INSTANT:添加列时立即返回。但是不能是虚拟列。这个原理很简单,对于新建一列,表所有原有数据并不是立刻发生变化,只是在表字典里面记录下这个列和默认值,对于默认的 Dynamic 行格式(其实就是 Compressed 的变种),如果更新了这一列则原有数据标记为删除在末尾追加更新后的记录。这样做就是没有提前预留出列空间,之后更新可能经常会发生行记录空间变动。但是对于大多数业务,都是最近的时间的记录才会修改,所以问题不大。(8.0以上版本)
- INPLACE:在原表上直接进行修改,不会拷贝临时表,可以逐条记录修改,不会产生大量的 undolog 以及 redolog,不会占用很多 buffer。可以避免重建表带来的IO和CPU消耗,保证期间依然良好的性能和并发。
- COPY:拷贝到临时新表上进行修改。由于记录拷贝,会产生大量的 undolog 以及 redolog,并占用很多 buffer,对业务性能有影响。
LOCK:
- DEFAULT:和 ALGORITHM 的 DEFAULT 类似(8.0以上版本)
- NONE:无锁,允许并发读取和更新表
- SHARED:共享锁,允许读取不允许更新
- EXCLUSIVE:不允许读取和更新
官方文档
基础配置
服务器配置:
thinkPad笔记本
CPU:i3五代 2.00GHz 4核
内存:8G
MySQL:5.6
数据准备
单表20个字段,ID主键索引之外添加三个非主键索引且其中一个为唯一索引。
起始准备数据1400W条,数据总量约600M。
DDL
为数据表添加一列默认为null的varchar类型的字段,长度为255。
- ALGORITHM=INPLACE
- LOCK=NONE
测试过程即结果分析
仅执行online DDL
不对表进行CURD的任何操作,仅执行online DDL,最终的执行结果为531.4s。
执行读取操作的同时执行online DDL
- 开启10个线程,每个线程以10次/秒的速率访问数据库,通过ID作为查询条件做select操作。
- 同时执行online DDL语句。
- 在执行online DDL前,数据库读取操作每个耗时在0.01秒上下。
- 执行online DDL过程中,开始阶段数据库读取操作每个耗时增加到0.1秒上下,此过程持续约30秒时间,随后稳定在0.01秒上下,与未执行online DDL之前一致。
执行读取和修改操作的同时执行online DDL
- 开启20个线程,其中10个线程中的每个线程以10次/秒的速率访问数据库,通过ID作为查询条件做select操作;另外10个线程中的每个线程以10次/秒的速率先通过ID查询数据,再以ID作为条件执行update操作。
- 同时执行online DDL语句。
- 在执行online DDL前,数据库读取操作每个耗时在0.01秒上下,读取加修改操作每个耗时在0.03秒上下。
- 执行online DDL过程中,开始阶段读取操作耗时增长到0.1秒上下,读取加修改操作增长到0.2~0.3秒之间,持续时间约30秒左右,随后读取操作耗时回落并稳定在0.01秒上下,读取加修改操作耗时稳定在0.03秒上下。
执行读取、读取加修改、插入操作是执行online DDL
- 开启30个线程,其中10个线程中的每个线程以10次/秒的速率访问数据库,通过ID作为查询条件做select操作;另外10个线程中的每个线程以10次/秒的速率先通过ID查询数据,再以ID作为条件执行update操作;最后10个线程中的每个线程以10次/秒的速率执行insert操作。
- 同时执行online DDL语句。
- 在执行online DDL前,读取操作的单个耗时在0.01秒上下,偶发延迟到0.03~0.05秒;读取加修改操作的单个耗时在0.03秒上下,偶发延迟到0.05秒;写入操作的单个耗时在0.2秒上下,且较为稳定。
- 在执行online DDL过程中,开始阶段读取耗时增加到0.1秒以上,读取加修改操作的耗时增加到0.3秒上下,写入操作的耗时增加到0.4秒上下,约20秒后三种操作的耗时回落至操作前水平,但写入操作偶发延迟最长达8秒。
结论
online DDL确实将MySQL线上大表的修改操作实现为一种可能,且对读取和修改操作无太大影响,但对于写入操作会有偶发性的严重影响。
所以使用前最好根据自身的服务状况,在预发环境做充分测试后再到生产环境执行。
引用鸣谢:
- 张哈希 https://juejin.cn/post/6919646430567071751?utm_source=gold_browser_extension (MySQL 大表添加一列):online DDL简介-参数介绍
- MySQL官方文档 https://dev.mysql.com/doc/
来源:oschina
链接:https://my.oschina.net/cuttese/blog/4922388