国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

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

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

3天內不再提示

如何調優MyBatis 25倍性能

jf_ro2CN3Fa ? 來源:芋道源碼 ? 2023-05-30 09:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

來源:yes的練級攻略
  • 粗略的實驗
  • 最后


最近在壓測一批接口,發現接口處理速度慢的有點超出預期,感覺很奇怪,后面定位發現是數據庫批量保存這塊很慢。

這個項目用的是 mybatis-plus,批量保存直接用的是 mybatis-plus 提供的 saveBatch。

我點進去看了下源碼,感覺有點不太對勁:

2ad185ce-fe8a-11ed-90ce-dac502259ad0.png

我繼續追蹤了下,從這個代碼來看,確實是 for 循環一條一條執行了 sqlSession.insert,下面的 consumer 執行的就是上面的 sqlSession.insert:

2adaae10-fe8a-11ed-90ce-dac502259ad0.png

然后累計一定數量后,一批 flush。

從這點來看,這個 saveBach 的性能肯定比直接一條一條 insert 快。

我直接進行一個粗略的實驗,簡單創建了一張表來對比一波!

粗略的實驗

1000條數據,一條一條插入

@Test
voidMybatisPlusSaveOne(){
SqlSessionsqlSession=sqlSessionFactory.openSession();
try{
StopWatchstopWatch=newStopWatch();
stopWatch.start("mybatisplussaveone");
for(inti=0;i1000;i++){
OpenTestopenTest=newOpenTest();
openTest.setA("a"+i);
openTest.setB("b"+i);
openTest.setC("c"+i);
openTest.setD("d"+i);
openTest.setE("e"+i);
openTest.setF("f"+i);
openTest.setG("g"+i);
openTest.setH("h"+i);
openTest.setI("i"+i);
openTest.setJ("j"+i);
openTest.setK("k"+i);
//一條一條插入
openTestService.save(openTest);
}
sqlSession.commit();
stopWatch.stop();
log.info("mybatis plus save one:"+stopWatch.getTotalTimeMillis());
}finally{
sqlSession.close();
}
}
2ae2c12c-fe8a-11ed-90ce-dac502259ad0.png

可以看到,執行一批 1000 條數的批量保存,耗費的時間是 121011 毫秒。

1000條數據用 mybatis-plus 自帶的 saveBatch 插入

@Test
voidMybatisPlusSaveBatch(){
SqlSessionsqlSession=sqlSessionFactory.openSession();
try{
ListopenTestList=newArrayList<>();
for(inti=0;i1000;i++){
OpenTestopenTest=newOpenTest();
openTest.setA("a"+i);
openTest.setB("b"+i);
openTest.setC("c"+i);
openTest.setD("d"+i);
openTest.setE("e"+i);
openTest.setF("f"+i);
openTest.setG("g"+i);
openTest.setH("h"+i);
openTest.setI("i"+i);
openTest.setJ("j"+i);
openTest.setK("k"+i);
openTestList.add(openTest);
}
StopWatchstopWatch=newStopWatch();
stopWatch.start("mybatisplussavebatch");
//批量插入
openTestService.saveBatch(openTestList);
sqlSession.commit();
stopWatch.stop();
log.info("mybatis plus save batch:"+stopWatch.getTotalTimeMillis());
}finally{
sqlSession.close();
}
}
2ae81f1e-fe8a-11ed-90ce-dac502259ad0.png

耗費的時間是 59927 毫秒,比一條一條插入快了一倍,從這點來看,效率還是可以的。

然后常見的還有一種利用拼接 sql 方式來實現批量插入,我們也來對比試試看性能如何。

1000條數據用手動拼接 sql 方式插入

搞個手動拼接:

2aef8592-fe8a-11ed-90ce-dac502259ad0.png來跑跑下性能如何:

@Test
voidMapperSaveBatch(){
SqlSessionsqlSession=sqlSessionFactory.openSession();
try{
ListopenTestList=newArrayList<>();
for(inti=0;i1000;i++){
OpenTestopenTest=newOpenTest();
openTest.setA("a"+i);
openTest.setB("b"+i);
openTest.setC("c"+i);
openTest.setD("d"+i);
openTest.setE("e"+i);
openTest.setF("f"+i);
openTest.setG("g"+i);
openTest.setH("h"+i);
openTest.setI("i"+i);
openTest.setJ("j"+i);
openTest.setK("k"+i);
openTestList.add(openTest);
}
StopWatchstopWatch=newStopWatch();
stopWatch.start("mappersavebatch");
//手動拼接批量插入
openTestMapper.saveBatch(openTestList);
sqlSession.commit();
stopWatch.stop();
log.info("mapper save batch:"+stopWatch.getTotalTimeMillis());
}finally{
sqlSession.close();
}
}
2af6df90-fe8a-11ed-90ce-dac502259ad0.png

耗時只有 2275 毫秒,性能比 mybatis-plus 自帶的 saveBatch 好了 26 倍!

這時,我又突然回想起以前直接用 JDBC 批量保存的接口,那都到這份上了,順帶也跑跑看!

1000條數據用 JDBC executeBatch 插入

@Test
voidJDBCSaveBatch()throwsSQLException{
SqlSessionsqlSession=sqlSessionFactory.openSession();
Connectionconnection=sqlSession.getConnection();
connection.setAutoCommit(false);

Stringsql="insertintoopen_test(a,b,c,d,e,f,g,h,i,j,k)values(?,?,?,?,?,?,?,?,?,?,?)";
PreparedStatementstatement=connection.prepareStatement(sql);
try{
for(inti=0;i1000;i++){
statement.setString(1,"a"+i);
statement.setString(2,"b"+i);
statement.setString(3,"c"+i);
statement.setString(4,"d"+i);
statement.setString(5,"e"+i);
statement.setString(6,"f"+i);
statement.setString(7,"g"+i);
statement.setString(8,"h"+i);
statement.setString(9,"i"+i);
statement.setString(10,"j"+i);
statement.setString(11,"k"+i);
statement.addBatch();
}
StopWatchstopWatch=newStopWatch();
stopWatch.start("JDBCsavebatch");
statement.executeBatch();
connection.commit();
stopWatch.stop();
log.info("JDBC save batch:"+stopWatch.getTotalTimeMillis());
}finally{
statement.close();
sqlSession.close();
}
}
2afea46e-fe8a-11ed-90ce-dac502259ad0.png

耗時是 55663 毫秒,所以 JDBC executeBatch 的性能跟 mybatis-plus 的 saveBatch 一樣(底層一樣)。

綜上所述,拼接 sql 的方式實現批量保存效率最佳。

但是我又不太甘心,總感覺應該有什么別的法子,然后我就繼續跟著 mybatis-plus 的源碼 debug 了一下,跟到了 mysql 的驅動,突然發現有個 if 里面的條件有點顯眼:

2b05fd7c-fe8a-11ed-90ce-dac502259ad0.png

就是這個叫 rewriteBatchedStatements 的玩意,從名字來看是要重寫批操作的 Statement,前面batchHasPlainStatements 已經是 false,取反肯定是 true,所以只要這參數是 true 就會進行一波操作。

我看了下默認是 false。

2b0cc0b2-fe8a-11ed-90ce-dac502259ad0.png

同時我也上網查了下 rewriteBatchedStatements 參數,好家伙,好像有用!我直接將 jdbcurl 加上了這個參數:

2b13cef2-fe8a-11ed-90ce-dac502259ad0.png

然后繼續跑了下 mybatis-plus 自帶的 saveBatch,果然性能大大提高,跟拼接 SQL 差不多!

2b1b2bac-fe8a-11ed-90ce-dac502259ad0.png

順帶我也跑了下 JDBC 的 executeBatch ,果然也提高了。

2b21ec58-fe8a-11ed-90ce-dac502259ad0.png

然后我繼續 debug ,來探探 rewriteBatchedStatements 究竟是怎么 rewrite 的!

如果這個參數是 true,則會執行下面的方法且直接返回:

2b30f07c-fe8a-11ed-90ce-dac502259ad0.png

看下 executeBatchedInserts 究竟干了什么:

2b37bbfa-fe8a-11ed-90ce-dac502259ad0.png

看到上面我圈出來的代碼沒,好像已經有點感覺了,繼續往下 debug。

果然!sql 語句被 rewrite了:

2b3e7e7c-fe8a-11ed-90ce-dac502259ad0.png

對插入而言,所謂的 rewrite 其實就是將一批插入拼接成 insert into xxx values (a),(b),(c)...這樣一條語句的形式然后執行,這樣一來跟拼接 sql 的效果是一樣的。

那為什么默認不給這個參數設置為 true 呢?

原來是這樣的:

  1. 如果批量語句中的某些語句失敗,則默認重寫會導致所有語句都失敗。
  2. 批量語句的某些語句參數不一樣,則默認重寫會使得查詢緩存未命中。

看起來影響不大,所以我給我的項目設置上了這個參數!

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

  • 項目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

最后

稍微總結下我粗略的對比(雖然粗略,但實驗結果符合原理層面的理解),如果你想更準確地實驗,可以使用JMH,并且測試更多組數(如 5000,10000等)的情況。

批量保存方式 數據量(條) 耗時(ms)
單條循環插入 1000 121011
mybatis-plus saveBatch 1000 59927
mybatis-plus saveBatch(添加rewtire參數) 1000 2589
手動拼接sql 1000 2275
jdbc executeBatch 1000 55663
jdbc executeBatch(添加rewtire參數) 1000 324

所以如果有使用 jdbc 的 Batch 性能方面的需求,要將 rewriteBatchedStatements 設置為 true,這樣能提高很多性能。

然后如果喜歡手動拼接 sql 要注意一次拼接的數量,分批處理。


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

    關注

    8

    文章

    685

    瀏覽量

    31317
  • 接口處理
    +關注

    關注

    0

    文章

    3

    瀏覽量

    6509
  • mybatis
    +關注

    關注

    0

    文章

    64

    瀏覽量

    7139

原文標題:調優 MyBatis 25 倍性能

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

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    解鎖Zephyr實時操作系統深度調能力

    可以說,代碼編寫只是項目開發的起點,而隨之而來的資源分析與性能調才是確保系統穩定可靠的關鍵環節。
    的頭像 發表于 01-30 09:16 ?5650次閱讀

    Linux系統內核參數調實戰指南

    Linux 內核參數調是系統性能優化的核心環節。隨著云原生架構的普及和硬件性能的飛速提升,默認的內核參數配置往往無法充分發揮系統潛力。在高并發 Web 服務、大數據處理、容器化部署等
    的頭像 發表于 01-28 14:27 ?426次閱讀

    性能測試調實戰與探索(存儲模型優化+調用鏈路分析)

    分析、流量分析、壓測實施和剖解調優等主要環節中,引發對于系統能力底盤夯實和測試策略改進的諸多思考。 在性能測試階段,剖析系統能力實現及調方案,探索更優解及性能測試策略的提升空間。 ?
    的頭像 發表于 01-12 14:46 ?1433次閱讀
    <b class='flag-5'>性能</b>測試<b class='flag-5'>調</b><b class='flag-5'>優</b>實戰與探索(存儲模型優化+調用鏈路分析)

    實戰RK3568性能調:如何利用迅為資料壓榨NPU潛能-在Android系統中使用NPU

    《實戰RK3568性能調:如何利用迅為資料壓榨NPU潛能-在Android系統中使用NPU》
    的頭像 發表于 11-07 13:42 ?642次閱讀
    實戰RK3568<b class='flag-5'>性能</b><b class='flag-5'>調</b><b class='flag-5'>優</b>:如何利用迅為資料壓榨NPU潛能-在Android系統中使用NPU

    天翼云基于開源歐拉的智能調實踐

    在數字經濟加速滲透的當下,操作系統作為底層基礎設施的核心,其穩定性與適配性直接關系到行業數字化進程。隨著CentOS停止維護,國內企業面臨操作系統遷移的緊迫需求,天翼云基于開源歐拉研發的CTyunOS,不僅成為這一遷移浪潮中的關鍵解決方案,更通過智能調實踐,為數字經濟筑
    的頭像 發表于 10-17 11:04 ?671次閱讀

    HarmonyOSAI編程智慧調

    DevEco Studio提供智慧調能力,支持通過自然語言交互,分析并解釋當前實例或項目中存在的性能問題,幫助開發者快速定位影響性能的具體原因。該功能從DevEco Studio 6
    發表于 09-01 15:15

    Linux服務器性能調的核心技巧和實戰經驗

    如果你正在為這些問題頭疼,那么這篇文章就是為你準備的!作為一名擁有10年經驗的運維工程師,我將毫無保留地分享Linux服務器性能調的核心技巧和實戰經驗。
    的頭像 發表于 08-27 14:36 ?1045次閱讀

    Linux性能監控與調技巧

    作為一名在一線摸爬滾打多年的運維工程師,我見過太多因為性能問題導致的線上故障。凌晨2點被告警電話吵醒,面對CPU飆升到100%、內存不足、磁盤IO瓶頸等問題時的那種焦慮,相信每個運維人都深有體會。
    的頭像 發表于 08-18 11:26 ?842次閱讀

    HarmonyOS AI輔助編程工具(CodeGenie)智慧調

    DevEco Studio提供智慧調能力,支持通過自然語言交互,分析并解釋當前實例或項目中存在的性能問題,幫助開發者快速定位影響性能的具體原因。該功能從DevEco Studio 6
    發表于 08-14 11:12

    Linux網絡性能調方案

    在當今高并發、大流量的互聯網環境下,網絡性能往往成為系統的瓶頸。作為一名資深運維工程師,我在生產環境中遇到過無數次因為TCP/IP參數配置不當導致的性能問題。今天分享一套完整的Linux網絡性能
    的頭像 發表于 08-06 18:01 ?1324次閱讀

    Linux內核參數調方案

    在高并發微服務環境中,網絡性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細化的Linux內核參數調,讓你的K8s節點網絡性能提升30%以上。
    的頭像 發表于 08-06 17:50 ?947次閱讀

    Linux系統性能調方案

    關鍵要點預覽:本文將深入解析Linux系統性能瓶頸的根本原因,提供可直接落地的調方案,讓你的系統性能提升30-50%!
    的頭像 發表于 08-06 17:49 ?874次閱讀

    MySQL配置調技巧

    上個月,我們公司的核心業務系統突然出現大面積超時,用戶投訴電話不斷。經過緊急排查,發現是MySQL服務器CPU飆升到99%,大量慢查詢堆積。通過一系列配置調和SQL優化,最終在30分鐘內恢復了服務。
    的頭像 發表于 07-31 10:27 ?607次閱讀

    Nginx在企業環境中的調策略

    Nginx作為現代互聯網架構中最重要的Web服務器和反向代理服務器,其性能調對企業級應用的穩定性和效率至關重要。本指南將從運維實踐角度出發,詳細介紹Nginx在企業環境中的各種調
    的頭像 發表于 07-14 11:13 ?629次閱讀

    手把手教你如何調Linux網絡參數

    在高并發網絡服務場景中,Linux內核的默認網絡參數往往無法滿足需求,導致性能瓶頸、連接超時甚至服務崩潰。本文基于真實案例分析,從參數解讀、問題診斷到優化實踐,手把手教你如何調Linux網絡參數,支撐百萬級并發連接。
    的頭像 發表于 05-29 09:21 ?964次閱讀