DDL工具测试对比
测试步骤
- 创建4张表,表结构如下:
CREATE TABLE if not exists users ( `rid` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `nid` bigint(20) DEFAULT NULL, `level` int(11) DEFAULT NULL, `vip` int(11) DEFAULT NULL, `vip_exp` int(11) DEFAULT NULL, `reg_channel` int(11) DEFAULT NULL, `guild_id` bigint(20) unsigned DEFAULT '0', `guild_open` tinyint(1) DEFAULT '0', `forbid_login_time` bigint(20) DEFAULT NULL, `forbid_talk_time` bigint(20) DEFAULT NULL, `ctime` bigint(20) DEFAULT NULL, `mtime` datetime(3) DEFAULT NULL, `last_offline_time` bigint(20) DEFAULT NULL, `friend_open` tinyint(1) DEFAULT '0', `user_data_str` mediumblob, `name` varchar(64) DEFAULT NULL, `db_fix_version` int(10) DEFAULT '0', PRIMARY KEY (`rid`), KEY `idx_users_99_nid` (`nid`), KEY `idx_users_99_level` (`level`), KEY `idx_users_99_ctime` (`ctime`), KEY `idx_users_99_mtime` (`mtime`), KEY `idx_users_99_last_offline_time` (`last_offline_time`), KEY `idx_users_99_name` (`name`) ) ENGINE=InnoDB AUTO_INCREMENT=4393751571200 DEFAULT CHARSET=utf8mb4;
- 分别给每张表插入3000万行数据。
- 使用MySQL原生copy算法在表1中添加一列,并在执行过程中建立新会话执行select,update,insert操作10万条数据。
- 使用MySQL原生inplace算法在表2添加一列,并在执行过程中建立新会话执行select,update,insert操作10万条数据。
- 使用gh-ost工具在表3中添加一列,并在执行过程中建立新会话执行select,update,insert操作10万条数据。
- 记录DDL和DML语句执行时间。
执行操作 |
MySQL Copy |
MySQL Inplace |
gh-ost |
---|---|---|---|
增加一列 |
1294.29 |
755.52 |
1876.79 |
select |
1.35 |
1.29 |
1.29 |
update |
1266.78 |
0.19 |
0.11 |
insert |
1296.19 |
7.47 |
4.49 |
测试结果
- MySQL原生copy算法:update、insert执行会阻塞,select语句可以正常执行。
- MySQL原生inplace算法:不会长时间阻塞DML语句,且对大表添加一列耗时最短。
- gh-ost工具:几乎不阻塞DML语句,DDL添加一列耗时比MySQL原生的两种算法时间长。
算法使用建议
采用Inplace算法进行DDL操作时阻塞DML的时间很短,对主从时延无严格要求的客户,推荐直接使用社区已有能力快速完成表结构变更。对主从复制延迟容忍较低的业务,推荐使用gh-ost工具来完成DDL操作。使用了MySQL 8.0.12版本及以上的用户,当满足instant算法条件时,可指定使用instant来减少DDL操作对业务的影响。