<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          利用多線程批量拆分 List 導(dǎo)入數(shù)據(jù)庫,效率杠杠的!

          共 9971字,需瀏覽 20分鐘

           ·

          2022-05-09 23:11

          一、前言

          前兩天做了一個(gè)導(dǎo)入的功能,導(dǎo)入開始的時(shí)候非常慢,導(dǎo)入2w條數(shù)據(jù)要1分多鐘,后來一點(diǎn)一點(diǎn)的優(yōu)化,從直接把list懟進(jìn)Mysql中,到分配把list導(dǎo)入Mysql中,到多線程把list導(dǎo)入Mysql中。

          時(shí)間是一點(diǎn)一點(diǎn)的變少了。非常的爽,最后變成了10s以內(nèi)。

          下面就展示一下過程。

          二、直接把list懟進(jìn)Mysql

          使用mybatis的批量導(dǎo)入操作:

          @Transactional(rollbackFor?=?Exception.class)??
          public?int?addFreshStudentsNew2(List<FreshStudentAndStudentModel>?list,?String?schoolNo)?
          {??
          ????if?(list?==?null?||?list.isEmpty())?{??
          ????????return?0;??
          ????}??
          ????List?studentEntityList?=?new?LinkedList<>();??
          ????List?enrollStudentEntityList?=?new?LinkedList<>();??
          ????List?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());??//密碼設(shè)置為考生號(hào)??
          ????????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 (),()…….();

          這樣的缺點(diǎn)是,數(shù)據(jù)庫一般有一個(gè)默認(rèn)的設(shè)置,就是每次sql操作的數(shù)據(jù)不能超過4M。這樣插入,數(shù)據(jù)多的時(shí)候,數(shù)據(jù)庫會(huì)報(bào)錯(cuò)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 =6710886467108864=64M,默認(rèn)大小4194304 也就是4M

          修改完成之后要重啟mysql服務(wù),如果通過命令行修改就不用重啟mysql服務(wù)。

          完成本次操作,但是我們不能保證項(xiàng)目單次最大的大小是多少,這樣是有弊端的。所以可以考慮進(jìn)行分組導(dǎo)入。

          三、分組把list導(dǎo)入Mysql中

          同樣適用mybatis批量插入,區(qū)別是對(duì)每次的導(dǎo)入進(jìn)行分組計(jì)算,然后分多次進(jìn)行導(dǎo)入:

          @Transactional(rollbackFor?=?Exception.class)??
          public?int?addFreshStudentsNew2(List<FreshStudentAndStudentModel>?list,?String?schoolNo)?
          {??
          ????if?(list?==?null?||?list.isEmpty())?{??
          ????????return?0;??
          ????}??
          ????List?studentEntityList?=?new?LinkedList<>();??
          ????List?enrollStudentEntityList?=?new?LinkedList<>();??
          ????List?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());??//密碼設(shè)置為考生號(hào)??
          ????????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;??
          }??

          代碼說明:

          這樣操作,可以避免上面的錯(cuò)誤,但是分多次插入,無形中就增加了操作實(shí)踐,很容易超時(shí)。所以這種方法還是不值得提倡的。

          再次改進(jìn),使用多線程分批導(dǎo)入。

          四、多線程分批導(dǎo)入Mysql

          依然使用mybatis的批量導(dǎo)入,不同的是,根據(jù)線程數(shù)目進(jìn)行分組,然后再建立多線程池,進(jìn)行導(dǎo)入。

          @Transactional(rollbackFor?=?Exception.class)??
          public?int?addFreshStudentsNew(List<FreshStudentAndStudentModel>?list,?String?schoolNo)?
          {??
          ????if?(list?==?null?||?list.isEmpty())?{??
          ????????return?0;??
          ????}??
          ????List?studentEntityList?=?new?LinkedList<>();??
          ????List?enrollStudentEntityList?=?new?LinkedList<>();??
          ????List?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());??//密碼設(shè)置為考生號(hào)??
          ????????allusersEntityList.add(allusersEntity);??
          ????});??
          ??
          ??
          ????int?nThreads?=?50;??
          ??
          ????int?size?=?enrollStudentEntityList.size();??
          ????ExecutorService?executorService?=?Executors.newFixedThreadPool(nThreads);??
          ????List>?futures?=?new?ArrayList>(nThreads);??
          ??
          ????for?(int?i?=?0;?i?????????final?List?EnrollStudentEntityImputList?=?enrollStudentEntityList.subList(size?/?nThreads?*?i,?size?/?nThreads?*?(i?+?1));??
          ????????final?List?studentEntityImportList?=?studentEntityList.subList(size?/?nThreads?*?i,?size?/?nThreads?*?(i?+?1));??
          ????????final?List?allusersEntityImportList?=?allusersEntityList.subList(size?/?nThreads?*?i,?size?/?nThreads?*?(i?+?1));??
          ??
          ???????Callable?task1?=?()?->?{??
          ??????studentSave.saveStudent(EnrollStudentEntityImputList,studentEntityImportList,allusersEntityImportList);??
          ???????????return?1;??
          ????????};??
          ??????futures.add(executorService.submit(task1));??
          ????}??
          ????executorService.shutdown();??
          ????if?(!futures.isEmpty()?&&?futures?!=?null)?{??
          ????????return?10;??
          ????}??
          ????return?-10;??
          }??

          代碼說明:

          上面是通過應(yīng)用ExecutorService?建立了固定的線程數(shù),然后根據(jù)線程數(shù)目進(jìn)行分組,批量依次導(dǎo)入。一方面可以緩解數(shù)據(jù)庫的壓力,另一個(gè)面線程數(shù)目多了,一定程度會(huì)提高程序運(yùn)行的時(shí)間。

          缺點(diǎn)就是要看服務(wù)器的配置,如果配置好的話就可以開多點(diǎn)線程,配置差的話就開小點(diǎn)。

          五、小結(jié)

          通過使用這個(gè)操作真是不斷的提高了,項(xiàng)目使用技巧也是不錯(cuò)。

          加油~~ 多線程哦~~

          來源:blog.csdn.net/kisscatforever/article/

          details/79817039

          瀏覽 31
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆成人AV一二三区在线播放 | 欧美精品成人网站在线观看 | 欧美精品三级在线观看 | 久久夜精品视频 | 苏清歌训练营EP2 |