对于批量插入,mybatis-plus提供了相应的API实现:
boolean saveBatch(Collection<T> entityList, int batchSize);
参数entityList为需要批量插入的数据的集合;参数batchSize为批处理大小,表示将传入的实体List分为每批batchSize个进行插入操作。不传参时batchSize默认1000,部分旧版本mp默认30。
测试:每次插入10000条数据入表,表字段4个 ,主键自增,数据库表和模型类及mapper、service、serviceImpl代码省略。
1、编写简单Controller类进行测试
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@RequestMapping("/batchTest")
@RestController
public class BatchDemoController {
@Autowired
private BatchDemoService batchDemoService;
@PostMapping("/t1")
public String test() {
//构造集合
List<Batch> lis = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Batch b = new Batch();
b.setAge(new Random().nextInt(100));
b.setName("user" + b.getAge());
b.setTel(1332546587);
lis.add(b);
}
//批量插入,记录时间
long one = System.currentTimeMillis();
boolean b = batchDemoService.saveBatch(lis, 2000);
long two = System.currentTimeMillis();
if (b) {
return "执行success," + "执行SQL总计用时:" + (two - one) / 1000.000 + "秒";
} else
return "fail";
}
}
2、修改MySQL的JDBC连接的url,测试批量插入数据效果,每种测试三次
测试配置1,不添加批处理参数
url: jdbc:mysql://127.0.0.1:3306/text1?characterEncoding=UTF-8&useSSL=false
测试配置2,添加批处理参数
url: jdbc:mysql://127.0.0.1:3306/text1?characterEncoding=UTF-8&useSSL=false&rewriteBatchedStatements=true
3、测试结果展示
测试配置1的插入用时:
执行success,执行SQL总计用时:8.653秒
执行success,执行SQL总计用时:8.429秒
执行success,执行SQL总计用时:8.542秒
测试配置2的插入用时:
执行success,执行SQL总计用时:0.483秒
执行success,执行SQL总计用时:0.347秒
执行success,执行SQL总计用时:0.366秒
结合上述测试结果,对比测试配置①,可知只有在开启了rewriteBatchedStatements=true参数后,批处理才能实现高性能的批量插入,拼接参数后的saveBatch()批量插入性能提升约95.3%。
下文为其他老哥的结论内容,仅作参考:
MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证MySQL5.1.13以上版本的驱动,才能实现高性能的批量插入。
MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,此时的批量插入实际上是单条插入,直接造成较低的性能。
只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL。(该参数默认为false)
这个选项对INSERT/DELETE/UPDATE增删改三类的批量操作都有效:
对delete和update,驱动所做的事就是把多条sql语句累积起来再一次性发出去;
而对于insert,驱动则会把多条sql语句合并重写成一条sql语句,然后再发出去。
官方文档说,这种insert写法可以提高性能(”This is considerably faster (many times faster in some cases) than using separate single-row INSERT statements”)