2012-01-12 9 views
1

私は、改行で区切られた158000レコード(12MB)を含むファイルを読み込み、そのレコードをmysqlデータベースに入れようとしていますが、約49000レコードを挿入した後、データをエラーが発生しました:: java.lang.OutOfMemoryError:Javaヒープスペース

FileInputStream file; 
     DataInputStream dataIn; 
     BufferedReader bReader; 
     Connection conn= openConnection(); 
     String strRecord=new String(); 
     String[]strSplittedRecord; 
     file= new FileInputStream("D:\\Java\\CountryWhois.txt"); 
     dataIn= new DataInputStream(file); 
     bReader= new BufferedReader(new InputStreamReader(dataIn)); 
     PreparedStatement insertStmt; 
     String strQuery="insert into countrywhois values(?,?,?,?,?,?)"; 
     while((strRecord=bReader.readLine())!=null) 
     { 

      strSplittedRecord=strRecord.split(","); 

     try { 

      insertStmt=conn.prepareStatement(strQuery); 
      insertStmt.setString(1,strSplittedRecord[0].substring(1, strSplittedRecord[0].length()-1)); 
      insertStmt.setString(2,strSplittedRecord[1].substring(1, strSplittedRecord[1].length()-1)); 
      insertStmt.setString(3,strSplittedRecord[2].substring(1, strSplittedRecord[2].length()-1)); 
      insertStmt.setString(4,strSplittedRecord[3].substring(1, strSplittedRecord[3].length()-1)); 
      insertStmt.setString(5,strSplittedRecord[4].substring(1, strSplittedRecord[4].length()-1)); 
      insertStmt.setString(6,strSplittedRecord[5].substring(1, strSplittedRecord[5].length()-1)); 
      int nResultInsert=insertStmt.executeUpdate(); 
      if(nResultInsert!=0) 
      { 
       System.out.println("Inserted 1"); 


      } 
      else 
      { 
       if(conn!=null) 
       { 
        conn.close(); 
        System.out.println("Disconnected from database"); 
       } 
      } 
     } 
     catch (Exception e) 
     { 
      conn.close(); 
      e.printStackTrace(System.out);   
     } 

     } 

の挿入例外

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space 
    at java.util.jar.Manifest$FastInputStream.<init>(Manifest.java:315) 
    at java.util.jar.Manifest$FastInputStream.<init>(Manifest.java:310) 
    at java.util.jar.Manifest.read(Manifest.java:178) 
    at java.util.jar.Manifest.<init>(Manifest.java:52) 
    at java.util.jar.JarFile.getManifestFromReference(JarFile.java:167) 
    at java.util.jar.JarFile.getManifest(JarFile.java:148) 
    at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:696) at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:696) 

    at java.net.URLClassLoader.defineClass(URLClassLoader.java:228) 
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58) 
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:430) at com.mysql.jdbc.Util.handleNewInstance(Util.java:430) 

    at com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:553) 
    at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1378) 
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4143) 
    at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4042) 
    at loadcsvdatabase.LoadCsvDatabase.fnLoadCsvIntoMemory(LoadCsvDatabase.java:52) 
    at loadcsvdatabase.LoadCsvDatabase.main(LoadCsvDatabase.java:29) 

Javaコード次それはラインinsertStmt = conn.prepareStatement(strQuery)に例外をスロー。

私のプログラムがメモリ例外が不足している理由を私に勧めてください。..

答えて

7

は、新しいPreparedStatementのレコードを挿入するたびに作成されています。これはPreparedStatementsの使用方法ではありません。また、作成されたPreparedStatementを閉じることは決してありません。おそらくOutOfMemoryExceptionが発生しますが、これは根本的な問題ではありません。

PreparedStatementを1つだけ作成して再利用する必要があります。次に、すべてのレコードを挿入した後、PreparedStatementとConnectionを閉じます。

+2

さらにaddBatchは、パフォーマンスを向上させることがポイントであること。 –

+0

私は2番目のckuetbachです。しかし、まずNishitはOOMの問題を最初に修正してから最適化する必要があります。また、レコードのサイズが大きいため、1回のexecuteBatch()呼び出しごとにaddBatch呼び出しを100(IMO)に制限する必要があります。 –

+0

ありがとうございました!それはループ中に準備されたステートメントを置くことによって私がやっていた間違いでした。 –

0
insertStmt=conn.prepareStatement(strQuery); 

ループはwhileの外側にある必要があります。正確strQuery

+0

Thanks It Woks !! –

0

を初期化した後、あなたがこの方法に従うようにコードを修正する必要があり、それを入れてください:

... 

try { 
    Connection conn = openConnection(); 
    try { 

    String strQuery="insert into countrywhois values(?,?,?,?,?,?)"; 
    PreparedStatement insertStmt=conn.prepareStatement(strQuery); 
    while (...) { 
     try { 
      .... 
      int nResultInsert=insertStmt.executeUpdate(); 

      // handle your result here (e.g. print/log) 
      // DO NOT close() here, continue with loop 

     } catch (Exception e) { 
      // handle your exception here (e.g. print/log) 
      // DO NOT close() here, continue with loop, OR break loop 
     } 
    } 

    } finally { 
     // closing SQL Connection no matter what happens to your while-loop 
     conn.close(); 
    } 
} catch (Exception e) { 
    // handle your exception here (e.g. print/log) 
} 
+0

ありがとうございます!できます –

関連する問題