<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>

          給你 2 萬條數(shù)據(jù),怎么快速導入到 MySQL?寫得太好了!

          共 9764字,需瀏覽 20分鐘

           ·

          2022-04-07 14:59

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

          一、前言

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

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

          下面就展示一下過程。

          二、直接把list懟進Mysql

          使用mybatis的批量導入操作:

          @Transactional(rollbackFor?=?Exception.class)
          public?int?addFreshStudentsNew2(List?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è)置為考生號
          ????????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;
          }

          推薦一個 Spring Boot 基礎(chǔ)教程及實戰(zhàn)示例:

          https://github.com/javastacks/spring-boot-best-practice


          Mapper.xml

          "insertAll"?parameterType="com.dmsdbj.itoo.basicInfo.entity.EnrollStudentEntity">
          ????insert?into?tb_enroll_student
          ????"("?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????????????????
          ????values
          ????"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()????????
          ????)???
          ????????????????????
          ?

          代碼說明:

          底層的mapper是通過逆向工程來生成的,批量插入如下,是拼接成類似:insert into tb_enroll_student()values (),()…….();

          關(guān)注Java項目精選,推送更多 Java 干貨!

          這樣的缺點是,數(shù)據(jù)庫一般有一個默認的設(shè)置,就是每次sql操作的數(shù)據(jù)不能超過4M。這樣插入,數(shù)據(jù)多的時候,數(shù)據(jù)庫會報錯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,默認大小4194304 也就是4M

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

          完成本次操作,但是我們不能保證項目單次最大的大小是多少,這樣是有弊端的。所以可以考慮進行分組導入。

          三、分組把list導入Mysql中

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

          @Transactional(rollbackFor?=?Exception.class)
          public?int?addFreshStudentsNew2(List?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è)置為考生號
          ????????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的批量導入,不同的是,根據(jù)線程數(shù)目進行分組,然后再建立多線程池,進行導入。

          @Transactional(rollbackFor?=?Exception.class)
          public?int?addFreshStudentsNew(List?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è)置為考生號
          ????????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ù)目進行分組,批量依次導入。一方面可以緩解數(shù)據(jù)庫的壓力,另一個面線程數(shù)目多了,一定程度會提高程序運行的時間。

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

          五、小結(jié)

          通過使用這個操作真是不斷的提高了,項目使用技巧也是不錯。

          加油~~ 多線程哦~~

          如有文章對你有幫助,

          在看”和轉(zhuǎn)發(fā)是對我最大的支持!

          暫時開放微信大號,好友位不多,需要的小伙伴們可以加,朋友圈和交流群里會發(fā)一些學習資料、個人見解、白嫖課程等等。

          掃描下方二維碼即可加我微信啦,2022,抱團取暖,一起牛逼。

          瀏覽 32
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  亚洲精品在线视频 | 久久成人免费91影片 | 日韩高清无码三级片 | www.色老板最新地址 | 久久无码一区二区三区 |