采用EasyExcel+多线程的方式实现大批量数据写入数据库

文章讲述了作者在面临大量数据导入数据库的问题时,从使用POI到尝试多线程、EasyExcel和MybatisPlus批量插入的优化过程。在多线程基础上,通过EasyExcel读取数据并分片,每个分片由单独线程处理,利用MybatisPlus批量插入,显著提升了效率,降低了系统资源消耗。最终实现30w条数据在6分44秒内完成导入。
摘要由CSDN通过智能技术生成

近期遇到一个需要将大量数据写入数据库的事情,但是没有正版Navicate,别的软件也不好用,就想着写个接口来实现,(如果不考虑安全问题,我建议使用navicate->网上pojie版资源很多)

回归正题因为是周五下午快下班告诉我的,所以当时思考了一下,决定采用POI来做(因为之前没有用过这个功能)后来写了一下,实现了这个功能(第一个版本),但是非常简陋,面对2000条数据都很耗时,更不要说30w条数据。

周五下班在地铁上在想怎么优化代码,坐上回学校的校车时候突然想到用多线程,回来之后立马用多线程实现了,最终测试了一下面对2017条数据耗时大概14.55秒(第二个版本),但是面对29w条数据时候出现电脑性能被吃满,非常卡,cpu和内存都被吃满了,这还仅仅是一个存入数据库的功能而已,如果真的上线,对其他功能以及整个程序会造成无法挽回的后果,29w条数据最终耗时大概在24分钟左右,相比第一个版本耗时64分钟提升太多了,但是最终还是决定继续优化,碰巧周五坐大巴时候看到一篇博客讲的是阿里的EasyExcel性能非常好,周日也没啥事情,就决定采用EasyExcel来实现一下,万万没想到只是比第一个版本在导入2017条数据时候快了1秒在导入29w条数据时候快了大概有2分钟吧,当时就蒙了,还以为是用错了,又去官网看了一下,结果还是一样,最后想到了用MybatisPlus的批量导入功能,可是依旧改变不大(第三个版本)

最终想着让Chatgpt帮我实现,可是弄了一下午,最后发现它根本不会(只能锦上添花,当个搜索引擎来用),我就尝试了很多办法,看了很多人的文档,都以失败告终。然后就决定自己来想怎么做,经过思考决定在第二个版本多线程的基础上来实现,我采用EasyExcel来读取数据,然后对数据进行分片操作,每一片对应一个线程,然后采用MybatisPlus的批量插入,一次插入一片数据,我定义的一片数据为500条。最终结果是非常快2017条一共耗时6秒,比一般的多线程快了一半多时间,30w+条数据耗时6分44秒。并且全程电脑性能正常,没有吃CPU和内存,其他指数也都正常,真正达到了我的预期。

最后我也去网上又找了其他的方法,发现有的比我的快得多只用了24秒,能力有限我确实想不出是怎么实现的,代码还有许多要调优的地方,大家可以自己再优化一下。

 

 

    @Test
    public void testExcel04(){
        String excelFilePath = "D:\\data\\0406-0410.xlsx";
        int numThreads = 8; // 线程数
        int pagesize=500;

        // 创建线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(numThreads);
        List<Exceltest> list = EasyExcel.read(new File(excelFilePath))
                .head(Exceltest.class)
                .sheet(0)
                .doReadSync();
        int size = list.size();

        //对list进行切分然后对分片进行插入操作
        for (int i = 0; i < size; i+=pagesize) {
            int startindex= i;
            int endindex=Math.min(i+pagesize,size);
            List<Exceltest> sublist = list.subList(startindex, endindex);
//            new work04(list,pagesize)
            threadPool.submit(new Runnable() {
                @Override
                public void run() {
                    savedata(sublist,pagesize);
                }
            });
        }

        // 关闭线程池
        threadPool.shutdown();
        //等待执行完毕
        try {
            threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public void savedata(List<Exceltest> list,int pagesize){
        System.out.println(LocalDateTime.now()+"线程"+Thread.currentThread().getName()+"正在执行分片"+(list.get(0).getObjectid()/pagesize+1)+"保存数据的任务.....");
        exceltestService.saveBatch(list);
        System.out.println(LocalDateTime.now()+"线程"+Thread.currentThread().getName() + "执行分片"+(list.get(0).getObjectid() / pagesize + 1) + "保存数据的任务完成.....");
    }

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

确实够拉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值