是否有一个尊重fetchSize的mysql JDBC?

我正在使用MySQL并希望利用setFetchSize属性。 默认的MySQL JDBC实现并不真正尊重它。 如果你将fetchsize设置为Integer.MIN_VALUE ,它将分别获取每一行,但考虑到我想使用fetchSize的原因是我有足够的数据将我的内存使用量放到2 G范围内,每行必须进行一次查询永远。

我想插入一个可以与MySQL一起工作的JDBC实现并正确地考虑获取大小,允许我设置10,000的提取量或其他一些更高的限制。 任何人都可以指向一个可能提供这种实现的jar吗? 失败那是否有任何其他资源允许我合理地以有效的方式进行包含数万个条目的查询,但是在内存和所需的sql查询数量方面。

技术问题要求图书馆是偏离主题的。 也就是说,据我所知,没有替代MySQL的驱动程序。 您可以选择获取可能导致内存不足情况的所有行,也可以通过设置setFetchSize(Integer.MIN_VALUE)让驱动程序按需获取它们。

正如我从Connector / J实现说明中所理解的那样,原因是MySQL协议不能在每个连接上打开多个游标,因此它默认在执行时将所有行流式传输到客户端。

另一个选项是逐行检索行,但这会带来在处理ResultSet时无法在同一连接上执行其他语句的问题:

这种方法有一些警告。 您必须先读取结果集中的所有行(或关闭它), 然后才能对连接发出任何其他查询 ,否则将引发exception。

所以MySQL只能选择获取所有内容或一次获取一个。 这意味着驱动程序无法遵守不同的提取大小。 由于在逐个获取时需要注意,他们选择使用Integer.MIN_VALUE (而不仅仅是1 )作为在执行此操作之前应该考虑的信号。

可能的“中间”解决方案需要您使用LIMITOFFSET编程并重复执行查询。

如果启用MySQL JDBC选项 useCursorFetch ,驱动程序确实会遵守fetchSize。

但是,这种方法有一个缺点:它将使用服务器端游标,在MySQL中使用临时表实现。 这意味着在服务器上完成查询之后结果才会到达,并且将在服务器端使用额外的内存。

如果您只想使用结果流并且不关心确切的提取大小,则setFetchSize(Integer.MIN_VALUE)的开销不会像文档所暗示的那样糟糕。 它实际上只是禁用整个响应的客户端缓存,并在它们到达时为您提供响应; 每行不需要往返。

这不是上述问题的真正答案。 由于我无法将其纳入评论,我将其作为答案提供。 对于面临类似问题的人来说,这可能会有所帮助。

对于批处理作业,我需要打开流模式,因为我的结果集太大了。 首先,如MySQL 文档中所示 ,我以这种方式设置连接:

 Statement extrapackStreamingQuery = dbExtrapackConnection.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); extrapackStreamingQuery.setFetchSize(Integer.MIN_VALUE); 

但它会系统地给我错误:

 Application was streaming results when the connection failed. Consider raising value of 'net_write_timeout' on the server. 

我尝试了一些配置选项,例如: max_allowed_packet = 128Mmax_connect_errors = 9999net_write_timeout = 180 。 但他们都没有帮助。

错误地认为TCP连接可能因空闲时间过长而关闭,我甚至尝试在/proc/sys/net/ipv4/tcp_keepalive_time/etc/sysctl.conf使用: net.ipv4.tcp_keepalive_time=60更改TCP ping时间帧/etc/sysctl.conf文件。

实际上,如果打开数据库连接但没有发送足够长的TCP数据包,则TCP连接关闭时数据库连接将丢失。 更频繁地发送TCP数据包以保持TCP连接活动可以解决问题。

但这也没有帮助。

然后,在阅读完这篇文章后,我将连接设置更改为:

 protected static final int DB_STREAMING_FETCH_AMOUNT = 50; ... Statement extrapackStreamingQuery = dbExtrapackConnection.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); extrapackStreamingQuery.setFetchSize(DB_STREAMING_FETCH_AMOUNT); 

我的url使用尾随选项:

 String fullUrl = url + host + ":" + port + "/" + dbName; if (streaming) { fullUrl += "?useCursorFetch=true"; } 

我的批处理工作现在工作正常,它完成甚至运行得更快。