mysql批量插入性能优化:executeBatch如何通过rewriteBatchedStatements参数逆袭

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: mysql批量插入性能优化:executeBatch如何通过rewriteBatchedStatements参数逆袭

前言


前面关于mybatis-plus的文章中提到过内置的批量插入方法saveBatch并不是真正的批量写入,而是通过executeBatch分批提交。所以我们通过sql注入器注入InsertBatchSomeColumn方法实现了insert的多值插入,提升了批量插入的性能。但其实还有更简单的优化方式,只通过添加一个参数,就能让采用executeBatch批量插入数据的性能实现逆袭。


这就是今天给大家介绍的rewriteBatchedStatements参数。


一、实战演示


项目工程依然采用之前mybatis-plus系列文章中的工厂。

这里我们通过在不添加rewriteBatchedStatements参数的前后采用executeBatch批量执行插入1万数据,并与InsertBatchSomeColumn方法进行对比。


1、单元测试

@Test
    public void testBatchInsert() {
        System.out.println("----- batch insert method test ------");
        long startTime = System.currentTimeMillis();
        List<User> list = new ArrayList<>();
        for (int i = 0; i < 10000; i++) {
            User user = new User();
            user.setName("test");
            user.setAge(13);
            user.setEmail("101@qq.com");
            list.add(user);
        }
        userService.saveBatch(list);
        System.out.println("耗时:" + (System.currentTimeMillis() - startTime));
    }


saveBatch方法默认情况下,每次提交1000条sql。

saveBatch方法的底层实现是通过executeBatch批量执行sql。

default boolean saveBatch(Collection<T> entityList) {
    return this.saveBatch(entityList, 1000);
}
public boolean saveBatch(Collection<T> entityList, int batchSize) {
     String sqlStatement = this.getSqlStatement(SqlMethod.INSERT_ONE);
     return this.executeBatch(entityList, batchSize, (sqlSession, entity) -> {
         sqlSession.insert(sqlStatement, entity);
     });
 }


2、不添加rewriteBatchedStatements参数

属性配置:

spring.datasource.url = jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
spring.datasource.username = root
spring.datasource.password = 123456


测试结果:

51.png

说明是一条insert语句插入一条记录。

50.png

插入10000条数据,耗时49646ms


3、添加rewriteBatchedStatements参数

在mysql的数据库连接参数中添加rewriteBatchedStatements=true

spring.datasource.url = jdbc:mysql://localhost:3306/seckill?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&rewriteBatchedStatements=true
spring.datasource.username = root
spring.datasource.password = 123456


执行结果:

49.png

添加rewriteBatchedStatements=true后,executeBatch批量提交到mysql的sql语句还是一条insert语句插入一条记录。

插入10000条数据耗时1289ms,批量插入的效率得到大幅提升。

48.png


4、采用InsertBatchSomeColumn方法

这里我们只需要将UserServiceImpl中采用InsertBatchSomeColumn重写的saveBatch方法的注释放开即可。

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;
    /**
     *
     * @param entityList
     * @param batchSize
     * @return
     */
    @Override
    @Transactional(rollbackFor = {Exception.class})
    public boolean saveBatch(Collection<User> entityList, int batchSize) {
        try {
            int size = entityList.size();
            int idxLimit = Math.min(batchSize, size);
            int i = 1;
            //保存单批提交的数据集合
            List<User> oneBatchList = new ArrayList<>();
            for(Iterator<User> var7 = entityList.iterator(); var7.hasNext(); ++i) {
                User element = var7.next();
                oneBatchList.add(element);
                if (i == idxLimit) {
                    userMapper.insertBatchSomeColumn(oneBatchList);
                    //每次提交后需要清空集合数据
                    oneBatchList.clear();
                    idxLimit = Math.min(idxLimit + batchSize, size);
                }
            }
        }catch (Exception e){
            log.error("saveBatch fail",e);
            return false;
        }
        return  true;
    }
}


执行单元测试:

可以看到,采用insertBatchSomeColumn方法进行的批量插入是采用了insert的多值插入,一条insert语句插入多条记录。这里每批插入1000条记录。

最终,插入10000条记录只话费了663ms


insertBatchSomeColumn方法由于底层并不是走的executeBatch批量提交sql,所以性能并不会受rewriteBatchedStatements参数的影响。

46.png

47.png


二、官方文档


Mysql官方文档:rewriteBatchedStatements

45.png

核心:

prepared statements for INSERT into multi-value inserts when executeBatch() is called


rewriteBatchedStatements选项默认是关闭的,3.1.13以后的mysql连接驱动都支持该配置。

如果开启该配置rewriteBatchedStatements=true,在调用 executeBatch() 批量执行 INSERT语句时,mysql内部会自动将批量提交的sql重写为insert多值插入再执行。


总结


本文主要介绍在采用executeBatch进行mysql批量数据插入时,通过在mysql连接信息中添加rewriteBatchedStatements=true使得执行效率大幅提升。

1、批量sql重写开关参数rewriteBatchedStatements默认是关闭的,mysql连接驱动器版本3.1.13以后支持该配置。

2、其底层原理是:将通过executeBatch方法批量提交到mysql服务端的sql重写为insert多值插入再执行。

3、通过测试发现,开启rewriteBatchedStatements后,采用executeBatch方法批量插入的性能已经接近InsertBatchSomeColumn真实insert多值批量写入。

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
存储 关系型数据库 MySQL
MySQL数据库进阶第三篇(MySQL性能优化)
MySQL数据库进阶第三篇(MySQL性能优化)
|
19天前
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
165 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
8天前
|
存储 关系型数据库 MySQL
mysql-性能优化(一)
mysql-性能优化(一)
|
17天前
|
关系型数据库 MySQL 数据处理
针对MySQL亿级数据的高效插入策略与性能优化技巧
在处理MySQL亿级数据的高效插入和性能优化时,以上提到的策略和技巧可以显著提升数据处理速度,减少系统负担,并保持数据的稳定性和一致性。正确实施这些策略需要深入理解MySQL的工作原理和业务需求,以便做出最适合的配置调整。
69 6
|
3天前
|
SQL 存储 关系型数据库
深入 MySQL 的执行计划与性能优化
深入 MySQL 的执行计划与性能优化
11 0
|
2月前
|
存储 关系型数据库 MySQL
"深入探索MySQL临时表:性能优化利器,数据处理的灵活之选"
【8月更文挑战第9天】MySQL临时表专为存储临时数据设计,自动创建与删除,仅在当前会话中存在,有助于性能优化。它分为本地临时表和全局临时表(通过特定逻辑模拟)。创建语法类似于普通表,但加TEMPORARY或TEMP关键字。适用于性能优化、数据预处理和复杂查询,需注意内存占用和事务支持问题。合理使用可大幅提升查询效率。
103 2
|
3月前
|
SQL 存储 数据库
MySQL设计规约问题之性能分析工具如Sql explain、show profile和mysqlsla在数据库性能优化中有什么作用
MySQL设计规约问题之性能分析工具如Sql explain、show profile和mysqlsla在数据库性能优化中有什么作用
|
3月前
|
分布式计算 关系型数据库 MySQL
MySQL超时参数优化与DataX高效数据同步实践
通过合理设置MySQL的超时参数,可以有效地提升数据库的稳定性和性能。而DataX作为一种高效的数据同步工具,可以帮助企业轻松实现不同数据源之间的数据迁移。无论是优化MySQL参数还是使用DataX进行数据同步,都需要根据具体的应用场景来进行细致的配置和测试,以达到最佳效果。
|
4月前
|
SQL 关系型数据库 MySQL
MySQL性能优化实战:从索引策略到查询优化
MySQL性能优化聚焦索引策略和查询优化。创建索引如`CREATE INDEX idx_user_id ON users(user_id)`可加速检索;复合索引考虑字段顺序,如`idx_name ON users(last_name, first_name)`。使用`EXPLAIN`分析查询效率,避免全表扫描和大量`OFFSET`。通过子查询优化分页,如LIMIT配合内部排序。定期审查和调整策略以提升响应速度和降低资源消耗。【6月更文挑战第22天】
606 2
|
3月前
|
存储 缓存 关系型数据库
Mysql/etc/my.cnf参数详解
以上只是 `/etc/my.cnf`中的部分参数,实际上,`/etc/my.cnf`中的参数非常多,可以根据具体的应用需求进行调整。
38 0
下一篇
无影云桌面