关于批量导入的一些想法

背景

业务系统中经常有批量导入的功能。
导入的数据里面,因为不清楚这些数据是新增的或是更新的,所以默认的一种做法是,先查一下,然后分出哪些是新增的数据,哪些是更新的数据,
然后再分新增和更新。

理论是这样子,但总感觉每次都要查询一下,也不是很舒服。

有一个想法
如果一个批次,100条数据,
如果先不管它有多少是需要insert的,先把这100条都按update 去做,然后如果update 的总数小于100,再去查询一次,找出需要 insert的,再去insert, 这次,会不会稍为好一点点呢。
如果update 的条目总数等于100,那说明不需要做insert,也不需要再去查一次。

并发的情况

如果是先查询,再去做 insert,也是会存在一种可能性,
A,B两个用户都去做导入,并且数据存在重复,
A,B都先查询出来,发现其中有10个Id 不存在,然后都选择对这10条数据进行 insert, 刚好 A用户先提交并且insert成功,commit了。这个时候B用户再按预期操作去insert,会发现报错(主键重复,如果不是主键,那数据也会重复了)。

这种情况是很可能存在的,如果是100个用户去同时导入,那这种可能性就更高好。
嗯,感觉都不是特别好。

先记录一下吧。


怎样做批量导入性能比较高呢?

参考转载于这篇文章: https://juejin.cn/post/7007608714093920286
个人是还没有试验过,不过这个结果也比较有参考价值了的。

image


private StopWatch sw = new StopWatch();

@Test
public void processInsert() {
    sw.start("批处理执行 插入");
    // 打开批处理
    SqlSession session = sqlSessionFactory.openSession(ExecutorType.BATCH);
    UserInfoBatchMapper mapper = session.getMapper(UserInfoBatchMapper.class);
    for (int i = 0,length = list.size(); i < length; i++) {
        mapper.insert(list.get(i));
        //每20000条提交一次防止内存溢出
        if(i%20000==19999){
            session.commit();
            session.clearCache();
        }
    }
    session.commit();
    session.clearCache();
    sw.stop();
    log.info("all cost info:{}",sw.prettyPrint());
}
posted @ 2023-02-02 14:33  aaacarrot  阅读(26)  评论(0编辑  收藏  举报