使用 JDBC 循环访问大型表的最快方法

2022-09-01 19:14:14

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

  • 选择一次 1000 行的增量
  • 使用 JDBC 在以下 SQL 查询 SELECT * FROM TABLE 上获取结果集,其中 ID > 0,ID < 1000
  • 将生成的数据添加到内存中数组
  • 继续查询,每次添加结果时,以 1000 为增量,一直到 500,000。

这需要很长时间。事实上,它甚至没有超过从1000到2000的第二个增量。查询需要永远才能完成(尽管当我直接通过MySQL浏览器运行同样的事情时,它的速度相当快)。自从我直接使用JDBC以来已经有一段时间了。有没有更快的替代方案?


答案 1

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

// 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 ...");

它使您能够使用“绝对”和“相对”方法移动到所需的任何行。


答案 2

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

  • 您的网络(或者至少是您与mysql的连接)是否非常慢?如果是这样,您可以尝试在mysql框中本地运行该进程,或者连接得更好。

  • 表结构中是否有某些原因导致它?为每行拉下 10k 个数据?200 个字段?计算基于非索引行获取的 id 值?您可以尝试找到一种对数据库更友好的方法来提取数据(例如,仅查找所需的列,具有数据库聚合值等)

如果你没有通过第二个增量,那么真的错了 - 无论是否有效,你都应该在正在运行的JVM上将2000或20,000行转储到内存中。也许您以冗余方式存储数据或效率极低?


推荐