Java 使用JDBC迭代大型表的最快方法

Java 使用JDBC迭代大型表的最快方法,java,mysql,jdbc,Java,Mysql,Jdbc,我正在尝试创建一个java程序来清理和合并表中的行。这个表很大,大约有500k行,我当前的解决方案运行非常缓慢。我想做的第一件事就是简单地获取一个内存中的对象数组,该数组表示表中的所有行。以下是我正在做的: 一次选择1000行的增量 使用JDBC获取以下SQL查询的结果集 从ID>0且ID

我正在尝试创建一个java程序来清理和合并表中的行。这个表很大,大约有500k行,我当前的解决方案运行非常缓慢。我想做的第一件事就是简单地获取一个内存中的对象数组,该数组表示表中的所有行。以下是我正在做的:

一次选择1000行的增量 使用JDBC获取以下SQL查询的结果集 从ID>0且ID<1000的表格中选择* 将结果数据添加到内存阵列中 继续查询,每次添加结果时,以1000为增量一直查询到500000。
这是一个漫长的过程。事实上,它甚至还没有超过从1000到2000的第二个增量。虽然当我直接通过MySQL浏览器运行同样的东西时,它的速度非常快,但是查询需要永远的时间才能完成。我已经有一段时间没有直接使用JDBC了。有更快的选择吗?

首先,您确定需要将整个表存储在内存中吗?也许你应该考虑如果可能的话,选择你想更新/合并的行等。如果你真的必须拥有整个表格,你可以考虑使用可滚动结果集。您可以这样创建它

// make sure autocommit is off (postgres)
con.setAutoCommit(false);

Statement stmt = con.createStatement(
                   ResultSet.TYPE_SCROLL_INSENSITIVE, //or ResultSet.TYPE_FORWARD_ONLY
                   ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("select * from ...");

通过使用“绝对”和“相对”方法,您可以移动到所需的任何行。

虽然它可能不是最佳的,但您的解决方案似乎适合一次性数据库清理例程。运行这样一个查询并得到结果应该不会花那么长时间,因为这是一次性的,所以我假设几秒钟就可以了。可能出现的问题-

您的网络或至少您与mysql的连接是否非常慢?如果是的话,您可以尝试在mysql盒上本地运行该进程,或者使用更好的连接方式

表结构中有什么导致它的原因吗?每行向下拉10k数据?200块地?基于非索引行计算要获取的id值?您可以尝试找到一种更为db友好的方式来提取数据,例如,只需要所需的列,具有db聚合值,等等


如果您没有完成第二个增量,那么就真的出了问题——效率与否,在运行的JVM上将2000行或20000行转储到内存中应该不会有任何问题。可能是您存储数据冗余或效率极低?

帮助我的一件事是Statement.setFetchSizeInteger.MIN\u VALUE。这个主意是我从你那里得到的。这将执行时间减少了一半以上。内存消耗急剧下降,因为一次只读取一行


不过,这个技巧对PreparedStatement不起作用。

太棒了。这就成功了。回答您关于选择性获取数据的观点。不幸的是,我不知道要提前合并和修复哪些行-我必须遍历所有行并进行检查,构建适当的内存哈希映射,然后根据某些特性返回并清理表。这种方法相当脆弱。如果您有数百万行和一些处理要做,您可能会遇到网络延迟或超时,这将使在某些情况下很难恢复操作。不幸的是,这在大型表上运行得非常慢,因为MySQL JDBC驱动程序不支持游标,驱动程序试图将所有数据加载到内存。我正在使用postgressql作为数据库,但这没用。仍在运行。请检查您使用的驱动程序是否支持此功能。考虑其他可能的原因堆的大小是多少?你想在内存中存储多少数据?谢谢你的建议。我相信主要的问题是我没有以最佳方式使用JDBCAPI。我现在能够以10k-20k的增量相对快速地获取数据。很好的建议,虽然只是拉必要的列,而不是做一个SELECT*。较大的值不会改变任何东西。