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

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是自己设置的所以没有问题,在这里提个醒

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

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值