iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > Python >java多线程批量拆分List导入数据库的实现过程
  • 767
分享到

java多线程批量拆分List导入数据库的实现过程

2024-04-02 19:04:59 767人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

目录一、前言二、直接把list怼进Mysql三、分组把list导入mysql中四、多线程分批导入Mysql五、小结一、前言 前两天做了一个导入的功能,导入开始的时候非常慢,导入2w

一、前言

前两天做了一个导入的功能,导入开始的时候非常慢,导入2w条数据要1分多钟,后来一点一点的优化,从直接把list怼进Mysql中,到分配把list导入Mysql中,到多线程把list导入Mysql中。时间是一点一点的变少了。非常的爽,最后变成了10s以内。下面就展示一下过程。

二、直接把list怼进Mysql

使用mybatis的批量导入操作:


  @Transactional(rollbackFor = Exception.class)
    public int addFreshStudentsNew2(List<FreshStudentAndStudentModel> list, String schoolNo) {
        if (list == null || list.isEmpty()) {
            return 0;
        }
        List<StudentEntity> studentEntityList = new LinkedList<>();
        List<EnrollStudentEntity> enrollStudentEntityList = new LinkedList<>();
        List<AllusersEntity> allusersEntityList = new LinkedList<>();

        for (FreshStudentAndStudentModel freshStudentAndStudentModel : list) {

            EnrollStudentEntity enrollStudentEntity = new EnrollStudentEntity();
            StudentEntity studentEntity = new StudentEntity();
            BeanUtils.copyProperties(freshStudentAndStudentModel, studentEntity);
            BeanUtils.copyProperties(freshStudentAndStudentModel, enrollStudentEntity);
            String operator = TenancyContext.UserID.get();
            String studentId = BaseUuidUtils.base58Uuid();
            enrollStudentEntity.setId(BaseUuidUtils.base58Uuid());
            enrollStudentEntity.setStudentId(studentId);
            enrollStudentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            enrollStudentEntity.setOperator(operator);
            studentEntity.setId(studentId);
            studentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            studentEntity.setOperator(operator);
            studentEntityList.add(studentEntity);
            enrollStudentEntityList.add(enrollStudentEntity);

            AllusersEntity allusersEntity = new AllusersEntity();
            allusersEntity.setId(enrollStudentEntity.getId());
            allusersEntity.setUserCode(enrollStudentEntity.getNemtCode());
            allusersEntity.setUserName(enrollStudentEntity.getName());
            allusersEntity.setSchoolNo(schoolNo);
            allusersEntity.setTelNum(enrollStudentEntity.getTelNum());
            allusersEntity.setPassword(enrollStudentEntity.getNemtCode());  //密码设置为考生号
            allusersEntityList.add(allusersEntity);
        }
            enResult = enrollStudentDao.insertAll(enrollStudentEntityList);
            stuResult = studentDao.insertAll(studentEntityList);
            allResult = allusersFacade.insertUserList(allusersEntityList);

        if (enResult > 0 && stuResult > 0 && allResult) {
            return 10;
        }
        return -10;
    }

Mapper.xml


  <insert id="insertAll" parameterType="com.dmsdbj.itoo.basicInfo.entity.EnrollStudentEntity">
        insert into tb_enroll_student
        <trim prefix="(" suffix=")" suffixOverrides=",">
                id,  
                remark,  
                nEMT_aspiration,  
                nEMT_code,  
                nEMT_score,  
                student_id,  
                identity_card_id,  
                level,  
                major,  
                name,  
                nation,  
                secondary_college,  
                operator,  
                sex,  
                is_delete,  
                account_address,  
                native_place,  
                original_place,  
                used_name,  
                pictrue,  
                join_party_date,  
                political_status,  
                tel_num,  
                is_reGIStry,  
                graduate_school,  
                create_time,  
                update_time        </trim>        
        values
        <foreach collection="list" item="item" index="index" separator=",">
        (
                #{item.id,jdbcType=VARCHAR},
                #{item.remark,jdbcType=VARCHAR},
                #{item.nemtAspiration,jdbcType=VARCHAR},
                #{item.nemtCode,jdbcType=VARCHAR},
                #{item.nemtScore,jdbcType=VARCHAR},
                #{item.studentId,jdbcType=VARCHAR},
                #{item.identityCardId,jdbcType=VARCHAR},
                #{item.level,jdbcType=VARCHAR},
                #{item.major,jdbcType=VARCHAR},
                #{item.name,jdbcType=VARCHAR},
                #{item.nation,jdbcType=VARCHAR},
                #{item.secondaryCollege,jdbcType=VARCHAR},
                #{item.operator,jdbcType=VARCHAR},
                #{item.sex,jdbcType=VARCHAR},
                0,
                #{item.accountAddress,jdbcType=VARCHAR},
                #{item.nativePlace,jdbcType=VARCHAR},
                #{item.originalPlace,jdbcType=VARCHAR},
                #{item.usedName,jdbcType=VARCHAR},
                #{item.pictrue,jdbcType=VARCHAR},
                #{item.joinPartyDate,jdbcType=VARCHAR},
                #{item.politicalStatus,jdbcType=VARCHAR},
                #{item.telNum,jdbcType=VARCHAR},
                #{item.isRegistry,jdbcType=TINYINT},
                #{item.graduateSchool,jdbcType=VARCHAR},
                now(),
                now()        
        )   
        </foreach>                
  </insert> 

代码说明:

底层的mapper是通过逆向工程来生成的,批量插入如下,是拼接成类似: insert into tb_enroll_student()values (),()…….() ;

这样的缺点是,数据库一般有一个默认的设置,就是每次sql操作的数据不能超过4M。这样插入,数据多的时候,数据库会报错Packet for query is too large (6071393 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable.,虽然我们可以通过

类似 修改 my.ini 加上 max_allowed_packet =67108864

67108864=64M

默认大小4194304 也就是4M

修改完成之后要重启mysql服务,如果通过命令行修改就不用重启mysql服务。

完成本次操作,但是我们不能保证项目单次最大的大小是多少,这样是有弊端的。所以可以考虑进行分组导入。

三、分组把list导入Mysql中

同样适用mybatis批量插入,区别是对每次的导入进行分组计算,然后分多次进行导入:


 @Transactional(rollbackFor = Exception.class)
    public int addFreshStudentsNew2(List<FreshStudentAndStudentModel> list, String schoolNo) {
        if (list == null || list.isEmpty()) {
            return 0;
        }
        List<StudentEntity> studentEntityList = new LinkedList<>();
        List<EnrollStudentEntity> enrollStudentEntityList = new LinkedList<>();
        List<AllusersEntity> allusersEntityList = new LinkedList<>();

        for (FreshStudentAndStudentModel freshStudentAndStudentModel : list) {

            EnrollStudentEntity enrollStudentEntity = new EnrollStudentEntity();
            StudentEntity studentEntity = new StudentEntity();
            BeanUtils.copyProperties(freshStudentAndStudentModel, studentEntity);
            BeanUtils.copyProperties(freshStudentAndStudentModel, enrollStudentEntity);
            String operator = TenancyContext.UserID.get();
            String studentId = BaseUuidUtils.base58Uuid();
            enrollStudentEntity.setId(BaseUuidUtils.base58Uuid());
            enrollStudentEntity.setStudentId(studentId);
            enrollStudentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            enrollStudentEntity.setOperator(operator);
            studentEntity.setId(studentId);
            studentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            studentEntity.setOperator(operator);
            studentEntityList.add(studentEntity);
            enrollStudentEntityList.add(enrollStudentEntity);

            AllusersEntity allusersEntity = new AllusersEntity();
            allusersEntity.setId(enrollStudentEntity.getId());
            allusersEntity.setUserCode(enrollStudentEntity.getNemtCode());
            allusersEntity.setUserName(enrollStudentEntity.getName());
            allusersEntity.setSchoolNo(schoolNo);
            allusersEntity.setTelNum(enrollStudentEntity.getTelNum());
            allusersEntity.setPassword(enrollStudentEntity.getNemtCode());  //密码设置为考生号
            allusersEntityList.add(allusersEntity);
        }

        int c = 100;
        int b = enrollStudentEntityList.size() / c;
        int d = enrollStudentEntityList.size() % c;

        int enResult = 0;
        int stuResult = 0;
        boolean allResult = false;

        for (int e = c; e <= c * b; e = e + c) {
            enResult = enrollStudentDao.insertAll(enrollStudentEntityList.subList(e - c, e));
            stuResult = studentDao.insertAll(studentEntityList.subList(e - c, e));
            allResult = allusersFacade.insertUserList(allusersEntityList.subList(e - c, e));
        }
        if (d != 0) {
            enResult = enrollStudentDao.insertAll(enrollStudentEntityList.subList(c * b, enrollStudentEntityList.size()));
            stuResult = studentDao.insertAll(studentEntityList.subList(c * b, studentEntityList.size()));
            allResult = allusersFacade.insertUserList(allusersEntityList.subList(c * b, allusersEntityList.size()));
        }

        if (enResult > 0 && stuResult > 0 && allResult) {
            return 10;
        }
        return -10;
    }

代码说明:

这样操作,可以避免上面的错误,但是分多次插入,无形中就增加了操作实践,很容易超时。所以这种方法还是不值得提倡的。

再次改进,使用多线程分批导入。

四、多线程分批导入Mysql

依然使用mybatis的批量导入,不同的是,根据线程数目进行分组,然后再建立多线程池,进行导入。


  @Transactional(rollbackFor = Exception.class)
    public int addFreshStudentsNew(List<FreshStudentAndStudentModel> list, String schoolNo) {
        if (list == null || list.isEmpty()) {
            return 0;
        }
        List<StudentEntity> studentEntityList = new LinkedList<>();
        List<EnrollStudentEntity> enrollStudentEntityList = new LinkedList<>();
        List<AllusersEntity> allusersEntityList = new LinkedList<>();

        list.forEach(freshStudentAndStudentModel -> {
            EnrollStudentEntity enrollStudentEntity = new EnrollStudentEntity();
            StudentEntity studentEntity = new StudentEntity();
            BeanUtils.copyProperties(freshStudentAndStudentModel, studentEntity);
            BeanUtils.copyProperties(freshStudentAndStudentModel, enrollStudentEntity);
            String operator = TenancyContext.UserID.get();
            String studentId = BaseUuidUtils.base58Uuid();
            enrollStudentEntity.setId(BaseUuidUtils.base58Uuid());
            enrollStudentEntity.setStudentId(studentId);
            enrollStudentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            enrollStudentEntity.setOperator(operator);
            studentEntity.setId(studentId);
            studentEntity.setIdentityCardId(freshStudentAndStudentModel.getIdCard());
            studentEntity.setOperator(operator);
            studentEntityList.add(studentEntity);
            enrollStudentEntityList.add(enrollStudentEntity);

            AllusersEntity allusersEntity = new AllusersEntity();
            allusersEntity.setId(enrollStudentEntity.getId());
            allusersEntity.setUserCode(enrollStudentEntity.getNemtCode());
            allusersEntity.setUserName(enrollStudentEntity.getName());
            allusersEntity.setSchoolNo(schoolNo);
            allusersEntity.setTelNum(enrollStudentEntity.getTelNum());
            allusersEntity.setPassword(enrollStudentEntity.getNemtCode());  //密码设置为考生号
            allusersEntityList.add(allusersEntity);
        });


        int nThreads = 50;

        int size = enrollStudentEntityList.size();
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
        List<Future<Integer>> futures = new ArrayList<Future<Integer>>(nThreads);

        for (int i = 0; i < nThreads; i++) {
            final List<EnrollStudentEntity> EnrollStudentEntityImputList = enrollStudentEntityList.subList(size / nThreads * i, size / nThreads * (i + 1));
            final List<StudentEntity> studentEntityImportList = studentEntityList.subList(size / nThreads * i, size / nThreads * (i + 1));
            final List<AllusersEntity> allusersEntityImportList = allusersEntityList.subList(size / nThreads * i, size / nThreads * (i + 1));

           Callable<Integer> task1 = () -> {
          studentSave.saveStudent(EnrollStudentEntityImputList,studentEntityImportList,allusersEntityImportList);
               return 1;
            };
          futures.add(executorService.submit(task1));
        }
        executorService.shutdown();
        if (!futures.isEmpty() && futures != null) {
            return 10;
        }
        return -10;
    }

代码说明:

上面是通过应用ExecutorService 建立了固定的线程数,然后根据线程数目进行分组,批量依次导入。一方面可以缓解数据库的压力,另一个面线程数目多了,一定程度会提高程序运行的时间。缺点就是要看服务器的配置,如果配置好的话就可以开多点线程,配置差的话就开小点。

五、小结

通过使用这个操作真是不断的提高了,项目使用技巧也是不错。加油~~ 多线程哦~~

到此这篇关于java多线程批量拆分List导入数据库的文章就介绍到这了,更多相关java多线程批量拆分List内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: java多线程批量拆分List导入数据库的实现过程

本文链接: https://www.lsjlt.com/news/155961.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • java多线程批量拆分List导入数据库的实现过程
    目录一、前言二、直接把list怼进Mysql三、分组把list导入Mysql中四、多线程分批导入Mysql五、小结一、前言 前两天做了一个导入的功能,导入开始的时候非常慢,导入2w...
    99+
    2024-04-02
  • 怎么实现java多线程批量拆分List导入数据库
    本篇内容介绍了“怎么实现java多线程批量拆分List导入数据库”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!直接把list怼进Mysql使...
    99+
    2023-06-25
  • SpringBoot用多线程批量导入数据库实现方法
    目录环境原始的for循环入库批量保存操作在批量插入的基础上使用多线程处理多线程入库的事务问题环境 springboot、mybatisPlus、mysql8 mysql8(部署在1核...
    99+
    2023-02-03
    SpringBoot多线程导入数据库 SpringBoot导入数据库 SpringBoot批量导入数据库
  • Java分批将List数据导入数据库
    目录 一、项目场景:二、为什么要分批次?三、解决方案:1. MyBatisPlus原生方法导入2. List分组导入(1)UserServiceImpl类中导入方法(2)UserMapper数据持久化接口(3)UserMapper....
    99+
    2023-08-19
    java 数据库 mysql
  • Java实现多线程大批量同步数据(分页)
    背景 最近遇到个功能,两个月有300w+的数据,之后还在累加,因一开始该数据就全部存储在mysql表,现需要展示在页面,还需要关联另一张表的数据,而且产品要求页面的查询条件多达20个...
    99+
    2022-11-13
    Java同步数据 Java多线程同步数据 Java多线程大批量同步数据
  • Java大批量导出Excel数据的优化过程
    目录背景问题和解决方案遇到的问题解决步骤整理工具类参考资料背景 团队目前在做一个用户数据看板(下面简称看板),基本覆盖用户的所有行为数据,并生成分析报表,用户行为由多个数据来源组成...
    99+
    2024-04-02
  • 小程序中如何实现excel数据批量导入
    本篇内容介绍了“小程序中如何实现excel数据批量导入”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 建立数据源要想将数据入库,就先需要建...
    99+
    2023-07-02
  • java之CSV大批量数据入库的实现
    目录需求前期准备代码展示关键代码及思路关键的SQL语句方案选型需求 读200+的CSV/EXCEL文件,按文件名称存到不同数据库 前期准备 环境 maven + jdk8 + mys...
    99+
    2023-02-05
    java CSV大批量入库 java CSV 批量入库
  • Java多线程实现FTP批量上传文件
    本文实例为大家分享了Java多线程实现FTP批量上传文件的具体代码,供大家参考,具体内容如下 1、构建FTP客户端 package cn.com.pingtech.common.ft...
    99+
    2024-04-02
  • SQLServer数据库怎么远程查询并批量导入数据
    本篇内容主要讲解“SQLServer数据库怎么远程查询并批量导入数据”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SQLServer数据库怎么远程查询并批量导入...
    99+
    2024-04-02
  • Java API如何实现向Hive批量导入数据
    Java API实现向Hive批量导入数据 Java程序中产生的数据,如果导入oracle或者mysql库,可以通过jdbc连接insert批量操作完成,但是当前版本的hive并不支...
    99+
    2024-04-02
  • 怎么用java多线程处理大批量数据
    在Java中使用多线程处理大批量数据可以提高程序的处理效率。下面是一个简单的示例代码,演示了如何使用多线程处理大批量数据: impo...
    99+
    2024-04-02
  • Springboot 手动分页查询分批批量插入数据的实现流程
    目录前言业务场景是什么? 正文前言 业务场景是什么?  就是数据库的一批数据,量不少,需要执行同步插入到别的地方。 简单点肯定是一次性查出来,然后循环一个个插入,...
    99+
    2024-04-02
  • 基于Java SSM如何实现Excel数据批量导入
    今天就跟大家聊聊有关基于Java SSM如何实现Excel数据批量导入,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。导入Maven依赖<dependency>&...
    99+
    2023-06-21
  • java多线程批量处理数据的方法是什么
    Java中处理批量数据的方法有以下几种:1. 使用线程池:创建一个线程池,将任务拆分为多个子任务,然后将子任务交给线程池中的线程进行...
    99+
    2023-09-27
    java
  • 小程序中实现excel数据的批量导入的示例代码
    目录1 建立数据源2 编制入库的代码2.1 创建低码方法2.2 低码中调用连接器3 最终的代码4 总结我们上一篇介绍了如何利用微搭的自定义连接器接入腾讯文档的数据,光有接入是不够的,...
    99+
    2024-04-02
  • 怎么使用java多线程处理大批量数据
    要使用Java多线程处理大批量数据,可以按照以下步骤进行:1. 创建一个线程池:使用Java中的ThreadPoolExecutor...
    99+
    2023-09-26
    java
  • Java实现批量导出导入数据及附件文件zip包
    目录前言-应用场景一、导出ZIP包1. 列表数据导出到本地excel文件2. 下载附件信息3. 生成压缩文件(浏览器下载)4. 删除临时目录二、导入ZIP包1. 上传zip包,解压到...
    99+
    2024-04-02
  • mysql导入导出数据库以及函数的过程
    本篇内容主要讲解“mysql导入导出数据库以及函数的过程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mysql导入导出数据库以及函数的过程”吧!常用导出数据命...
    99+
    2024-04-02
  • Java多线程怎么实现FTP批量上传文件
    这篇文章主要介绍了Java多线程怎么实现FTP批量上传文件的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java多线程怎么实现FTP批量上传文件文章都会有所收获,下面我们一起来看看吧。1、构建FTP客户端pac...
    99+
    2023-07-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作