【问题标题】:MySQL update every single row from a 3 million row tableMySQL 从 300 万行表中更新每一行
【发布时间】:2013-10-25 21:55:31
【问题描述】:

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

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

这个想法是这样的:

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 知道我正在做全表扫描,所以只是按顺序为我返回记录,但不是一次全部返回。

欢迎任何建议

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

【问题讨论】:

  • 如果您对更新所涉及的内容有所了解,将会有所帮助。如果更新相对简单,并且您使用的是 MySQL,您可能会很好地查看 SELECT INTO OUTFILELOAD DATA INFILE
  • 谢谢迈克,这是一次重要的更新,涉及长度操作:(

标签: mysql jdbc


【解决方案1】:

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

stmt.setFetchSize(Integer.MIN_VALUE); 

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

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

【讨论】:

  • Mysql 连接器/J 驱动和 java.sql.QuerySet
  • 抱歉,在 MySQL Connector/J 5.1.25(我刚刚抓取了源代码)和 J2SE 7 中都没有出现该名称的类。您从哪里获得该类?
  • 我在导入语句的顶部有这个:import java.sql.{Connection, DriverManager, ResultSet};
  • @baboonWorksFine ResultSet != QuerySet.
  • 对,如果您使用的是 java.sql.ResultSet,那么我的答案是正确的。
猜你喜欢
  • 1970-01-01
  • 2019-05-05
  • 1970-01-01
  • 1970-01-01
  • 2013-04-20
  • 1970-01-01
  • 2012-07-10
  • 1970-01-01
  • 2015-06-13
相关资源
最近更新 更多