首页 > 其他分享 >Mybatis Plus 批量插入方法效率低问题优化方案 BatchExcutor

Mybatis Plus 批量插入方法效率低问题优化方案 BatchExcutor

时间:2023-06-21 15:35:31浏览次数:49  
标签:BatchExcutor tempEntityList 批量 插入方法 拼接 Plus result sql

1、问题描述

项目用的是Mybatis Plus框架操作数据库,在使用batchSave批量插入方法的时候发现效率极低,插入2w数据花了6分钟,太恐怖了。

看了源码发现,项目的批量插入方法调用的是Mybatis Plus的BatchExcutor,用这个本意是将多次更新sql语句集合为一条更新语句,复用同一个sql连接更新数据。但是打印sql语句发现,实际上仍然是一条一条插入的,只不过是复用同一个prepareStatement而已。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eYdXHEWB-1643113459225)(resource/image-20220124202735365.png)]

2、问题解决

方案一:之所以没有按照预期的拼接sql为一条是因为我们需要在连接数据库的时候设置参数 rewriteBatchedStatements

url: jdbc:mysql://${datasource.host}/${datasource.name}??rewriteBatchedStatements=true

方案二:配置解决的方式太麻烦,在微服务情况下又要改很多地方,所以我采用了第二种方案也是mybatis plus 提供的sql注入器

  • 继承框架提供的DefaultSqlInjector,实现自己的sql注入器
@Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new InsertBatchSomeColumn());  // 加入批量插入方法
        return methodList;
    }
  • InsertBatchSomeColumn 也是框架提供的批量插入方法,一句话来讲就是将我们的多条插入sql拼接成一条sql,这里就不插代码了,当然你也可以自己写一个方法继承AbstractMethod
  • 继承BaseMaper,加上sql注入的方法名接口即可使用
public interface InjectionMapper<T> extends BaseMapper<T> {

    Integer insertBatchSomeColumn(Collection<T> entityList);

    int batchSize = 1000;  // 应为mysql对于太长的sql语句是有限制的,所以我这里设置每1000条批量插入拼接sql

    default Integer batchInsert(Collection<T> entityList) {

        int result = 0;
        Collection<T> tempEntityList = new ArrayList<>();
        int i = 0;
        for (T entity : entityList) {
            tempEntityList.add(entity);
            if (i > 0 && (i % batchSize == 0)) {
                result += insertBatchSomeColumn(tempEntityList);
                tempEntityList.clear();
            }
            i++;
        }

        if (ValidateUtil.isNotEmpty(tempEntityList)) {
            result += insertBatchSomeColumn(tempEntityList);
        }
        return result;
    }

}

3、总结

其实两种方法底层都是将sql语句拼接起来,只不过一个是我们手动拼接,一个是mysql帮我们拼接

其实还有一种方式就是在xml中写动态sql,foreach标签拼接,但是太麻烦了不是。而且也是拼接sql的方式

我看网上对于这种方法遇到过一个问题就是主键id自增出错的问题,但是我的id是自己设置的所以没有问题,在这里提个醒

上图是我修改后,插入效率的提升,可以说是指数倍提升吧,有用的话点个赞哦。

标签:BatchExcutor,tempEntityList,批量,插入方法,拼接,Plus,result,sql
From: https://blog.51cto.com/u_16167766/6528827

相关文章

  • Vue3 element-Plus el-tree 权限树 传值给后端及回显问题
    内容:权限在新增人员时候选择传给后端并且编辑回显坑:1.传给后端的权限数组需要传父级id例如:一级目录下有二级目录和2-2目录,选了2-2目录,需要把一级目录的id也给后端2.回显的时候后端会把权限数组id都给你(包括一级目录),如果直接回显的话会默认一级下所有目录都选中 代......
  • Docker配置SpringBoot+ShardingJDBC+MybatisPlus项目实现分库分表与读写分离
    Docker配置SpringBoot+ShardingJDBC+MybatisPlus项目实现分库分表与读写分离 分类于 实战例子本文ShardingJDBC相关知识主要参考自ShardingJDBC官方文档,更多的用法建议到官网文档查看。前言传统的业务系统都是将数据集中存储至单一数据节点的解决方案,如今随着互联网数据......
  • C++ primer plus学习之第二章
    1.引用:intival=1024;int&refval=ival;//正确,refval时ival的别名int&re;//错误,引用必须被初始化int&ii=42;//错误:不能为非常量引用绑定字面值constint&ii=42;//正确:可以为常量引用绑定字面值2.初始化空指针int*p=0;int*p=NULL;int*p=nullptr;//最好用这个任何非零指......
  • Html使用Vue3+ElementPlus(图标 ElMessage)
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"/><metahttp-equiv="X-UA-Compatible"content="IE=edge"/><metaname="viewport"content="wid......
  • mybatis-plus 数据库日志仅打印SQL
     一、项目背景:springboot、web组件、Mysql8、java8+; 二、开发环境打印SQL及执行结果日志,便于调试接口;mybatis-plus配置文件的configuration节点添加以下配置2、效果   三、生产环境仅打印SQL,避免打印过多的查询结果影响系统性能    1、pom中增加sl4j的......
  • mybatis plus generate
    1.添加依赖<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency><dependency>......
  • 2023-06-19 uniapp云打包报错:app-plus.distribute.icons.android.hdpi 文件不存在
    详细报错:[HBuilder]11:02:51.408Manifest.json文件以下节点配置错误,请检查修复[HBuilder]11:02:51.408app-plus.distribute.icons.android.hdpi 文件不存在[HBuilder]11:02:51.408app-plus.distribute.icons.android.xxhdpi 文件不存在[HBuilder]11:02:51.408ap......
  • 【对比】ChatGPT Plus与ChatGPT实操对比体验
    前言......
  • MybatisPlus自动填充
    importcom.baomidou.mybatisplus.core.handlers.MetaObjectHandler;importlombok.extern.slf4j.Slf4j;importorg.apache.ibatis.reflection.MetaObject;importorg.springframework.stereotype.Component;importjava.time.LocalDateTime;@Slf4j@Componentpublic......
  • MybatisPlus拦截器配置
    /***配置mp的分页插件(拦截)*/@ConfigurationpublicclassMybatisPlusConfig{@BeanpublicMybatisPlusInterceptormpInterceptor(){MybatisPlusInterceptormybatisPlusInterceptor=newMybatisPlusInterceptor();mybatisPlusInterceptor.......