Mybatis-plus大批量数据导入与导出

数据导出–流式查询

public interface PsytheMapper extends BaseMapper<Psythe> {
    @Select("select * from psythe;")
    @Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = 1000)
    @ResultType(Psythe.class)
    void selectAllObject(ResultHandler<Psythe> handler);
}

所谓流式查询是指在一次connection中,不中断的从数据库拉取数据。
我说的这句话可能根别的up主或者播主说的不一样,这是因为不同的数据库对于流式查询实现方式和查询方式是不一样的。在使用的时候要注意,不是所有的数据库都建议使用这种方式。

数据导入–异步!!

异步的概念就不多讲了,实现异步的方式有很多,在同一个主机上的,在不同主机上的有不同的方法,对于导入数据这个任务而言,常见的比较推荐的实现方式(我知道的)主要有两种(这里主要面对访问量大,IO跟不上的情况,而不是单次数量太大):
1、使用消息队列,用消费者消费任务。这种方法适合项目组各种配置齐全的情况。但是比较贫穷组(比如我)。就不适合,因为没必要,而不是领导抠。
2、用定时任务,作一张表这个表里记录着你所有执行了和没执行的任务,在是否执行那一列中设置三个状态,未执行,正在执行,执行完,定时任务每过一段时间扫描这个表。把未执行的执行一遍就好了。

同时在数据方面,也要分批次的导入数据这个就不复杂了:

    @Transactional(rollbackFor = Exception.class)
    public void savePsytheExcel(MultipartFile file) {
        List<Psythe> psythes = new LinkedList<>();
        try(InputStream is = file.getInputStream()) {
            EasyExcel.read(is, PsytheDto.class, new ReadListener<Psythe>() {
                @Override
                public void invoke(Psythe o, AnalysisContext analysisContext) {
                    psythes.add(o);
                    //可以这么做
                    if (psythes.size() >= BATCH_SIZE) {
                        saveBatch(psythes);
                        psythes.clear();
                    }
                }
                @Override
                public void doAfterAllAnalysed(AnalysisContext analysisContext) {

                }
            }).sheet().doRead();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        insertBatchPsythe(psythes);
    }

如果内存比较阔绰,而且需要对数据校验,那就先读出来再subList插入就可以了,但是这里一定要注意,subList不会产生新的对象,也就是说你对subList的一切操作都是作用在原来的队列上的,这个要注意!

	private void insertBatchPsythe(List<Psythe> psythes) {
        for (int i = 0; i < psythes.size(); i+= BATCH_SIZE) {
            //subList 要注意
            saveBatch(psythes.subList(i*BATCH_SIZE, Math.min(psythes.size(), (i+1)*BATCH_SIZE)));
        }
    }

流式查询–不同数据库上的不同

我用过的数据库不少,但是从来没真正感受过不同数据库之间的差距,我对数据库之间的差异停留在数据库引擎和与之相关的八股文上,这是第一次被不同数据库的差异教训。
来比较一下Oracle数据库postgreSQL和mysql三种数据库在流式查询中的差异

1、Oracle数据库:没什么好注意的

2、postgreSQL数据库,

跟oracle相比,在大多数地方我没感受到有什么不同,但是在开启stream 的时候,这个数据库需要满足三个条件:
1、fechSize设置需要 > 0。
2、jdbc连接字符串不能加 preferQueryMode =simple。
3、需要设置autocommit为false
三个条件同时满足才可以开启。

3、Mysql

哈哈哈~~,那可太不一样了,简单的说,其实Mysql不推荐大家使用流式查询,这是为什么呢?因为MySQL的JDBC驱动本质上并不支持设置fetchsize,不管设置多大的fetchsize,JDBC驱动依然会将select的全部结果都读取到客户端后再处理, 这样的话当select返回的结果集非常大时将会撑爆Client端的内存。
但是在设置的时候fetchsize设置为Integer.MIN_VALUE的时候,mysql会一条一条的返回查询结果,很开心。
而且Oracle使用一个缓冲区来实现批量的返回查询结果,而Mysql呢!它通过使用CS阻塞方式的网络流控制实现服务端不会一下发送大量数据到客户端撑爆客户端内存。这就很坑了,因为这意味着一个MySQL数据库连接同一时间只能为一个ResultSet对象服务,并且如果该ResultSet对象没有关闭,势必会影响其他查询对数据库连接的使用!
也就是说如果贵公司使用Mysql数据库,而且数据库连接不是很富裕的话,就不要使用流式查询了~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值