解決spring?data?jpa?saveAll()?保存過慢問題
spring data jpa saveAll() 保存過慢
問題發(fā)現(xiàn)
今天在生產(chǎn)環(huán)境執(zhí)行保存數(shù)據(jù)時 影響隊列中其他程序的運行 隨后加日志排查 發(fā)現(xiàn) 執(zhí)行 4500條 insert操作時 耗時 9分鐘 我類個去…
解決方案1 此方案在第二天失效了
廢話不多說 直接上配置文件參數(shù)
application-prod.yml 部分參數(shù)如下
jpa:
show-sql: false
hibernate:
ddl-auto: none
properties:
hibernate:
jdbc:
#為spring data jpa saveAll方法提供批量插入操作 此處可以隨時更改大小 建議500哦
batch_size: 500
batch_versioned_data: true
order_inserts: true
通過日志打印 執(zhí)行結(jié)果如下
未開批處理 4507條 耗時: 227167ms
開啟批處理 500/次 4507條 耗時: 29140ms
開啟批處理 1000/次 4507條 耗時: 29631ms
以上方案有問題,下面附上徹底解決的截圖和記錄
后來發(fā)現(xiàn)在生產(chǎn)運行了一天 還是會導(dǎo)致保存阻塞的問題 100條保存耗時 9分鐘!!!
數(shù)據(jù)庫此時數(shù)據(jù)有300w條
于是分析 saveAll()的源代碼


原來這個保存的時候 會去數(shù)據(jù)庫查詢這條數(shù)據(jù)是否存在 如果存在 則修改 不存在則直接添加 如下圖

重寫 saveAll() 的方法 就是仿照它 for循環(huán)里面直接調(diào)用 save()方法
@PersistenceContext() protected EntityManager em;

此處你們可以改成泛型的方式,提取公共類,封裝一下即可。
JPA的saveAll方法執(zhí)行效率很差
springboot項目中使用了SpringDataJpa的技術(shù),很方便,省了很多dao層繁瑣的步驟,但是有一個接口需要批量更新或者插入,數(shù)據(jù)量挺大,大概1-2w條,每條記錄20-30個字段吧,對于剛工作不久的我還是比較大的。我開始使用的saveAll(),因為本地單元測試,也沒考慮那么多(其實更早期更蠢,遍歷再save,壓根不去考慮數(shù)據(jù)庫連接池的壓力或者說每次遍歷都要去連接數(shù)據(jù)庫的時間損耗…),但是客戶壓力測試,我的接口就拉胯了。接口等待時間太久…誒
剛開始的思路想解決saveAll方法為什么這么慢的問題,因為saveAll是有則更新,無則新增,所以每條記錄都要去比對該記錄是否存在表中,效率比較差(我以后還是用JPA去適應(yīng)數(shù)據(jù)量較小的吧,jpa可能還有什么別的路子后面可以配置進去也行)。
最后改用了mybatis的foreach方式,雖然比較老套而且肯定不是最快的辦法,但是還是實用。
使用過程中,出現(xiàn)了這個報錯:
Packet for query is too large (3227 > 1024). You can change this value on the server by setting the max_allowed_packet' variable.
應(yīng)該是一下子丟進來的數(shù)據(jù)太大,超過了mysql的限制,有人說通過修改數(shù)據(jù)庫的max_allowed_packet這個屬性來修改,不過我這里是jenkins部署的服務(wù)器,能操作到數(shù)據(jù)庫的只有navicat這個可視化工具,如果使用命令行修改這個屬性,好像只能暫時起效。我只好類似分頁,把18000條數(shù)據(jù)按照2000一次批量操作,分成9次,這樣既不會報錯,也會比savelAll快一些。后續(xù)再研究一下更快更高效的方法。
數(shù)據(jù)庫配置加上allowMultiQueries=true才會支持foreach循環(huán)操作。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MybatisPlus多條件?or()的使用問題小結(jié)
這篇文章主要介紹了MybatisPlus多條件?or()的使用問題小結(jié),本文給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧2024-05-05
使用Java實現(xiàn)文件流轉(zhuǎn)base64
這篇文章主要為大家詳細介紹了如何使用Java實現(xiàn)文件流轉(zhuǎn)base64效果,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-03-03
idea創(chuàng)建SpringBoot自動創(chuàng)建Lombok無效果的問題解決方案
這篇文章主要介紹了idea創(chuàng)建SpringBoot自動創(chuàng)建Lombok無效果的問題解決方案,感興趣的朋友跟隨小編一起看看吧2024-12-12

