真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化-創(chuàng)新互聯(lián)

這篇文章主要講解了“Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化”吧!

十多年專注成都網(wǎng)站制作,企業(yè)網(wǎng)站建設,個人網(wǎng)站制作服務,為大家分享網(wǎng)站制作知識、方案,網(wǎng)站設計流程、步驟,成功服務上千家企業(yè)。為您提供網(wǎng)站建設,網(wǎng)站制作,網(wǎng)頁設計及定制高端網(wǎng)站建設服務,專注于企業(yè)網(wǎng)站建設,高端網(wǎng)頁制作,對辦公窗簾等多個行業(yè),擁有豐富的網(wǎng)站設計經(jīng)驗。

現(xiàn)場提的問題概況

  • 數(shù)據(jù)量:生成xml,每個文件100W+ 條的數(shù)據(jù)

  • 內存控制:最好不要超過512M

  • 問題詳情:在處理70W左右的時候內存溢出

一、先來看一下程序要生成的xml文件的結構

 
1 
12 
03 
004 
5 
0006 
1000000 
 
 
  10350719507 
  1 
  20110303 
  20110419 
  45000 
 
  ...  

二、給大家說一下如何把大數(shù)據(jù)生成xml文件

1、小數(shù)據(jù)量的情況下 < 1W條數(shù)據(jù)

比較好用的方法是使用開源框架,比如XStream 直接把javabean 生成 xml

  • 優(yōu)點:api操作簡單,方便維護

  • 缺點:數(shù)據(jù)量大的情況下太消耗內存

2、大數(shù)據(jù)量生成一個xml文件(本程序采用的方法)

自己做的一個可以使用極少的內存生成無限制大的xml文件框架由3部分生成xml文件

第一部分:生成文件頭

例如:xxx.toXML(Object obj, String fileName)

第二部分:通過每次向文件里面追加3000(可配置)條數(shù)據(jù)的形式生成文件塊

例如:xxx.appendXML(Object object); //object 可以是ArrayList 或者一個單獨的javaBean

第三部分:生成xml文件尾巴

例如:xxx.finishXML();

  • 程序中的調用:調用xxx.toXML(Object obj, String fileName) 生成文件頭之后,可以循環(huán)從數(shù)據(jù)庫中讀取數(shù)據(jù)生成ArrayList,通過xxx.appendXML(Object object) 方法追加到xml文件里面,xxx.finishXML() 對文件進行收尾

  • 對框架說明:我上面提供的例子有文件頭 + 文件塊 + 文件尾巴. 如果和你們的實際使用文件不太一致的話,可以參考上面提供的思路修改一下即可,主要的方法是把相同的文件塊部分分離出來通過追加的形式寫入xml文件.

有了思路之后,大家可以嘗試著自己寫一個類似的大數(shù)據(jù)處理框架(千萬級別以上),如何有什么需要幫助的可以直接聯(lián)系我,因為是公司的程序,不太敢放出來,怕......

三、我是如何測試性能和優(yōu)化的

1、手動排除

根據(jù)文件崩潰時候的日志發(fā)現(xiàn)是在生成xml的框架里面報的錯誤,第一想到的是框架有些資源沒有釋放.于是把自己做的文件生成框架整體的排查了一遍,并且自己寫個簡單程序生成200萬條數(shù)據(jù),使用xml框架生成一個xml文件,整個生成過程中任務管理器(xp)查看程序對應的java進程使用的內存基本在20M左右,因此排除框架的問題.懷疑是數(shù)據(jù)庫查詢和調用框架的部門出現(xiàn)問題.

檢測了一遍主程序的關鍵部分代碼,優(yōu)化了一下字符串處理.手動的釋放一些對象的內存(例如:調用ArrayList.clear(),或者把對象置空等),分配512內存后運行程序,60萬數(shù)據(jù)的時候內存溢出,因為能主動釋放的對象都已經(jīng)釋放掉了,還是沒有解決,果斷放棄看代碼,準備使用JProfile進行內存檢測.

2、手動排除沒有解決,借助內存分析工具JProfile進行排除

通過在數(shù)據(jù)庫中生成300W條數(shù)據(jù),在JProfile上面多跑程序,一邊運行,一邊調用JProfile 提供的執(zhí)行GC按鈕主動運行垃圾回收,運行50W數(shù)據(jù)后,通過檢測中發(fā)現(xiàn) java.long.String[] 和 oracle.jdbc.driver.Binder[] 兩個對象的數(shù)目一直保持在自增狀態(tài),而且數(shù)目基本上差不多,對象數(shù)目 都在200W以上,由于java.long.String[]對象是需要依賴對象而存在的,因此斷定問題就出在oracle.jdbc.driver.Binder[]上面,由于改對象存在引用導致String[]不能正?;厥?

3、通過在JProfile對象查看對象的管理

檢測到oracle.jdbc.driver.Binder 被 oracle.jdbc.driver.T4CPreparedStatement 引起,而T4CPreparedStatement正好是Oracle對jdbc OraclePreparedStatement的具體實現(xiàn),因此斷定是在數(shù)據(jù)庫處理方面出現(xiàn)的問題導致oracle.jdbc.driver.Binder對象不能正常釋放,通過再一次有目的的檢測代碼,排查jdbc數(shù)據(jù)查詢的問題,把問題的矛頭直至數(shù)據(jù)庫的批處理和事務處理.因此程序是每生成一個文件成功后,會把已經(jīng)處理的數(shù)據(jù)轉移到對應的歷史表中進行備份,而再個表操作的過程中使用了批處理和事務,使用批處理主要是保證執(zhí)行速度,使用事務主要是保證同時成功和失敗。

4、又因此程序每次從數(shù)據(jù)庫中查詢3000條數(shù)據(jù)處理

所以準備監(jiān)控oracle.jdbc.driver.Binder的對象數(shù)目是否和查詢次數(shù)對應.,通過在程序中Sysout輸出查詢次數(shù) + JProfile運行GC測試 Binder,數(shù)據(jù)匹配,證實是java在數(shù)據(jù)庫批處理的過程中有些問題.

5、專門把批處理代碼提取出來通過JProfile內存分析.最終問題定位完畢.

原因如下:100W數(shù)據(jù)生成一個文件的過程中,等文件生成完畢之后才能把數(shù)據(jù)庫中的數(shù)據(jù)備份到歷史表中,這個時候才能進行事務的提交,也就是執(zhí)行commit(), 并且刪除原表數(shù)據(jù),100W數(shù)據(jù)按照3000一批寫入文件,每批次只是通過 PreparedStatement.addBatch();加入到批次里面去,并沒有執(zhí)行PreparedStatement.executeBatch(),而是在commit()之前統(tǒng)一調用的PreparedStatement.executeBatch(),這樣的話PreparedStatement就會緩存100W條數(shù)據(jù)信息,造成了內存溢出.

錯誤的方法如下

try{
    conn.setAutoCommit(false);
    pst = conn.prepareStatement(insertSql);
    pstDel = conn.prepareStatement(delSql);
    pstUpdate = conn.prepareStatement(sql);
    ... 
      //totalSize = 100W數(shù)據(jù) / 3000一批次 
    for (int i = 1; i <= totalSize; i++) {
        client.appendXML(list);
    }
    // 錯誤的使用方法 
    client.finishXML();
    pst.executeBatch();
    pstDel.executeBatch();
}
... 
  finally {
    try {
        if (isError) {
            conn.rollback();
        } else 
              conn.commit();
        ...
    }
    ...
}

正確的方法如下

try{
    conn.setAutoCommit(false);
    pst = conn.prepareStatement(insertSql);
    pstDel = conn.prepareStatement(delSql);
    pstUpdate = conn.prepareStatement(sql);
    ... 
        //totalSize = 100W數(shù)據(jù) / 3000一批次 
    for (int i = 1; i <= totalSize; i++) {
        list = 從數(shù)據(jù)庫中查詢3000條數(shù)據(jù) 
                client.appendXML(list);
        pst.executeBatch();
        pstDel.executeBatch();
    }
    client.finishXML();
}
... 
finally {
    try {
        if (isError) {
            conn.rollback();
        } else 
               conn.commit();
        ...
    }
    ...
}

如果碰到和我一樣的需要給大家一個提醒。

oracle在每次執(zhí)行executeBatch();進行批處理的時候,當前connection對應的rownum會根據(jù)操作的結果發(fā)生變化。

在執(zhí)行pst.executeBatch(); 之后,當前連接的 rownum 數(shù)就會發(fā)生變化. 因此凡是通過rownum查詢數(shù)據(jù)的程序都要小心這一點。

感謝各位的閱讀,以上就是“Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化”的內容了,經(jīng)過本文的學習后,相信大家對Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關知識點的文章,歡迎關注!

另外有需要云服務器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內外云服務器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務器、裸金屬服務器、高防服務器、香港服務器、美國服務器、虛擬主機、免備案服務器”等云主機租用服務以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應用場景需求。


分享題目:Java怎么將千萬級別數(shù)據(jù)生成文件并優(yōu)化-創(chuàng)新互聯(lián)
標題路徑:http://weahome.cn/article/dgjcjh.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部