項(xiàng)目中進(jìn)行接口壓測,發(fā)現(xiàn)批量插入的速度有點(diǎn)超出預(yù)期,感覺很奇怪,經(jīng)過定位后發(fā)現(xiàn)mybatise-plus批量保存的處理十分緩慢,使用的是saveBatch方法,這點(diǎn)有點(diǎn)想不通。于是就進(jìn)行了相關(guān)內(nèi)容分析。
根據(jù)mybatise-plus中saveBatch的方法進(jìn)行源碼查看:
?
繼續(xù)跟蹤邏輯,從代碼上看,確實(shí)是一條條執(zhí)行了sqlSession.insert(sqlStatement, entity) 方法。
?繼續(xù)跟蹤,下面的consumer執(zhí)行的就是上面的sqlSession.insert方法:
具體執(zhí)行邏輯中是累計(jì)到 一定數(shù)量后,一批數(shù)據(jù)進(jìn)行flush。
其實(shí),從上述的代碼實(shí)現(xiàn)上看,整個(gè)實(shí)現(xiàn)機(jī)制跟我們預(yù)想的差不多,基本上是批量的實(shí)現(xiàn)思路。這種批量的處理肯定比一條條的insert要快。
但是,為什么還是如此的緩慢。
下面我們就進(jìn)行一個(gè)粗略的實(shí)驗(yàn),來對(duì)比一波。現(xiàn)在使用4種方式進(jìn)行比較:
1、批量數(shù)據(jù)單條執(zhí)行,調(diào)用myBatise方法save
2、批量執(zhí)行調(diào)用myBatise方法saveBatch
3、通過xml手寫sql批量插入
4、JDBC方式批量插入開始進(jìn)行實(shí)驗(yàn)
1、1000條數(shù)據(jù),一條條的插入
?
執(zhí)行結(jié)果為:
可以看到,執(zhí)行一批1000條點(diǎn)的數(shù)據(jù),耗費(fèi)時(shí)間為1173毫秒。
2、1000條數(shù)據(jù),使用mybatise-plus的saveBatch插入
執(zhí)行結(jié)果為:
?可以看到,本次總的耗時(shí)為289毫秒,比一條條的插入快了大約4倍,效率還是可以的。
3、通過xml手寫sql批量插入。
Xml中拼接內(nèi)容為:
Java代碼內(nèi)容為:
執(zhí)行程序看下性能如何:
本次耗時(shí)只有34毫秒,性能比saveBatch提高了7倍
4、JDBC方式批量插入開始進(jìn)行實(shí)驗(yàn)
執(zhí)行情況:
本次耗時(shí)142毫秒,
執(zhí)行效率比saveBatch要快,比手動(dòng)拼接方式要慢,
綜上所述,手動(dòng)拼接sql的方式是批量保存效率最佳。
5、結(jié)論
整個(gè)執(zhí)行結(jié)果跟預(yù)期的不一樣,這里我們直接說結(jié)論,因?yàn)閙ybatise-plus的saveBatch方法會(huì)繼續(xù)調(diào)用mysql驅(qū)動(dòng)中的實(shí)現(xiàn),
在Mysql的驅(qū)動(dòng)jar中,ClientPreparedStatement.java中executeBatchInternal()方法中
就是這個(gè)叫 rewriteBatchedStatements 的屬性,從名字來看是要重寫批操作的 Statement,前面batchHasPlainStatements 已經(jīng)是 false,取反肯定是 true,所以只要這參數(shù)是 true 就會(huì)進(jìn)行一波操作。
屬性默認(rèn)是 false。
可以直接將 jdbcurl 加上了這個(gè)參數(shù):
看下 executeBatchedInserts 究竟干了什么,在上面基礎(chǔ)上繼續(xù)執(zhí)行邏輯,
果然,sql語句倍rewrite了:
對(duì)于插入而言,所謂的rewrite其實(shí)就是將一批插入拼接成insert into XXX values(a),(b)…
這樣的一條語句形式后再執(zhí)行,這樣一來跟拼接sql的效果是一樣的。
那么,為什么默認(rèn)不給這個(gè)rewriteBatchedStatements屬性設(shè)置為true,
原來有如下原因:
看下 executeBatchedInserts 究竟干了什么:
1.???? 如果批量語句中的某些語句失敗,則默認(rèn)重寫會(huì)導(dǎo)致所有語句都失敗。
2.???? 批量語句的某些語句參數(shù)不一樣,則默認(rèn)重寫會(huì)使得查詢緩存未命中。
看起來影響不大,所以我給我的項(xiàng)目設(shè)置上了這個(gè)參數(shù)!
最后我稍微總結(jié)下粗略的對(duì)比:大家如果想要更準(zhǔn)確的實(shí)現(xiàn),可以自己進(jìn)行更多組數(shù)據(jù)測試:
以如果有使用 jdbc 的 Batch 性能方面的需求,要將 rewriteBatchedStatements 設(shè)置為 true,這樣能提高很多性能。
然后如果喜歡手動(dòng)拼接 sql 要注意一次拼接的數(shù)量,分批處理。
以上為全部內(nèi)容。
歡迎關(guān)注10W+的微信公眾號(hào):
技術(shù)難點(diǎn)歡迎咨詢,如有需要加我微信:1106915848。文章來源:http://www.zghlxwxcb.cn/news/detail-606178.html
星光不問趕路人,時(shí)光不負(fù)有心人文章來源地址http://www.zghlxwxcb.cn/news/detail-606178.html
到了這里,關(guān)于MyBatis批量插入數(shù)據(jù)優(yōu)化,增加一個(gè)參數(shù),效率提升百倍的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!