MySQL 8.0.31并行构建索引特性管窥

网友投稿 954 2023-04-23

MySQL 8.0.31并行构建索引特性管窥

MySQL 8.0.31并行构建索引特性管窥

MySQL 8.0.31于2022.10.11发布了,比我预计的日期早了一周,先赞一个。

看了下 release notes ,新增的东西不算多,感觉MySQL官方对8.0版本已经进入维稳的后半段了,英文不好的同学可以戳此查看 徐轶韬老师针对8.0.31做的快速解读​。另外,根据 徐老师的最新推文,也了解到MySQL针对8.0版本延长了标准支持(Premier Support)时长,从原来的2023.4延长到了2025.4,不过延伸支持(Extended Support)的期限没有改变,仍然是2026.4。

本次发布的8.0.31新特性中,我注意到有一句不太起眼的说明:

InnoDB: InnoDB now supports parallel index builds, which improves index build performance. In particular, loading sorted index entries into a B-tree is now multithreaded. Previously, this action was performed by a single thread.

只有这么简单的一句,没更多扩展解释说明。简言之,就是支持并行构建索引,提升索引构建性能。

并行构建索引测试

还是直接做个测试看看吧。

利用sysbench构建一个有400万行记录的测试表,只有一个主键索引时,表空间物理文件大小为1044381696 Bytes,添加完测试索引后,表空间物理文件大小涨到1434451968 Bytes,增加了37.35%。

mysql> CREATE TABLE `t1` ( `id` int NOT NULL AUTO_INCREMENT, `k` int NOT NULL DEFAULT '0', `c` char(120) NOT NULL DEFAULT '', `pad` char(60) NOT NULL DEFAULT '', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;mysql> select count(*) from t1;+----------+| count(*) |+----------+| 4000000 |+----------+1 row in set (0.35 sec)

接下来,我分别针对GreatSQL 8.0.25-16、MySQL 8.0.31做重建索引的测试,每个数据库跑10次,计算其每次耗时,去掉最大最小偏差值,取剩下的8次求平均值。都先采用默认设置,最后得到的结果如下表:

GreatSQL 8.0.25-16

MySQL 8.0.31

平均耗时(秒)

42.529

31.202

可以看到,使用MySQL 8.0.31重建索引的效率提升了约36%,还是相当可观的,如果是线上环境有大表可能提升效果更可观。

进一步提高索引构建效率

从MySQL 8.0.27开始,新增选项 innodb_ddl_buffer_size​,其作用是作为Online DDL期间的buffer(代替 innodb_sort_buffer_size​ 的作用),用于提升辅助索引构建的效率。这是Online DDL期间总共可以使用的buffer,如果有多个DDL并发线程,则每个线程最大可用的buffer是 innodb_ddl_buffer_size / innodb_ddl_threads。其默认值是1MB,明显太低了,我在本案中尝试修改成64M、128MB、256MB、512MB、1GB,再对比测试其效果。

选项 innodb_ddl_threads 也是从8.0.27开始新增的,用于定义Online DDL的并发线程数,默认值是4,可根据实际情况调整。

模式

平均耗时(秒)

提升比例

GreatSQL 8.0.25-16默认值

42.529

MySQL 8.0.31默认值

31.202

36.30%

64M

23.448

81.38%

64M + 8thds

21.202

100.59%

128M

22.856

86.07%

128M + 8thds

21.456

98.21%

256M

22.047

92.90%

256M + 8thds

21.266

99.99%

512M

22.885

85.84%

512M + 8thds

23.227

83.10%

1G

25.239

68.51%

1G + 8thds

24.486

73.69%

上面表格中,64M表示innodb_ddl_buffer_size=64M​,8thds表示innodb_ddl_threads=8,其他以此类推。

可以看到,当 innodb_ddl_buffer_size​ 及 innodb_ddl_threads 值适当加大后,重建索引的耗时明显降低,最好的情况下,索引重建效率可提升1倍;不过其效率也并不随着值增加而线性提高。看起来,线上生产环境需要根据实测情况进行调整。

循环自动测试的shell脚本也顺便分享出来:

#!/bin/bashdb=MySQL# 设置不同的ddl buffer sizefor dbp in 64 128 256 512 1024doexec 3>&1 4>&2 1>> parallel-index-build-${dbp}m.log 2>&1# 循环10次for i in $(seq 1 10)do echo "$db cycle $i" mysql -N -s -q -f -S./$db/mysql.sock -e "set global innodb_ddl_buffer_size=$dbp*1024*1024" test > /dev/null 2>&1 mysql -f -S./$db/mysql.sock -e "select @@global.innodb_ddl_buffer_size" test mysql -N -s -q -f -S./$db/mysql.sock -e "alter table t1 drop index i1, drop index i2;" test > /dev/null 2>&1 sleep 5 time mysql -N -s -q -f -S./$db/mysql.sock -e "alter table t1 add index i1(k), add index i2(pad);" test echo "" echo "" sleep 5done# 调整ddl threads = 8exec 3>&1 4>&2 1>> parallel-index-build-${dbp}m-8th.log 2>&1for i in $(seq 1 10)do echo "$db cycle $i" mysql -N -s -q -f -S./$db/mysql.sock -e "set global innodb_ddl_threads=8" test > /dev/null 2>&1 mysql -f -S./$db/mysql.sock -e "select @@global.innodb_ddl_threads" test mysql -N -s -q -f -S./$db/mysql.sock -e "alter table t1 drop index i1, drop index i2;" test > /dev/null 2>&1 sleep 5 time mysql -N -s -q -f -S./$db/mysql.sock -e "alter table t1 add index i1(k), add index i2(pad);" test echo "" echo "" sleep 5done# 恢复 ddl threads=4 mysql -N -s -q -f -S./$db/mysql.sock -e "set global innodb_ddl_threads=4" test > /dev/null 2>&1 mysql -f -S./$db/mysql.sock -e "select @@global.innodb_ddl_threads" testdone

并行构建索引的限制

最后,再来看下并行构建索引新特性都有哪些限制:

不支持虚拟列(virtual columns)。

不支持全文索引(full-text index)。

不支持空间索引(spatial index )。

期待MySQL 8.0未来新版本中继续推出更多实用的新特性吧。

延伸阅读

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:CMU 15445 学习之Hash Table
下一篇:SQL优化实战:如何通过缓存给MySQL查询进行流量削峰?
相关文章