關於Java導出100萬行數據到Excel的優化方案


1》場景

  項目中需要從數據庫中導出100萬行數據,以excel形式下載並且只要一張sheet(打開這么大文件有多慢另說,呵呵)。

  ps:xlsx最大容納1048576行 ,csv最大容納1048576行,xls最大容納65536行,但是存放相同的數據量 文件大小排序:xls>csv>xlsx ;xls是biff8的二進制文件,就是個B+樹而xlsx是 xml的zip壓縮文件。

2》常規做法

  按照平常的做法,先到數據庫中取數然后循環組裝成一個list,然后用excel工具(我用的是POI)生成excel。

3》遇到的問題

  1' 內存經常溢出。

  2' 組裝list,生成excel慢,50萬的數據花了一個小時都沒見完成。

4》解決方法

  1' POI 改用 SXSSFWorkbook 參看 比如SXSSFWorkbook wb = new SXSSFWorkbook(100);在內存中只保留100行記錄,超過100就將之前的存儲到磁盤里,

      2' 調整JVM 相關的參數 -Xmx....

    3' 循環中減少使用new,盡量復用;String改為StringBuffer就不說了,重點是在組裝一行數據時,一直比較喜歡用map來拼裝,但是在我功能上發現還是耗內存的,后來的GC時間太長,造成嚴重拖累組裝數據的效率,后來發現由HashMap改為用StringBuffer拼接行數據效率直接就上去了,當然指定合理的StringBuffer的起始容量效率就更好了。

  ps:StringBuffer 的構造器會創建一個默認大小(通常是16)的字符數組。在使用中,如果超出這個大小,就會重新分配內存,創建一個更大的數組,並將原先的數組復制過來,再丟棄舊的數組。在大多數情況下,你可以在創建 StringBuffer的時候指定大小,這樣就避免了在容量不夠的時候自動增長,以提高性能。

      4' 下載任務由同步改為異步,用戶提交了后只要等待郵件通知即可,我用了quartz。

5》效果

    100萬數據組裝以及生成excel大概要10分鍾,平均下來1分鍾10萬條,我的小黑腰不酸腿不疼了。

好了就這些,我也看了,網上導出很多是分批導出或者用csv的解決的,但是我就這樣的需求,人家任性沒辦法,我的方法還有待完善的地方,歡迎交流。

本文原創,轉載請注明出處,謝謝。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM