inert和update在數據量龐大的情況下,速度非常慢,那怎么解決呢?可以用批量插入和批量更新
批量插入11萬條數據,如下圖
第一個圖數據庫已經有11萬的情況下測試,第二個圖數據庫已經有22萬的情況下測試
我的代碼是同時測試批量插入和批量更新,
Controller層
@Test public String sayHello(){ //獲取數據保存到List,紅色部分你們自己獲取數據 HelloController helloController=new HelloController(); long strMillis = System.currentTimeMillis(); List<LogisticsReturn> fileList = helloController.getFileList(); long endMillis = System.currentTimeMillis(); long time = endMillis - strMillis; //批量更新 strMillis = System.currentTimeMillis(); logisticsReturnService.saveAll(fileList); endMillis = System.currentTimeMillis(); long time2 = endMillis - strMillis; //批量修改 strMillis = System.currentTimeMillis(); logisticsReturnService.batchUpdate(fileList); endMillis = System.currentTimeMillis(); long time3 = endMillis - strMillis; System.out.println("解析使用時間:"+time); System.out.println("插入使用時間:"+time2); System.out.println("更新使用時間:"+time3); }
ServiceImpl層
@Service public class LogisticsReturnServiceImpl implements LogisticsReturnService { static Logger logger = LogManager.getLogger(LogisticsReturnServiceImpl .class); @Autowired SqlSessionTemplate sqlSessionTemplate; //將DAO注入Service層 @Autowired private LogisticsReturnMapper logisticsReturnMapper; @Override public void saveAll(List<LogisticsReturn> logisticsReturns) { SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); LogisticsReturnMapper dao = session.getMapper(LogisticsReturnMapper.class); int size = logisticsReturns.size(); try { for (int i = 0; i < size; i++) { dao.insert(logisticsReturns.get(i)); if (i % 10000 == 0 || i == size - 1) { //手動每10000個一提交,提交后無法回滾 session.commit(); //清理緩存,防止溢出 session.clearCache(); } } } catch (Exception e) { logger.error("批量保存失敗:" ,e); session.rollback(); } finally { session.close(); } } @Override public void batchUpdate(List<LogisticsReturn> logisticsReturns) { SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false); LogisticsReturnMapper dao = session.getMapper(LogisticsReturnMapper.class); int size = logisticsReturns.size(); try { List<LogisticsReturn> temp=new ArrayList<>(); for (int i = 0; i < size; i++) { temp.add(logisticsReturns.get(i)); if (i % 500 == 0 || i == size - 1) { //手動每500個一提交,提交后無法回滾 dao.updateBatch(temp); temp=new ArrayList<>(); session.commit(); //清理緩存,防止溢出 session.clearCache(); } } } catch (Exception e) { logger.error("批量更新失敗:" ,e); session.rollback(); } finally { session.close(); } } }
mybatis的SQL語句
<insert id="insert" parameterType="LogisticsReturn"> insert into [dbo].[LogisticsReturn] <trim prefix="(" suffix=")" suffixOverrides=","> <if test="guid != null and guid != ''">guid,</if> <if test="logisticsCode != null and logisticsCode != ''">logisticsCode,</if> <if test="logisticsNo != null and logisticsNo != ''">logisticsNo,</if> <if test="returnStatus != null and returnStatus != ''">returnStatus,</if> <if test="returnTime != null and returnTime != ''">returnTime,</if> <if test="returnInfo != null and returnInfo != ''">returnInfo,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="guid != null and guid != ''"> #{guid},</if> <if test="logisticsCode != null and logisticsCode != ''">#{logisticsCode},</if> <if test="logisticsNo != null and logisticsNo != ''"> #{logisticsNo},</if> <if test="returnStatus != null and returnStatus != ''">#{returnStatus},</if> <if test="returnTime != null and returnTime != ''"> #{returnTime},</if> <if test="returnInfo != null and returnInfo != ''">#{returnInfo},</if> </trim> </insert> <update id="updateBatch" parameterType="java.util.List"> update [dbo].[LogisticsReturn] <trim prefix="set" suffixOverrides=","> <trim prefix="returnInfo =case" suffix="end," > <foreach collection="list" item="i" index="index"> <if test="i.returnInfo!=null"> when( logisticsNo=#{i.logisticsNo} ) then #{i.returnInfo} </if> </foreach> </trim> </trim> where <foreach collection="logisticsReturns" separator="or" item="i" index="index" > logisticsNo=#{i.logisticsNo} </foreach> </update>
如果你不懂SQL的when then是什么,建議先看看這條語句
select ID,Username,namer=(case when(score<='50') then '實習' when(score>'50' and score<='500' ) then '赤腳醫生' when(score>'500' and score<='1000' ) then '村衛生員' when(score>'1000' and score<='1500' ) then '鄉衛生員' when(score>'1500' and score<='2000' ) then '鎮衛生員' when(score>'2000' and score<='3000' ) then '醫師' when(score>'3000' and score<='5000' ) then '主治醫師' when(score>'5000' and score<='10000' ) then '副主任醫師' when(score>'10000' and score<='20000' ) then '主任醫師' when(score>'20000' and score<='50000' ) then '健康大使' else '健康大使' end ), (SELECT count(id) FROM jk01_YiWen_Question WHERE UserID = dbo.jk01_Member.ID) as questionnum from jk01_Member
Batch速度比insert和update提升好幾倍,看完點個推薦看吧。