当前位置: 首页 > 知识库问答 >
问题:

有没有一个mysql JDBC会尊重fetchSize?

倪棋
2023-03-14

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

相反,我想插入一个JDBC实现,它将与MySQL一起使用并适当尊重获取大小,允许我将获取大小设置为10,000或其他更高的限制。有人能给我指出一个可以提供这种实现的jar吗?如果没有,还有任何其他资源允许我以高效的方式合理地执行包含数以万计条目的查询,但需要内存和sql查询数量。

共有3个答案

子车芷阳
2023-03-14

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

对于批处理作业,我需要打开流模式,因为我的结果集太大了。首先,正如在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时间范围。

事实上,如果一个数据库连接打开了,但是在足够长的时间内没有发送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";
}

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

邵耀
2023-03-14

从技术上讲,向图书馆提出的问题是离题的。也就是说,据我所知,MySQL没有其他驱动程序。您可以选择获取可能导致内存不足的所有行,或者通过设置<code>setFetchSize(Integer.MIN_VALUE)

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

另一种选择是一行一行地检索,但这带来了一个问题,即在处理< code>ResultSet时,不能在同一连接上执行其他语句:

这种方法有一些警告。在对连接发出任何其他查询之前,必须读取(或关闭)结果集中的所有行,否则将引发异常

因此,MySQL只能选择获取所有内容或一次获取一个。这意味着驱动程序无法尊重不同的获取大小。由于在逐个获取时的注意事项,他们选择使用<code>整数。MIN_VALUE(而不是简单的<code>1)作为一个信号,您应该在执行此操作之前认真考虑。

一种可能的“中间”解决方案需要您使用<code>LIMIT并重复执行查询来编程。

东方修谨
2023-03-14

如果启用MySQL JDBC选项<code>useCursorFetch</code>,则驱动程序确实会尊重fetchSize。

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

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

 类似资料:
  • 我不知道为什么背压在这个流动链中没有得到尊重。 我将其简化为以下三个阶段:,和。前两个阶段的速度比最后一个阶段快得多,因此它们的输出会让内存等待第3步,从而导致内存不足错误/内存使用量不断增加。 当我观看调试器时,我注意到步骤1比步骤3更频繁地发生,尽管我已经将缓冲区大小(observeOn的第三个参数)设置为一个较低的数字(例如1)。 我已经阅读了我正在使用的每个运算符的留档,看起来他们都有一些

  • 我如何获得所有列没有一个特定的? 示例:如果我有一个包含n列的dataframe、、...,如何获得没有的所有列?

  • 更新2 在较新版本的Sprint Boot上再次遇到此问题,不得不改为:

  • 问题内容: 根据MDN 文档: 该 方法冻结对象:即,防止向其添加新属性;防止现有属性被删除;并防止更改现有属性或其可枚举性,可配置性或可写性。本质上,对象实际上是不可变的。该方法返回被冻结的对象。 我期望在某个日期调用冻结会阻止对该日期进行更改,但是它似乎没有用。这是我正在做的(运行Node.js v5.3.0): 我本以为调用会失败或什么都不做。任何想法如何冻结日期? 问题答案: 有没有办法O

  • 是否可以像所附图像一样在表格中放置一个按钮?

  • 在Android上使用phonegap创建了一个应用程序。 一切都很好,除了视频不会以任何形式播放。只有音频。 错误: E/libEGL(1441):在没有当前上下文的情况下调用OpenGL ES API(每个线程记录一次) 尝试使用非嵌入式视频,不同的格式,不同的嵌入,改变config.xml设置,基本上大约30-40种不同的解决方案。并且已经为此工作了40多个小时。 大约11个月前,我在Pho