要求:我必须扫描整个表并更新每个记录,期间。
正如其他人所建议的那样,我应该创建一个与原始模式具有相同模式的临时表,然后插入更新的值,然后重命名表而不是更新原始表。
这个想法是这样的:
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 |不可滚动等等。或者Mysql服务器有一些配置来做智能的东西,比如mysql理解我正在做一个全表扫描,所以只是顺序返回记录给我,但不是一次性。
欢迎任何建议
[UPDATE]似乎MySQL connector / J具有名为useCursorFetch
的配置参数,如果设置为true,则statement.setFetchSize(1000)
将起作用。不确定这是否是最终的解决方案。
答案 0 :(得分:1)
您可以通过以下方式将JDBC语句设置为非缓冲:
stmt.setFetchSize(Integer.MIN_VALUE);
但我也建议使用INSERT... SELECT
语句,因此您不必使用while循环而不必获取任何内容。如果您可以使用SQL表达式执行“执行某些更新值”的步骤,那么您可以在一个SQL语句中执行整个操作。
PS:你必须更具体地了解QuerySet。我在不同的库中找到了多个名为QuerySet的类,例如org.dbunit.ant.QuerySet,org.gusdb.wdk.model.QuerySet等。