網站首頁 編程語言 正文
?? 背景介紹
在最近的開發過程中,遇到了往數據庫中表中插入大量的數據。有一個全國銀行各分行的信息,共計148032條數據
文件有8.45MB,因為考慮到數據量比較大,就想著導入到MySQL看一看需要多長時間。
?? 方案一:用 for語句循環插入(不推薦)
使用for循環語句將,將數據一條條插入。
insert into t_bank values (?, ?, ?, ?, ?)
/**
* 導入銀行信息
*
* @param bankList
* @return java.lang.String
*/
@Override
public String importBank(List<TBank> bankList) {
if (StringUtils.isNull(bankList) || bankList.size() == 0)
{
throw new CustomException("導入用戶數據不能為空!");
}
long start = System.currentTimeMillis();
for (int i = 0; i < bankList.size(); i++) {
tBankMapper.insertTBank(bankList.get(i));
}
long end = System.currentTimeMillis();
log.info("數據總耗時:" + (end-start) + "ms" );
return "Success";
}
優勢:JDBC 中的 PreparedStatement 有預編譯功能,預編譯之后會緩存起來。
之后SQL執行會比較快,且 JDBC可以開啟批處理,這個批處理執行非常給力。
劣勢:這種方式插入大量數據時,效率非常底下,不推薦。很多時候我們的 SQL 服務器和應用服務器可能并不是同一臺,所以必須要考慮網絡 IO。
如果網絡 IO 比較費時間的話,那么可能會拖慢 SQL 執行的速度。
?? 方案二:利用mybatis的foreach來實現循環插入(不推薦)
insert into t_bank values (?, ?, ?, ?, ?) , (?, ?, ?, ?, ?) , (?, ?, ?, ?, ?)
/**
* 導入銀行信息
*
* @param bankList
* @return java.lang.String
*/
@Override
public String importBank(List<TBank> bankList) {
if (StringUtils.isNull(bankList) || bankList.size() == 0)
{
throw new CustomException("導入用戶數據不能為空!");
}
long start = System.currentTimeMillis();
tBankMapper.batchInsert(bankList);
long end = System.currentTimeMillis();
log.info("數據總耗時:" + (end-start) + "ms" );
return "Success";
}
<insert id="batchInsert" parameterType="java.util.List">
insert into t_bank (
bank_id,
branch_name,
bank_code,
contact_line,
parent_id,
branch_province,
branch_province_name,
branch_city,
branch_city_name)
values
<foreach collection="list" item="item" separator=",">
(
#{item.bankId},
#{item.branchName},
#{item.bankCode},
#{item.contactLine},
#{item.parentId},
#{item.branchProvince},
#{item.branchProvinceName},
#{item.branchCity},
#{item.branchCityName})
</foreach>
</insert>
優勢:不用頻繁訪問數據庫,一條sql搞定,效率比較高。
劣勢:一當數據量太大時,會出現拼接的sql語句超長而執行失敗,所以當數據量太大時,也不推薦。
二是 SQL 太長了,甚至可能需要分片后批量處理。
三是無法充分發揮 PreparedStatement 預編譯的優勢,SQL 要重新解析且無法復用
?? 第三種方案,使用sqlSessionFactory實現批量插入(推薦)
@Resource
private SqlSessionFactory sqlSessionFactory;
/**
* 導入銀行信息
*
* @param bankList
* @param isUpdateSupport
* @return java.lang.String
* @author PuWenshuo
* @date 2023/9/18 11:32
*/
@Override
public String importBank(List<TBank> bankList, Boolean isUpdateSupport) {
if (StringUtils.isNull(bankList) || bankList.size() == 0)
{
throw new CustomException("導入用戶數據不能為空!");
}
String msg="";
long start = System.currentTimeMillis();
// 指定分頁大小
int pageSize = 1000; // 每批插入1000條數據
// 關閉session的自動提交
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
try {
TBankMapper bankMapper = sqlSession.getMapper(TBankMapper.class);
// 計算總頁數
int totalSize = bankList.size();
int totalPages = (int) Math.ceil((double) totalSize / pageSize);
for (int page = 1; page <= totalPages; page++) {
// 計算當前頁的起始和結束索引
int startIndex = (page - 1) * pageSize;
int endIndex = Math.min(startIndex + pageSize, totalSize);
// 獲取當前頁的數據
List<TBank> banks = bankList.subList(startIndex, endIndex);
// 批量插入數據
tBankMapper.batchInsert(banks);
// 提交事務
sqlSession.commit();
}
msg="恭喜您,數據已全部導入成功!";
} catch (Exception e) {
sqlSession.rollback();
log.error(e.getMessage());
msg="很抱歉,導入失敗!";
} finally {
sqlSession.close();
}
long end = System.currentTimeMillis();
log.info("數據總耗時:" + (end-start) + "ms" );
return msg;
}
優勢:這種方式可以說是集第一種和第二種方式的優點于一身,既可以提高運行效率,又可以保證大數據量時執行成功,大數據量時推薦使用這種方式。
原文鏈接:https://blog.csdn.net/qq_41596778/article/details/132990502
- 上一篇:沒有了
- 下一篇:沒有了
相關推薦
- 2022-04-10 Git常用命令介紹_其它綜合
- 2022-04-27 ASP.NET?Core中的策略授權和ABP授權_實用技巧
- 2021-12-15 Android中Intent組件的入門學習心得_Android
- 2023-05-08 淺談golang通道類型_Golang
- 2022-07-06 C#中DataSet,DataTable,DataView的區別與用法_C#教程
- 2022-12-09 Oracle遞歸查詢簡單示例_oracle
- 2022-04-12 安裝zsh&oh-my-zsh(沒有root權限)
- 2022-11-14 開發板NFS掛載方案
- 欄目分類
-
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支