處理記錄
借鑒文章地址:https://www.imooc.com/article/321536
采用方案:for 循環(huán)循環(huán)插入
JDBC 中的 PreparedStatement 有預(yù)編譯功能呛每,預(yù)編譯之后會緩存起來,后面的 SQL 執(zhí)行會比較快并且 JDBC 可以開啟批處理哨鸭,這個批處理執(zhí)行非常快。
具體步驟:
1.設(shè)置MySQL批量執(zhí)行
MySQL JDBC 驅(qū)動在默認(rèn)情況下會無視 executeBatch() 語句窥翩,把我們期望批量執(zhí)行的一組 sql 語句拆散如孝,一條一條地發(fā)給 MySQL 數(shù)據(jù)庫充蓝,批量插入實際上是單條插入岁诉,直接造成較低的性能锚沸。將 rewriteBatchedStatements 參數(shù)置為 true, 數(shù)據(jù)庫驅(qū)動才會幫我們批量執(zhí)行 SQL。
image.png
2.開啟批處理 ExecutorType.BATCH
@Transactional(rollbackFor = Exception.class)
public List<StudentBatchImportDto> studentBatchImport(List<StudentBatchImportDto> read, Map collects, Map map) {
//如果自動提交設(shè)置為true,將無法控制提交的條數(shù)唉侄,改為最后統(tǒng)一提交咒吐。
SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);
MicroApplicationMapper sessionMapper = session.getMapper(MicroApplicationMapper.class);
Date date = new Date();
String pwd = passwordEncoder.encode(DEFAULT_PASSWORD);
//用來裝重復(fù)數(shù)據(jù)
List<StudentBatchImportDto> list = new ArrayList<>();
int dateSize = read.size();
int i =1;
for (StudentBatchImportDto studentBatchImportDto : read) {
//如果身份證已存在則不導(dǎo)入
String ifExit = (String)collects.get(studentBatchImportDto.getIdCard());
if(!StringUtils.isEmpty(ifExit)){//判斷當(dāng)前身份證是否在數(shù)據(jù)庫存在
list.add(studentBatchImportDto);
}else {
//插入表t_user
studentBatchImportDto.setPwd(pwd);
studentBatchImportDto.setDate(date);
sessionMapper.insertStudentSource(studentBatchImportDto);
if(i % size ==0){ //防止內(nèi)存溢出野建,分批提交
session.commit();
}
i++;
}
}
session.commit();
return list;
}
雖然是一條一條的插入属划,但是開啟了批處理模式(BATCH),這樣前前后后就只用這一個 SqlSession候生。節(jié)約了反反復(fù)復(fù)獲取 Connection 以及釋放 Connection 得大量時間同眯。
最后插入15000大概2.6M得數(shù)據(jù)大概花了1-2秒左右得時間。