MyBatis-Plus的saveBatch批量插入為何效率很低耗時長詳解及解決方案

1、分析

參考:https://huaweicloud.csdn.net/63355e78d3efff3090b54618.html

(1)MySQL數(shù)據(jù)庫

針對MySQL數(shù)據(jù)庫saveBatch批量插入效率比較低登下,是比較好解決的茫孔,一般都是由于數(shù)據(jù)庫連接url上沒有配置批量操作的屬性叮喳,只需要在url上加上如下屬性即可:

rewriteBatchedStatements=true

即類似如下:
jdbc:mysql://數(shù)據(jù)庫地址/數(shù)據(jù)庫名?useUnicode=true&characterEncoding=UTF8&allowMultiQueries=true&rewriteBatchedStatements=true

加上之后,你就會發(fā)現(xiàn)缰贝,saveBatch的速度直線提升馍悟,效果還是很不錯的,一萬條數(shù)據(jù)估計也就在幾百毫秒剩晴。

(2)Oracle數(shù)據(jù)庫

Oracle數(shù)據(jù)庫的問題就比較大了锣咒,而且至今潘老師也沒找到一個比較完美的解決方案,此次寫這篇博客也正是由于Oracle數(shù)據(jù)庫saveBatch效率賊低引起的李破,先看下圖宠哄,批量插入一萬條數(shù)據(jù)(MyBatis-Plus的saveBatch默認(rèn)一次1000條,1w條會分10次嗤攻,當(dāng)然你也可以設(shè)置Batch Size)毛嫉,耗時竟然達到10s多,簡直不能忍啊妇菱,堪比龜速承粤!

image.png

于是就開始各種排查,經(jīng)過一番仔細debug闯团、翻源碼辛臊,反復(fù)測試對比驗證,最終發(fā)現(xiàn)是因為MyBatis-Plus的針對Oracle主鍵序列生成策略導(dǎo)致的房交,在上圖打印的日志可以看出彻舰,在每次打印參數(shù)之前,都會先執(zhí)行下SELECT XXX.NEXTVAL FROM DUAL候味,這是我們在實體Entity上加上了MyBatis-Plus的注解@KeySequence(value = “XXX”)引起的刃唤,本來預(yù)想的1萬條只需要和數(shù)據(jù)庫交互10次就解決了,現(xiàn)在看打印日志情況白群,預(yù)估是insert和查詢序列合計預(yù)計2萬次交互尚胞,于是,測試了下去掉@KeySequence注解帜慢,手工給id賦好值笼裳,再次批量保存1萬條,結(jié)果如下:


image.png

好家伙粱玲,直接干到1s多點躬柬,整整節(jié)約了10倍的時間,病根終于確定了抽减,就是@KeySequence注解導(dǎo)致的允青。

但你這就想把鍋甩給MyBatis-Plus那就大錯特錯了,這鍋歸根到底其實還是MyBatis的胯甩,為什么呢昧廷?經(jīng)過潘老師一番深入探查,發(fā)現(xiàn)正如MyBatis-Plus官方所說偎箫,只對MyBatis做擴展卻不改變木柬,做一對快樂的好基友,@KeySequence(value = “XXX”)作用就是結(jié)合KeyGenerator來實現(xiàn)自動化生成主鍵并回填淹办,但是MyBatis-Plus的所有KeyGenerator也是從MyBatis繼承擴展而來眉枕,而使用了之后,對于Oracle而言就相當(dāng)于在insert語句前加上了selectKey語句怜森,類似如下:

<selectKey keyColumn="id" keyProperty="id" resultType="int" order="BEFORE">
select XXX.nextval from dual
</selectKey>

這是不是很熟悉速挑,就是我們學(xué)MyBatis時候?qū)W的啊,MyBatis-Plus只不過是把它變成了@KeySequence注解副硅,省去了你寫這段xml了而已姥宝,而所有問題的源頭就來自于這段xml,潘老師親自測試恐疲,在insert前加上這段xml后使用Mybatis原生的SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH)批量插入腊满,發(fā)現(xiàn)批量插入無效,耗時和MyBatis-plus差不多培己,1w條大概10多秒碳蛋,但是一旦去掉這段xml,再使用原生的Batch插入省咨,我的天肃弟,竟然只要500多毫秒,也就是0.5秒零蓉,這差距在20倍左右笤受,一直以為是MyBatis-Plus的鍋,原來是MyBatis的鍋壁公,這下舒服了感论,可以安心地用MyBatis-Plus了,除非你不用mybatis了~


image.png

2紊册、修改
xml中sql都是由MyBatis-Plus動態(tài)幫我們生成的比肄,包括id為insert的,經(jīng)過測試發(fā)現(xiàn)囊陡,如果我們在xml中自己再新定義一個id為insert的sql語句(注意id必須為insert)芳绩,就將原來的默認(rèn)生成的覆蓋掉了,直接使用我們自己定義的撞反,那么問題就迎刃而解了妥色,具體如下:
a)去掉KeyGenerator實體對象的配置
b)去掉@KeySequence注解
c)id-type: 設(shè)置為AUTO
d)在實體對應(yīng)的xml新增id為insert的sql,類似如下:

<insert id="insert" parameterType="user">
insert into t_user(id, username, password)
values(SEQ_USER.NEXTVAL,#{username},#{password})
</insert>

e)繼續(xù)調(diào)用MyBatis-Plus的saveBatch或save遏片,都會走我們寫的這個insert對應(yīng)的xml
f)測試后1w條大概在幾百毫秒嘹害。

3撮竿、優(yōu)化
(1)主鍵生成策略
IdType.AUTO:表示主鍵自增,適用于數(shù)據(jù)庫支持的自增主鍵笔呀,如 MySQL 的 AUTO_INCREMENT幢踏。
IdType.ASSIGN_ID:使用雪花算法(Snowflake Algorithm)生成主鍵。
IdType.ASSIGN_UUID:生成一個不包含中劃線的 UUID 作為主鍵许师。
IdType.INPUT:表示主鍵值需要手動輸入或設(shè)置房蝉。
參考SEQ_USER.NEXTVAL類似的思路,實際實現(xiàn)的時候微渠,對IdType.ASSIGN_ID進行擴展搭幻,從數(shù)據(jù)庫進行序列化獲取值。在并發(fā)量較大的情況下逞盆,該序列的獲取也是一個瓶頸檀蹋。分析發(fā)現(xiàn)獲取是每次獲取一條,后續(xù)優(yōu)化獲取可以按照遞增的數(shù)量來批量獲取云芦,并在實體組裝的時候续扔,通過單獨調(diào)用批量獲取序號組裝參數(shù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末焕数,一起剝皮案震驚了整個濱河市纱昧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌堡赔,老刑警劉巖识脆,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異善已,居然都是意外死亡灼捂,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門换团,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悉稠,“玉大人,你說我怎么就攤上這事艘包〉拿停” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵想虎,是天一觀的道長卦尊。 經(jīng)常有香客問我,道長舌厨,這世上最難降的妖魔是什么岂却? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上躏哩,老公的妹妹穿的比我還像新娘署浩。我一直安慰自己,他們只是感情好扫尺,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布瑰抵。 她就那樣靜靜地躺著,像睡著了一般器联。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婿崭,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天拨拓,我揣著相機與錄音,去河邊找鬼氓栈。 笑死渣磷,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的授瘦。 我是一名探鬼主播醋界,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼提完!你這毒婦竟也來了形纺?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤徒欣,失蹤者是張志新(化名)和其女友劉穎逐样,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體打肝,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡脂新,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了粗梭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片争便。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖断医,靈堂內(nèi)的尸體忽然破棺而出滞乙,到底是詐尸還是另有隱情,我是刑警寧澤鉴嗤,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布酷宵,位于F島的核電站,受9級特大地震影響躬窜,放射性物質(zhì)發(fā)生泄漏浇垦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一荣挨、第九天 我趴在偏房一處隱蔽的房頂上張望男韧。 院中可真熱鬧朴摊,春花似錦、人聲如沸此虑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽朦前。三九已至介杆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間韭寸,已是汗流浹背春哨。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留恩伺,地道東北人赴背。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像晶渠,于是被迫代替她去往敵國和親凰荚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容