前言

由于项目是使用MyBatis-Plus开发的,用起来也确实比较方便,尤其是service层封装好的一些通用的增删改查方法,省去了不少sql语句的书写,但是在开发过程中,我也发现MyBatis-Plus的saveBatch批量插入方法针对MySQL数据库可能会出现效率贼低的情况,通过不断查询资料发现可以通过加rewriteBatchedStatements参数来解决(保证5.1.13以上版本)。

一、rewriteBatchedStatements参数介绍

MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL,另外这个选项对INSERT/UPDATE/DELETE都有效

如果你去看源码
在这里插入图片描述
会发现,默认的saveBatch方法,是通过for循环一条一条执行了 sqlSession.insert,下面的 consumer 执行的就是上面的 sqlSession.insert:
在这里插入图片描述
然后累计一定数量后,一批 flush。从这点来看,这个 saveBach 的性能肯定比直接一条一条 insert 快。
添加rewriteBatchedStatements=true这个参数后,会进入下面这个方法,对SQL 语句进行rewrite
在这里插入图片描述
在这里插入图片描述
对插入而言,所谓的 rewrite 其实就是将一批插入拼接成 insert into xxx values (a),(b),©…这样一条语句的形式然后执行,这样一来插入速度会大大提升。
下面通过一个例子来进行测试一下.

二、批量添加员工信息测试

1.普通saveBatch批量插入

我们循环1万次,把每个实例员工对象装到员工集合(List)中,然后调用Mybatis-Plus的saveBatch方法,传入List集合,实现批量员工的插入,然后我们在方法开始结束的地方,计算当前函数执行时长。

@PostMapping("/addBath")
@ResponseBody
public ApiResult<Employee> addBath(){
    long startTime = System.currentTimeMillis();
    List<Employee> list = new ArrayList<>();
    // 循环批量添加1万条员工数据
    for (int i = 0; i < 10000; i++) {
        Employee employee = new Employee();
        employee.setName("DT测试"+i);
        employee.setAge(20);
        employee.setSalary(9000D);
        employee.setDepartmentId(i);
        list.add(employee);
    }
    boolean batch = employeeService.saveBatch(list);
    if(batch){
        long endTime = System.currentTimeMillis();
        System.out.println("函数执行时间:" + (endTime - startTime) + "ms");
        return ApiResult.ok();
    }
    return ApiResult.fail();
}

在这里插入图片描述
为了测试的细致,我多点了几下这个方法,下面是每次记录的时长:

批量添加1万条员工数据,测试结果如下:

第一次:(2秒多)
在这里插入图片描述
第二次:(接近2秒)
在这里插入图片描述
第三次:(接近2秒)
在这里插入图片描述
差不多添加1万条数据在2秒左右,这个时候我们加大量10万条,再测试:
在这里插入图片描述
批量添加10万条员工数据,测试结果如下:

第一次:(19.341 秒)
在这里插入图片描述
第二次:(18.298 秒)
在这里插入图片描述

2.设置rewriteBatchedStatements=true批量插入

下面我们为数据库的连接加上rewriteBatchedStatements=true的属性,再测试批量加入的耗时。

rewriteBatchedStatements=true

在这里插入图片描述
批量添加1万条员工数据,测试结果如下:
在这里插入图片描述
对比默认插入:

1万条数据:2s -->>> 0.5s

批量添加10万条员工数据,测试结果如下:
在这里插入图片描述对比默认插入:

1万条数据:20s -->>> 5s

总结

所以,通过以上测试我们能发现,加了rewriteBatchedStatements的saveBatch要比默认的saveBatch快好几倍,如果你想验证rewriteBatchedStatements在你的系统里是否已经生效,记得要使用较大的batch,这样才能更明显的看出差距.

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐