Написание переносчика базы данных на Java, проблемы с памятью (структурирование кода?) - PullRequest
1 голос
/ 17 августа 2011

В настоящее время я пытаюсь перенести данные из filemaker pro 11 в MySQL с помощью JDBC.

Я имел дело с настройкой соединения с каждым, и у меня есть запросы, которые работают, и безопасно вставляю данные в 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);
}

Это нормально работает для небольших таблиц (~ 100 000 записей за 4 минуты), но некоторые из них очень, очень большие и вызывают сбой приложения :(.

Это должно быть в состоянии запускаться хотя бы один раз, чтобы заполнить все население, но после этого я могу ограничить вывод, чтобы зафиксировать изменения, сделанные, скажем, на прошлой неделе.

Ранее я писал это на VB.net и создавал большие вставки, но я сделал переключение - и мне действительно нужно это подготовительное утверждение, поскольку в текущей базе данных есть все виды сумасшедших символов.

Спасибо, Пол С

 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)

Ответы [ 4 ]

1 голос
/ 17 августа 2011

Возможно, вам придется использовать другой драйвер FileMaker JDBC.Я не думаю, что драйвер JDBC, поставляемый FileMaker, поддерживает потоковые наборы результатов, что означает, что он загружает все данные в память.

Если вы хотите, вы можете попробовать наш драйвер FileMaker JDBC на http://java.net/projects/woof/. Это немного медленнее, чем драйвер, предоставляемый FileMaker, потому что он работает через (медленный) интерфейс веб-публикации XML, но передает результаты и, следовательно, не должен исчерпывать память.

0 голосов
/ 17 августа 2011

Делайте это в партиях .Вы можете начать с размера пакета 100 КБ и увеличивать его, пока производительность не снизится.

  • 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();

как здесь http://download.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame6.html

  • 3) Кроме того, сохранитьотслеживать, какие записи были успешно обработаны.(либо обновите флаг в исходной строке, либо обработайте их в определенном порядке и сохраните последний)
  • 4) Обрабатывайте ошибки, фиксируйте изменения в БД, освобождайте ресурсы (операторы закрытия и т. д.)

цикл 1-4, пока все записи в исходной таблице не будут успешно обработаны.

0 голосов
/ 17 августа 2011

Возможно, это решит проблему:

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

(выпустите оператор явно, вместо того, чтобы ждать, пока GC сделает это за вас)

0 голосов
/ 17 августа 2011

PreparedStatement - это путь; не беспокойтесь там.

Мне нужно увидеть исключение, описывающее сбой, чтобы узнать причину, но я предполагаю, что вы пытаетесь ВСТАВИТЬ слишком много записей одновременно. Я разбивал бы его на более мелкие порции и фиксировал каждый порцию как одну транзакцию. Ваш журнал транзакций не должен содержать все вставки таким образом.

...