2011-08-17 2 views
1

현재 JDBC를 사용하여 filemaker pro 11에서 MySQL로 데이터를 전송하려고합니다.Java에서 데이터베이스 마이그레이션 도구 작성, 메모리 문제 (코드 구조)

각각에 대한 연결 설정을 다루었으며 쿼리가 작동하고 MySQL에 안전하게 데이터를 삽입했습니다.

try { 
    results = 
    query.executeQuery("SELECT \"field one\", \"field two\" from table"); 


    Connection con = DriverManager.getConnection("jdbc:mysql://website.com/database","user","password"); 

// Iterate through the results and print them to standard output 

    while (results.next()) { 
    String fname = results.getString("field one"); 
    String lname = results.getString("field two"); 
    System.out.println("Found user \"" + fname + " " + lname + "\""); 
    stmt = con.prepareStatement("INSERT ignore INTO table (idtable, name) values (?, ?)"); 

    // some of the data I've been provided with is pretty horrific, 
    // so inserting safely is of large concern. 

    stmt.setString(1, fname); 
    stmt.setString(2, lname); 
    stmt.executeUpdate(); 

    } 
} 
catch (SQLException e) { 
    System.out.println("Error retrieving data from database."); 
    e.printStackTrace(); 
    //System.exit(1); 
} 

이 작은 테이블 (~ 4 분에 10 만 개 기록)에 대한 괜찮 작동하지만 이들 중 일부는 매우, 매우 큰이며 :(응용 프로그램에 충돌이 원인이됩니다.

이 할 수 있어야합니다 적어도 한 번 실행하여 전체 채우기를 수행해야하지만 그 이후에는 지난 주에 변경된 내용을 가져올 출력을 제한 할 수 있습니다.

이전에이 내용을 VB.net에 작성하고 큰 삽입을 구성했지만, ve는 스위치를 만들었고 현재 데이터베이스에는 모든 종류의 미친 캐릭터가 있기 때문에 준비 문이 필요합니다.

감사합니다, 폴 S는

Error: 
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space 
at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:151) 
at java.lang.StringCoding.decode(StringCoding.java:191) 
at java.lang.String.<init>(String.java:451) 
at java.util.jar.Attributes.read(Attributes.java:401) 
at java.util.jar.Manifest.read(Manifest.java:199) 
at java.util.jar.Manifest.<init>(Manifest.java:69) 
at java.util.jar.JarFile.getManifestFromReference(JarFile.java:182) 
at java.util.jar.JarFile.getManifest(JarFile.java:163) 
at sun.misc.URLClassPath$JarLoader$2.getManifest(URLClassPath.java:710) 
at java.net.URLClassLoader.defineClass(URLClassLoader.java:238) 
at java.net.URLClassLoader.access$000(URLClassLoader.java:73) 
at java.net.URLClassLoader$1.run(URLClassLoader.java:212) 
at java.security.AccessController.doPrivileged(Native Method) 
at java.net.URLClassLoader.findClass(URLClassLoader.java:205) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:321) 
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:294) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:266) 
at com.mysql.jdbc.Util.handleNewInstance(Util.java:435) 
at com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:872) 
at com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1491) 
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4250) 
at com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4149) 
at datasync2.FMProConnection.companyQuoteInsert(FMProConnection.java:686) 
at datasync2.DataSync2View.jButton1ActionPerformed(DataSync2View.java:220) 
at datasync2.DataSync2View.access$800(DataSync2View.java:22) 
at datasync2.DataSync2View$4.actionPerformed(DataSync2View.java:124) 
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2012) 
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2335) 
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:404) 
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259) 
at   javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:253) 
at java.awt.Component.processMouseEvent(Component.java:6268) 
+1

당신은'con.prepareStatement()'호출을 루프 외부로 옮겨 보았습니까? 매번 새로운 PreparedStatement를 만들 필요가 없습니다. 매개 변수를 설정하고 실행하면됩니다. –

+1

내가 당신이라면 나는 [Spring Batch] (http://static.springsource.org/spring-batch/)를 사용할 것이다. 이를 염두에두고 시나리오를 작성하고 재시작, 트랜잭션 일괄 처리 및 기타 여러 가지 유용한 기능을 지원합니다. –

답변

0

일괄에서하십시오. 배치 크기가 100K부터 시작하여 성능이 저하 될 때까지 늘릴 수 있습니다.

  • 1) 소스 테이블의 처리되지 않은 행에서 제한된 수의 행을 선택하십시오.
  • 2) 일괄 삽입을

를 수행

Statement stmt = con.createStatement(); 
stmt.addBatch("INSERT INTO employees VALUES (1000, 'Joe Jones')"); 
stmt.addBatch("INSERT INTO departments VALUES (260, 'Shoe')"); 
int[] insertCounts = stmt.executeBatch(); 

은 소스 테이블의 모든 레 Z 드가 성공적으로 처리 될 때까지 1-4 루프됩니다.

+0

SQL 문을 일괄 처리하는 것이 좋습니다. 단일 PreparedStatement를 사용하여 일괄 처리를 사용하는 것이 더 좋습니다. –

0

PreparedStatement의 길을 가야하는 것입니다; 걱정할 필요가 없습니다.

근본 원인을 알기 위해 크래시를 설명하는 예외를 알아야하지만 내 생각에 너무 많은 레코드를 한 번에 삽입하려고합니다. 나는 하나의 트랜잭션으로 갔을 때 더 작은 덩어리로 나누고 각 덩어리를 커밋합니다. 트랜잭션 로그에는 그런 식으로 모든 INSERT가 포함될 필요가 없습니다.

//... 
stmt.executeUpdate(); 
stmt.close(); 
//... 

(문을 해제 명시 적으로 대신 GC가 당신을 위해 그것을 할 때까지 대기) 당신은 다른 파일 메이커 JDBC 드라이버를 사용해야 할 수도 있습니다

+0

그게 좋은 제안입니다. 저는 Sean이 제안한 'Spring Batch (스프링 배치)'도구를 조사하고 있습니다. 덕분에 입력 된 Duffymo에 많은 감사를드립니다! –

0

아마 그 문제를 해결하는 것입니다. FileMaker에서 제공하는 JDBC 드라이버가 스트리밍 결과 세트를 지원하지 않는다고 생각합니다. 즉, 모든 데이터를 메모리에로드합니다.

원하는 경우 FileMaker JDBC 드라이버 (http://java.net/projects/woof/)를 사용해보십시오. XML Web Publishing 인터페이스를 통해 실행되기 때문에 FileMaker에서 제공하는 드라이버보다 약간 느리지 만 결과를 스트리밍하므로 메모리가 부족하지 않아야합니다.

+0

방금 ​​loop 외부에 stmt.close()를 추가하여 AlistairIsreal의 제안과 결합하여 루프 전에 준비해야하지만 약간의 향상을 가져야한다고 생각합니다. Sean의 제안에서 기대하는 큰 변화에 감사드립니다. 지금까지 모두에게 많은 것을! –

1

:

+0

감사합니다. 나는 while 루프 외부에서 prepareStatement를 이동하여이를 저장할 수있었습니다. (@AlistairIsrael에게 크레딧을 제공 하겠지만 코멘트에서는 수행 할 수 없습니다). WOOF를 염두에 두어야합니다. 그래도 여전히 현재입니까? Filemaker 7에 대해 말했기 때문에, 그 이후로 꽤 중요한 기회가있었습니다. –

+0

예, 전 항상 변경 사항을 적용하고 있습니다 (어제보고 한 오류보고 기능이 향상되었습니다). FileMaker 7 이상에서 작동합니다. XML 형식은 그 이후로 변경되지 않았습니다. –

관련 문제