server多笔记录拼接字符串 sql_Java拼接“1亿行字符串”你会遇到什么问题?
拼接“1億行字符串”你會遇到什么問題?
本文將涉及到的三方面的內容,如下:
1,一個10萬次的for循環,4種實現的性能對比
2,直接將For循環改為1億次,遇到的問題
3,拓展
00. 需求
原計劃是生成1億條模擬數據,詳細的需求如下:
創建1億條Insert SQL語句,例如:INSERT INTO products (`id`,`code`) value (1, '000000000');其中,id 類型為INT(11)code 類型為VARCHAR(9),值區間00000000-99999999,長度不足9位的在前面補充0使其長度滿足9位。01. 一個10萬次的for循環,4種實現的性能對比
最終目的是1億,但是會涉及到時間消耗問題,所以計劃先從10萬行數據開始查看一下實現方式上的效率對別。決定使用方式之后將數據量升級到1億行最終實現需求。
選擇了日常代碼中經常見到的4種方式實現方式:
1, 使用 “+” 來拼接字符串; 2,使用StringBuffer | StringBuilder來拼接字符串; 3,使用String.formate() 來格式化字符串,并用 “+” 拼接字符串; 4,使用String.formate() 來格式化字符串,并用 StringBuffer | StringBuilder 拼接字符串;在10萬數據時候當前場景它們各自的執行效率如何呢,下面是統計后的對比
代碼結構如下:
對代碼感興趣同學可以看 這里;
整體性能的對比結果很顯然:
StringBuilder > "+"拼接 > String.formate()
使用 “+” 拼接字符串,雖然底層的實現使用StringBuilder做了優化,并不是直接用 “+” 拼接 直接代替StringBuilder那么簡單。
一次 “+”字符串拼接,相當于執行
new StringBuilder(str).append(newStr).toString();例如:
String name = "P" + "a" + "g" + "e";相當于
String name = new StringBuilder(new StringBuilder(new StringBuilder("P").append("a").toString()).append("g").toString()).append("e").toString();使用上面的方法測試不同數量級的運行時間得到如下參考數據:
整個過程中會多次創建新的對象,并頻繁調用toString()方法,最終導致了其性能的下降。
通過上面的結果我們可以得到如下結果:
1,在上面需求的復雜度的情況下,小于1000條數據時,選擇哪種實現均可,可以優先考慮可讀性,所以可以優先考慮String.formate();2,在上面需求的復雜度的情況下,大于1000條數據時,優先考慮StringBuilder或String.formate()。String.formate()通常能夠帶來更好的可讀性,但是如果性能上造成了很大的困擾時,請考慮使用StringBuilder;3,如果場景不是足夠簡單,盡量避免使用“+”拼接字符串,因為它既沒有帶來很好的可讀性,也沒帶來很好的性能。02. 目標1個億
上面數據量只到了100,000(即:10萬)條,而我們的目標是100,000,000(即:1億)條。
通過100條 - 10萬條數據的過程,我們字符串拼接的性能并不是線程增長的,在10W的時候:
(1)“+”已經達到38s,一次可以推斷 1億條記錄至少 38s x 1000 ≈ 10.5h。 (2)StringBuilder只用了43ms,所以它可能帶給我們驚喜。 (3)String.formate + StringBuilder消耗了532ms,1億條記錄至少 0.532s x 1000 ≈ 532s(9分多鐘)
所以直接使用方案2來StringBuffer生成SQL語句是個好選擇,直接將循環測試設為為1億次。
當將循環次數設定為循環1億次時,卻出了出了問題。
Exception in thread "main" java.lang.OutOfMemoryError: Java heap spaceJVM可以通過-Xms和-Xmx來設定堆內存。在經過幾次測試之后得到如下參考數據:
很顯然一臺內存是16GB的MacBook Pro是無法滿足直接在內存中創建1億行Insert SQL語句的。那么如何完成上述需求?
既然無法通過1個1一次的For循環來生成,那么可以通過多個多次的For循環,比如執行10次1千萬的For循環。按照上面的思路,執行了兩次操作: 1,執行10次,每次生成1000萬行數據,并將生成數據持久化的同一個文件。 2,執行10次,每次生成1000萬行數據,并將生成數據持久化的一個獨立的文件。 3,執行100次,每次生成100萬行數據,并將生成數據持久化的一個獨立的文件。
執行結果如下:
到此為止需求實現。
03. 拓展
1,如果一開始選擇實現方式是每生成一條SQL就append到文件中,那么上面的部分問題你不會遇到。
2,在生成測試數據時,如果數據比1億條更大,那么需要注意StringBuilder內部有一個capacity,capacity的類型為int,因此存在最大capacity的限制,另外
3,StringBuilder內部會有byte[]實現,處理大數據量是還需要關注數組越界的問題。
4,最終生成的文件大小可以在實際應用中需要進行判斷,使用何種體積的文件,建議使用每個文件100萬行數據體積64.9MB的文件,因為打開這個體積的文本文件速度較快(無論是通過Vim還是文本工具)。
5,在處理的大量數據時,除了關注可讀性可讀性,同時還需要關注效率以及,需要時還需要關注JVM參數設置。
總結
以上是生活随笔為你收集整理的server多笔记录拼接字符串 sql_Java拼接“1亿行字符串”你会遇到什么问题?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: elementui 按钮 表单_前后端分
- 下一篇: asp获取ftp服务器目录并显示_用 P