项目中MybatisPlus插入数据优化之旅

项目场景:

项目中涉及到接口人员同步,大约10万级数据量,但是在插入数据库的过程中发现很多问题,记录一下。

问题描述:

因为表中字较多,第一次插入数据库花了10多分钟,实在受不了,最终优化10万数据量插入数据库大约19秒左右。

解决方案:

解决方案一
第一次优化是在mysql链接的参数上面

批量插入:
&rewriteBatchedStatements=true
&allowMultiQueries=true

这两个参数非常重要,提升很明显,配置完从10多分钟优化到3分钟左右

解决方案二
执行分批插入,用的是MybatisPlus自带的saveBatch()方法
每批分500,循环插入,从3分钟优化到2分钟

解决方法三
多线程分批插入
测试类

 @Test
    public  void testMulBatch() throws InterruptedException{
        ExecutorService es = Executors.newFixedThreadPool(5);
        CountDownLatch c = new CountDownLatch(100);
        List<User> users = new ArrayList<>();
        for(int i =0 ; i<1000000; i++){
            User user = new User();
            user.setId((long)i);
            user.setAge(i);
            user.setName("dawdawdawdaw"+i);
            user.setEmail("dawdwadwa@adwda.com");
            users.add(user);
        }
        long begin = System.currentTimeMillis();
        for(int i= 0;i<100;i++) {
            es.submit(new MyThread(users.subList(i*10000,(i+1)*10000),c,userService));
        }
        c.await();
        es.shutdown();
        long end = System.currentTimeMillis();
        System.out.println("批量插入时间"+(end-begin));
    }

线程类

class MyThread implements Runnable {
    private CountDownLatch c;
    private UserService userService;
    private List<User> users;

    public MyThread(List<User> users, CountDownLatch c, UserService userService) {
        this.c = c;
        this.users = users;
        this.userService = userService;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName());
        userService.saveBatch(users);
        c.countDown();
    }
}

优化结果还是挺明显的,大致从2分钟提升到30多秒

解决方法四
因为看到控制台打印的sql语句发现,插入参数个数不同,导致saveBatch()变成一条一条的插入。mybatisplus可以帮你补全参数,但是要配置一下

public class EasySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        //防止父类方法不可用
        List<AbstractMethod> methods= super.getMethodList(mapperClass);
        methods.add(new InsertBatchSomeColumn());
        return methods;
    }
}

@Configuration
public class MybatisConfig {
    @Bean
    public EasySqlInjector easySqlInjector() {
        return new EasySqlInjector();
    }
}


public interface UserMapper extends BaseMapper<User> {
    Integer insertBatchSomeColumn(List<User> entityList);
}

调用类

 userService.getBaseMapper().insertBatchSomeColumn(users);

通过以上4次优化,现在最终插入时间为19秒。

总结

大批量数据插入数据库时首先把大化小,先考虑在代码上优化,多线程,分批等方案。在考虑表结构和sql语句,最终Mysql数据库本身参数问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值