3

要求:我必须扫描整个表并更新每条记录,周期。

正如其他人所建议的那样,我应该创建一个与原始表具有相同架构的临时表,并对更新的值进行插入,然后重命名表而不是更新原始表。

这个想法是这样的:

ResultSet row = select * from old_table;
While row.next
  do something to update values in this row
  insert updated values in to a identical table (different name of course)
endWhile

这里的问题是我使用的是 Java JDBC,我必须处理 ResultSet 对象。那么有没有办法防止“ResultSet row = select * from old_table”产生内存不足异常?

一个潜在的解决方案是分页,但这意味着我必须使用 ORDER BY 和 LIMIT,这在 300 万行的表上可能非常慢。

ResultSet 是否有一些技巧,比如指定一些标志,如 FOWARD_ONLY | NON-SCROLLABLE 等。或者 Mysql 服务器是否有一些配置可以做一些聪明的事情,比如 mysql 知道我正在做全表扫描,所以只是按顺序为我返回记录,但不是一次全部返回。

欢迎任何建议

[更新] 似乎 MySQL 连接器/J 具有名为的配置参数useCursorFetch,如果设置为 truestatement.setFetchSize(1000)则将起作用。不确定这是否是最终解决方案。

4

1 回答 1

1

您可以通过这种方式将 JDBC 语句设置为非缓冲:

stmt.setFetchSize(Integer.MIN_VALUE); 

但我也建议绑定使用INSERT... SELECT语句,这样您就不必使用 while 循环,也不必获取任何东西。如果您可以在“执行某些操作以更新值”的步骤中使用 SQL 表达式,那么您可以在一个 SQL 语句中完成整个操作。

PS:您必须更具体地了解 QuerySet。我在不同的库中找到了多个名为 QuerySet 的类,例如 org.dbunit.ant.QuerySet、org.gusdb.wdk.model.QuerySet 等。

于 2013-09-15T22:16:36.503 回答