用 Java 编写数据库迁移器,内存问题(代码结构?)

发布于 2024-11-29 19:43:55 字数 3486 浏览 0 评论 0原文

我目前正在尝试使用 JDBC 将数据从 filemaker pro 11 传输到 MySQL。

我已经处理了设置每个连接的问题,并进行了有效的查询,并将数据安全地插入到 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 分钟内约 100,000 条记录)来说还可以,但其中一些非常非常大,会导致应用程序崩溃:(。

这需要能够至少运行一次才能完成完整填充,但是之后,我可以限制输出以获取上周

我之前在 VB.net 中编写的更改,并构建了大型插入,但我做了一个切换 - 我确实需要那个准备语句,因为当前数据库有各种里面有很多疯狂的角色,

谢谢,保罗·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)

I'm currently attemping to transfer data away from filemaker pro 11 to MySQL using JDBC.

I've dealt with setting up the connection to each, and have queries that work, and insert the data safely into 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);
}

This works okay for smaller tables(~100,000 records in 4 mins), but some of these are very, very big and cause the application to crash :(.

This needs to be able to run at least once to do a full population, but after that I can limit the output to pick up changes made in say the last week.

I previously wrote this in VB.net, and constructed large inserts, but I've made a switch - and I really need that prepare statement, as the current database has all sorts of crazy characters in there.

Thanks, Paul 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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夜灵血窟げ 2024-12-06 19:43:55

您可能需要使用不同的 FileMaker JDBC 驱动程序。我认为 FileMaker 附带的 JDBC 驱动程序不支持流式结果集,这意味着它将所有数据加载到内存中。

如果您愿意,可以在 http://java.net/projects/woof/ 尝试我们的 FileMaker JDBC 驱动程序。它比 FileMaker 提供的驱动程序慢很多,因为它在(慢速)XML Web Publishing 接口上运行,但它会传输结果,因此不会耗尽内存。

You might need to use a different FileMaker JDBC driver. I don't think that the JDBC driver shipped by FileMaker supports streaming result sets, which means it loads all the data into memory.

If you'd like, you can try our FileMaker JDBC driver at http://java.net/projects/woof/. It is quite a bit slower than the driver supplied by FileMaker, because it runs over the (slow) XML Web Publishing interface, but it streams the results and thus should not run out of memory.

醉梦枕江山 2024-12-06 19:43:55

分批进行。
您可以从 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();

像这里 http://download.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame6.html

  • 3) 另外,跟踪已处理的记录 成功地。
    (更新源行上的标志或按特定顺序处理它们并保存最后一个)
  • 4)处理错误,提交对数据库的更改,释放资源(关闭语句等)

循环1-4,直到源中的所有记录表已成功处理。

Do it in batches.
You could start with a batch size of 100K and increase it until performance degrades.

  • 1) Try to select a limited number of rows from the unprocessed rows of the source table.
  • 2) Do a batch insert

:

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

like here http://download.oracle.com/javase/1.3/docs/guide/jdbc/spec2/jdbc2.1.frame6.html

  • 3) Also, keep track of which records had been processed successfully.
    (either update a flag on the source row or process them in a certain order and save the last one)
  • 4) Handle errors, Commit changes to db, free up resources (close statements, etc)

loop 1-4 until all records in source table had been processed successfully.

分开我的手 2024-12-06 19:43:55

ReadyStatement 是正确的选择;那里不用担心。

我必须查看描述崩溃的异常才能知道根本原因是什么,但我的猜测是您试图一次插入太多记录。我会将其分成更小的块,并在作为单个事务时提交每个块。您的事务日志不必以这种方式包含每个 INSERT。

PreparedStatement is the way to go; no worries there.

I'd have to see the exception that described the crash to know what the root cause is, but my guess is that you're trying to INSERT too many records at once. I'd break it into smaller chunks and commit each chunk as I went as a single transaction. Your transaction log doesn't have to contain every INSERT that way.

各空 2024-12-06 19:43:55

也许这可以解决问题:(

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

显式释放该语句,而不是等待 GC 为您执行此操作)

Maybe that would fix the problem:

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

(release the statement explicitly instead of waiting for the GC to do it for you)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文