3 回答
![?](http://img1.sycdn.imooc.com/54584c5e0001491102200220-100-100.jpg)
TA贡献1796条经验 获得超7个赞
您应该在几个级别上处理此问题:
JDBC驱动程序访存大小
JDBC有一个Statement.setFetchSize()方法,该方法指示从JDBC获取行之前,JDBC驱动程序将预取多少行。请注意,MySQL JDBC驱动程序并未真正正确地实现此功能,但您可以设置setFetchSize(Integer.MIN_VALUE)为阻止它一次性获取所有行。另请参阅此答案。
请注意,您还可以使用以下方法激活连接上的功能 useCursorFetch
你自己的逻辑
您不应将整个用户列表存储在内存中。您现在正在做的是从JDBC收集所有行,然后稍后使用来对列表进行分区Lists.partition(users, 2000)。这是朝着正确的方向发展,但是您做的还不是很正确。相反,请执行以下操作:
try (ResultSet rs = cs.executeQuery()) {
while (rs.next()) {
res.add(new ImmutablePair<>(rs.getLong(1), rs.getString(2)));
}
// Process a batch of rows:
if (res.size() >= 2000) {
process(res);
res.clear();
}
}
// Process the remaining rows
process(res);
此处的重要信息是不加载内存中的所有行,然后分批处理它们,而是在从JDBC流传输行时直接处理它们。
![?](http://img1.sycdn.imooc.com/5458471300017f3702200220-100-100.jpg)
TA贡献1794条经验 获得超7个赞
而不是Java端的Lists.partition(users,2000),您应该将每个请求的mysql结果集限制为2000。
select UserPropertyKindId, login from TEST.users limit <offset>, 2000;
更新:正如Raymond Nijland在下面的评论中提到的,如果偏移量太大,则查询速度可能会大大降低。
一种解决方法可能是使用偏移量,而不是使用偏移量,引入where语句,例如where id> last_user_id。
由于@All_safe在下面进行了注释,因此不存在自动增量ID,因此另一个针对较大偏移量的解决方法是:仅在子查询中获取主键,然后再联接回主表。这将强制mysql不执行早期行查找,这是大偏移量限制的主要问题。
但是您的原始查询仅获取主键列,我认为早期行查找不适用。
![?](http://img1.sycdn.imooc.com/54584dd900014f6c02200220-100-100.jpg)
TA贡献1820条经验 获得超2个赞
我遇到了类似的情况。我正在从一个MySQL数据库中读取数据,并将其复制到MS SQL Server数据库中。不是2亿,每天只有400万。但是我在通信链接失败时也遇到了同样的错误消息。我可以通过设置PreparedStatement.setFetchSize(Integer.MIN_VALUE);的fetchsize来解决它。因此,通信链接故障消失了。我知道,这不能解决您的列表问题。
添加回答
举报