在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

MyBatis、JDBC等做大數據量數據插入的案例和結果

jf_ro2CN3Fa ? 來源:芋道源碼 ? 2023-05-22 11:23 ? 次閱讀

30萬條數據插入插入數據庫驗證

實體類、mapper和配置文件定義

不分批次直接梭哈

循環逐條插入

MyBatis實現插入30萬條數據

JDBC實現插入30萬條數據

總結

本文主要講述通過MyBatis、JDBC等做大數據量數據插入的案例和結果。

30萬條數據插入插入數據庫驗證

實體類、mapper和配置文件定義

User實體

mapper接口

mapper.xml文件

jdbc.properties

sqlMapConfig.xml

不分批次直接梭哈

循環逐條插入

MyBatis實現插入30萬條數據

JDBC實現插入30萬條數據

總結

驗證的數據庫表結構如下:

CREATETABLE`t_user`(
`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'用戶id',
`username`varchar(64)DEFAULTNULLCOMMENT'用戶名稱',
`age`int(4)DEFAULTNULLCOMMENT'年齡',
PRIMARYKEY(`id`)
)ENGINE=InnoDBDEFAULTCHARSET=utf8COMMENT='用戶信息表';

話不多說,開整!

基于 Spring Boot + MyBatis Plus + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/ruoyi-vue-pro

視頻教程:https://doc.iocoder.cn/video/

實體類、mapper和配置文件定義

User實體

/**
*

用戶實體

* *@Authorzjq */ @Data publicclassUser{ privateintid; privateStringusername; privateintage; }

mapper接口

publicinterfaceUserMapper{

/**
*批量插入用戶
*@paramuserList
*/
voidbatchInsertUser(@Param("list")ListuserList);


}

mapper.xml文件

 

insertintot_user(username,age)values

(
#{item.username},
#{item.age}
)


jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc//localhost:3306/test
jdbc.username=root
jdbc.password=root

sqlMapConfig.xml





 



 





 













 






基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的后臺管理系統 + 用戶小程序,支持 RBAC 動態權限、多租戶、數據權限、工作流、三方登錄、支付、短信、商城等功能

項目地址:https://github.com/YunaiV/yudao-cloud

視頻教程:https://doc.iocoder.cn/video/

不分批次直接梭哈

MyBatis直接一次性批量插入30萬條,代碼如下:

@Test
publicvoidtestBatchInsertUser()throwsIOException{
InputStreamresourceAsStream=
Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(resourceAsStream);
SqlSessionsession=sqlSessionFactory.openSession();
System.out.println("=====開始插入數據=====");
longstartTime=System.currentTimeMillis();
try{
ListuserList=newArrayList<>();
for(inti=1;i<=?300000;?i++)?{
????????????User?user?=?new?User();
????????????user.setId(i);
????????????user.setUsername("共飲一杯無?"?+?i);
????????????user.setAge((int)?(Math.random()?*?100));
????????????userList.add(user);
????????}
????????session.insert("batchInsertUser",?userList);?//?最后插入剩余的數據
????????session.commit();

????????long?spendTime?=?System.currentTimeMillis()-startTime;
????????System.out.println("成功插入?30?萬條數據,耗時:"+spendTime+"毫秒");
????}?finally?{
????????session.close();
????}
}

可以看到控制臺輸出:

Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (27759038 >yun 4194304). You can change this value on the server by setting the max_allowed_packet’ variable.

f8f021c6-f84b-11ed-90ce-dac502259ad0.png

超出最大數據包限制了,可以通過調整max_allowed_packet限制來提高可以傳輸的內容,不過由于30萬條數據超出太多,這個不可取,梭哈看來是不行了

既然梭哈不行那我們就一條一條循環著插入行不行呢

循環逐條插入

mapper接口和mapper文件中新增單個用戶新增的內容如下:

/**
*新增單個用戶
*@paramuser
*/
voidinsertUser(Useruser);


insertintot_user(username,age)values
(
#{username},
#{age}
)

調整執行代碼如下:

@Test
publicvoidtestCirculateInsertUser()throwsIOException{
InputStreamresourceAsStream=
Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(resourceAsStream);
SqlSessionsession=sqlSessionFactory.openSession();
System.out.println("=====開始插入數據=====");
longstartTime=System.currentTimeMillis();
try{
for(inti=1;i<=?300000;?i++)?{
????????????User?user?=?new?User();
????????????user.setId(i);
????????????user.setUsername("共飲一杯無?"?+?i);
????????????user.setAge((int)?(Math.random()?*?100));
????????????//?一條一條新增
????????????session.insert("insertUser",?user);
????????????session.commit();
????????}

????????long?spendTime?=?System.currentTimeMillis()-startTime;
????????System.out.println("成功插入?30?萬條數據,耗時:"+spendTime+"毫秒");
????}?finally?{
????????session.close();
????}
}

執行后可以發現磁盤IO占比飆升,一直處于高位。

f8faa088-f84b-11ed-90ce-dac502259ad0.png

等啊等等啊等,好久還沒執行完

f9025210-f84b-11ed-90ce-dac502259ad0.gif

先不管他了太慢了先搞其他的,等會再來看看結果吧。

two thousand year later …

控制臺輸出如下:

f910aa54-f84b-11ed-90ce-dac502259ad0.png

總共執行了14909367毫秒,換算出來是4小時八分鐘。太慢了。。

f91fc8cc-f84b-11ed-90ce-dac502259ad0.png

還是優化下之前的批處理方案吧

MyBatis實現插入30萬條數據

先清理表數據,然后優化批處理執行插入:

--清空用戶表
TRUNCATEtablet_user;

以下是通過 MyBatis 實現 30 萬條數據插入代碼實現:

/**
*分批次批量插入
*@throwsIOException
*/
@Test
publicvoidtestBatchInsertUser()throwsIOException{
InputStreamresourceAsStream=
Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(resourceAsStream);
SqlSessionsession=sqlSessionFactory.openSession();
System.out.println("=====開始插入數據=====");
longstartTime=System.currentTimeMillis();
intwaitTime=10;
try{
ListuserList=newArrayList<>();
for(inti=1;i<=?300000;?i++)?{
????????????User?user?=?new?User();
????????????user.setId(i);
????????????user.setUsername("共飲一杯無?"?+?i);
????????????user.setAge((int)?(Math.random()?*?100));
????????????userList.add(user);
????????????if?(i?%?1000?==?0)?{
????????????????session.insert("batchInsertUser",?userList);
????????????????//?每?1000?條數據提交一次事務
????????????????session.commit();
????????????????userList.clear();

????????????????//?等待一段時間
????????????????Thread.sleep(waitTime?*?1000);
????????????}
????????}
????????//?最后插入剩余的數據
????????if(!CollectionUtils.isEmpty(userList))?{
????????????session.insert("batchInsertUser",?userList);
????????????session.commit();
????????}

????????long?spendTime?=?System.currentTimeMillis()-startTime;
????????System.out.println("成功插入?30?萬條數據,耗時:"+spendTime+"毫秒");
????}?catch?(Exception?e)?{
????????e.printStackTrace();
????}?finally?{
????????session.close();
????}
}

使用了 MyBatis 的批處理操作,將每 1000 條數據放在一個批次中插入,能夠較為有效地提高插入速度。同時請注意在循環插入時要帶有合適的等待時間和批處理大小,以防止出現內存占用過高等問題。此外,還需要在配置文件中設置合理的連接池和數據庫的參數,以獲得更好的性能。

f92a15c0-f84b-11ed-90ce-dac502259ad0.png

在上面的示例中,我們每插入1000行數據就進行一次批處理提交,并等待10秒鐘。這有助于控制內存占用,并確保插入操作平穩進行。

f93242d6-f84b-11ed-90ce-dac502259ad0.png

五十分鐘執行完畢,時間主要用在了等待上。

如果低谷時期執行,CPU和磁盤性能又足夠的情況下,直接批處理不等待執行:

/**
*分批次批量插入
*@throwsIOException
*/
@Test
publicvoidtestBatchInsertUser()throwsIOException{
InputStreamresourceAsStream=
Resources.getResourceAsStream("sqlMapConfig.xml");
SqlSessionFactorysqlSessionFactory=newSqlSessionFactoryBuilder().build(resourceAsStream);
SqlSessionsession=sqlSessionFactory.openSession();
System.out.println("=====開始插入數據=====");
longstartTime=System.currentTimeMillis();
intwaitTime=10;
try{
ListuserList=newArrayList<>();
for(inti=1;i<=?300000;?i++)?{
????????????User?user?=?new?User();
????????????user.setId(i);
????????????user.setUsername("共飲一杯無?"?+?i);
????????????user.setAge((int)?(Math.random()?*?100));
????????????userList.add(user);
????????????if?(i?%?1000?==?0)?{
????????????????session.insert("batchInsertUser",?userList);
????????????????//?每?1000?條數據提交一次事務
????????????????session.commit();
????????????????userList.clear();
????????????}
????????}
????????//?最后插入剩余的數據
????????if(!CollectionUtils.isEmpty(userList))?{
????????????session.insert("batchInsertUser",?userList);
????????????session.commit();
????????}

????????long?spendTime?=?System.currentTimeMillis()-startTime;
????????System.out.println("成功插入?30?萬條數據,耗時:"+spendTime+"毫秒");
????}?catch?(Exception?e)?{
????????e.printStackTrace();
????}?finally?{
????????session.close();
????}
}

則24秒可以完成數據插入操作:

f93ea85a-f84b-11ed-90ce-dac502259ad0.png

f948bf16-f84b-11ed-90ce-dac502259ad0.png

可以看到短時CPU和磁盤占用會飆高。

把批處理的量再調大一些調到5000,在執行:

f95130ba-f84b-11ed-90ce-dac502259ad0.png

13秒插入成功30萬條,直接蕪湖起飛

JDBC實現插入30萬條數據

JDBC循環插入的話跟上面的mybatis逐條插入類似,不再贅述。

以下是 Java 使用 JDBC 批處理實現 30 萬條數據插入的示例代碼。請注意,該代碼僅提供思路,具體實現需根據實際情況進行修改。

/**
*JDBC分批次批量插入
*@throwsIOException
*/
@Test
publicvoidtestJDBCBatchInsertUser()throwsIOException{
Connectionconnection=null;
PreparedStatementpreparedStatement=null;

StringdatabaseURL="jdbc//localhost:3306/test";
Stringuser="root";
Stringpassword="root";

try{
connection=DriverManager.getConnection(databaseURL,user,password);
//關閉自動提交事務,改為手動提交
connection.setAutoCommit(false);
System.out.println("=====開始插入數據=====");
longstartTime=System.currentTimeMillis();
StringsqlInsert="INSERTINTOt_user(username,age)VALUES(?,?)";
preparedStatement=connection.prepareStatement(sqlInsert);

Randomrandom=newRandom();
for(inti=1;i<=?300000;?i++)?{
????????????preparedStatement.setString(1,?"共飲一杯無?"?+?i);
????????????preparedStatement.setInt(2,?random.nextInt(100));
????????????//?添加到批處理中
????????????preparedStatement.addBatch();

????????????if?(i?%?1000?==?0)?{
????????????????//?每1000條數據提交一次
????????????????preparedStatement.executeBatch();
????????????????connection.commit();
????????????????System.out.println("成功插入第?"+?i+"?條數據");
????????????}

????????}
????????//?處理剩余的數據
????????preparedStatement.executeBatch();
????????connection.commit();
????????long?spendTime?=?System.currentTimeMillis()-startTime;
????????System.out.println("成功插入?30?萬條數據,耗時:"+spendTime+"毫秒");
????}?catch?(SQLException?e)?{
????????System.out.println("Error:?"?+?e.getMessage());
????}?finally?{
????????if?(preparedStatement?!=?null)?{
????????????try?{
????????????????preparedStatement.close();
????????????}?catch?(SQLException?e)?{
????????????????e.printStackTrace();
????????????}
????????}

????????if?(connection?!=?null)?{
????????????try?{
????????????????connection.close();
????????????}?catch?(SQLException?e)?{
????????????????e.printStackTrace();
????????????}
????????}
????}
}
f95afca8-f84b-11ed-90ce-dac502259ad0.giff9631622-f84b-11ed-90ce-dac502259ad0.png

上述示例代碼中,我們通過 JDBC 連接 MySQL 數據庫,并執行批處理操作插入數據。具體實現步驟如下:

獲取數據庫連接。

創建 Statement 對象。

定義 SQL 語句,使用 PreparedStatement 對象預編譯 SQL 語句并設置參數。

執行批處理操作。

處理剩余的數據。

關閉 Statement 和 Connection 對象。

使用setAutoCommit(false) 來禁止自動提交事務,然后在每次批量插入之后手動提交事務。每次插入數據時都新建一個 PreparedStatement 對象以避免狀態不一致問題。在插入數據的循環中,每 10000 條數據就執行一次 executeBatch() 插入數據。

另外,需要根據實際情況優化連接池和數據庫的相關配置,以防止連接超時等問題。

總結

實現高效的大量數據插入需要結合以下優化策略(建議綜合使用):

1.批處理: 批量提交SQL語句可以降低網絡傳輸和處理開銷,減少與數據庫交互的次數。在Java中可以使用Statement或者PreparedStatement的addBatch()方法來添加多個SQL語句,然后一次性執行executeBatch()方法提交批處理的SQL語句。

在循環插入時帶有適當的等待時間和批處理大小,從而避免內存占用過高等問題:

設置適當的批處理大小:批處理大小指在一次插入操作中插入多少行數據。如果批處理大小太小,插入操作的頻率將很高,而如果批處理大小太大,可能會導致內存占用過高。通常,建議將批處理大小設置為1000-5000行,這將減少插入操作的頻率并降低內存占用。

采用適當的等待時間:等待時間指在批處理操作之間等待的時間量。等待時間過短可能會導致內存占用過高,而等待時間過長則可能會延遲插入操作的速度。通常,建議將等待時間設置為幾秒鐘到幾十秒鐘之間,這將使操作變得平滑且避免出現內存占用過高等問題。

可以考慮使用一些內存優化的技巧,例如使用內存數據庫或使用游標方式插入數據,以減少內存占用。

總的來說,選擇適當的批處理大小和等待時間可以幫助您平穩地進行插入操作,避免出現內存占用過高等問題。

2.索引: 在大量數據插入前暫時去掉索引,最后再打上,這樣可以大大減少寫入時候的更新索引的時間。

3.數據庫連接池: 使用數據庫連接池可以減少數據庫連接建立和關閉的開銷,提高性能。在沒有使用數據庫連接池的情況,記得在finally中關閉相關連接。

數據庫參數調整:增加MySQL數據庫緩沖區大小、配置高性能的磁盤和I/O等。

審核編輯:彭靜
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 接口
    +關注

    關注

    33

    文章

    8598

    瀏覽量

    151157
  • 大數據
    +關注

    關注

    64

    文章

    8889

    瀏覽量

    137442
  • mybatis
    +關注

    關注

    0

    文章

    60

    瀏覽量

    6713

原文標題:高效方案:30萬條數據插入 MySQL 僅需13秒

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    貴州數據寶:做大數據行業的“淘寶”

    ``公司簡介數據寶核心優勢 選擇數據寶選擇合作共贏數據寶公司目前得到各大官方媒體的密切關注。貴州日報報道—數據寶要做大數據行業的“支付寶”
    發表于 07-04 11:41

    大數據運用的技術

    大數據是對海量數據進行存儲、計算、統計、分析處理的一系列處理手段,處理的數據量通常是TB級,甚至是PB或EB級的數據,這是傳統數據處理手段所
    發表于 04-08 16:50

    大數據專業技術學習之大數據處理流程

    集中的大型分布式數據庫 或者分布式存儲集群,利用分布式技術來對存儲于其內的集中的海量數據進行普通的查詢和分類匯總,以此滿足大多數常見的分析需求。特點和挑戰:導入數據量大,查詢涉及的
    發表于 06-11 16:41

    VLFFT加入PCIE實現大數據量計算

    我買了一個研華的8681E開發板,核心用的是C6678,我想使用PCIE接口,結合VLFFT程序,實現持續的大數據量的FFT變換,但是我不知道如何在VLFFT程序的基礎上進行修改,加入PCIE的傳輸
    發表于 06-19 06:11

    我的LWIP write發送大數據量就卡死該怎么辦?

    目前在做httpserver,發現發送小數據時沒有問題,但當發送大數據量時,發現write函數,無法返回,一路跟蹤下來發現卡死在u32_t sys_arch_sem_wait(sys_sem_t
    發表于 07-16 22:28

    stm32f405+lwip+enc28j60+TCPModbus大數據量頻繁收發主動斷開連接

    單片機作為服務器,PC作為客戶端,通過上位機讀取單片機flash中的數據,遵從TCPModbus協議。現在就是頻繁大數據量收發會導致服務器主動斷開連接,然后客戶端就連不上了,也ping不通,希望各位大神幫忙分析一下,或者給個排查問題的思路。
    發表于 03-18 04:35

    mybatis支持數據庫輕兼容的輕方案

    一個輕的方案, 令mybatis支持數據庫輕兼容
    發表于 04-09 17:44

    大數據與物聯網如何相互協作

    來源:互聯網隨著物聯網不斷的發展的趨于成熟期,我們同時也收集了更多的信息數據,其實就是所謂的大數據。換個說法,也就是說物聯網和大數據可以互相協作。據統計《福布斯》預測,到2025年,生成的數據
    發表于 10-22 06:01

    數據量大、分析急,該用什么軟件做數據分析?

    數據量大,現在的軟件分析效率太低,操作也麻煩,有沒有更適合的數據分析軟件?或許BI數據分析軟件會是個好選擇。奧威軟件旗下的OurwayBI就是一款專做大數據可視分析的軟件,能在極短時間
    發表于 12-29 11:33

    怎樣去解決HAL庫在大數據量頻繁收發時出現串口接收失效的問題

    HAL庫在大數據量頻繁收發時為什么會出現串口接收失效呢?怎樣去解決HAL庫在大數據量頻繁收發時出現串口接收失效的問題?
    發表于 12-08 07:53

    基于數字廣播的大數據量接收與存儲策略

    數字廣播嵌入式終端在接收大數據量的廣播信息時受限于軟件處理速度,數據因不能得到及時處理而造成丟包,大量數據動態存儲時的頻繁申請易產生內存碎片,影響系統運行速度
    發表于 04-09 08:44 ?36次下載

    jdbcmybatis的區別

    MyBatis 是一款優秀的持久層框架,它支持定制化 SQL、存儲過程以及高級映射。MyBatis 避免了幾乎所有的 JDBC 代碼和手動設置參數以及獲取結果集。
    發表于 02-02 17:43 ?1.1w次閱讀
    <b class='flag-5'>jdbc</b>與<b class='flag-5'>mybatis</b>的區別

    MyBatis的實現原理

    本文主要詳細介紹了MyBatis的實現原理。mybatis底層還是采用原生jdbc來對數據庫進行操作的,只是通過 SqlSessionFactory,SqlSession Execut
    的頭像 發表于 02-24 11:25 ?6490次閱讀
    <b class='flag-5'>MyBatis</b>的實現原理

    MyBatis Plus解決大數據量查詢慢問題

    在實際工作中當指定查詢數據過大時,我們一般使用分頁查詢的方式一頁一頁的將數據放到內存處理。但有些情況不需要分頁的方式查詢數據或分很大一頁查詢數據時,如果一下子將
    的頭像 發表于 01-16 10:17 ?1879次閱讀

    藍牙Mesh模塊多跳大數據量高帶寬傳輸數據方法

    通過多個跳數進行通信,從而實現大范圍的覆蓋。然而,隨著數據量的增加和帶寬需求的提高,如何在藍牙Mesh網絡中實現高效、穩定的多跳大數據量高帶寬傳輸數據成為了一個亟待解決的問題。本文將介紹一種基于藍牙Mesh模塊的多跳
    的頭像 發表于 05-28 11:23 ?757次閱讀
    藍牙Mesh模塊多跳<b class='flag-5'>大數據量</b>高帶寬傳輸<b class='flag-5'>數據</b>方法
    主站蜘蛛池模板: 日本不卡视频| 222.www免费观看| 一级网站在线观看| 中文天堂最新版www官网在线| 韩国午夜精品理论片西瓜| 91精品国产亚洲爽啪在线影院| 女同性大尺度床戏视频| 日韩毛片大全| 国产主播精品在线| 亚洲久久在线| 在线免费看黄视频| 日本最好的免费影院| 小优视频在线| 色婷婷九月| 欧美成人精品| 1000部啪啪| 中文字幕一区二区三区精彩视频 | 国产伦精品一区二区三区女| 丁香六月激情网| 性色aⅴ闺蜜一区二区三区| 三级电影在线观看视频| 国外精品视频在线观看免费| 国产香蕉98碰碰久久人人| 一级片aaa| 久久精品亚洲一级毛片| 天天射天天拍| 乱轮黄色小说| 青草青青视频| 欧美一级视频在线高清观看| 亚洲国产一区二区在线| 欧美一级高清片在线| 午夜痒痒网| 91大神在线免费观看| 日本大黄视频| 天天做天天爱天天爽综合网| 黄视频免费在线看| 国产精品一区二区综合| 国产精品嫩草影院人体模特| 四虎永久免费地址| 岛国三级在线看| 欧美精品激情|