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

MySQL Connector/J在“流式传输”结果集时是否缓冲行?

梁丘洲
2023-03-14

根据我的阅读,我认为使用MySQL JDBC驱动程序在MySQL中流式传输< code>ResultSet的方法是这两个命令:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

我的问题是,专家能否澄清使用上述代码流式传输ResultSet是否会将一行返回给客户端,然后去服务器获取下一行,依此类推(效率非常低),或者它是否足够智能,可以像BufferedStreamReader一样进行缓冲流式传输?如果它进行缓冲流式传输,如何设置缓冲区大小?

编辑:来自文档:

前向只读结果集与整数获取大小的组合。MIN_VALUE用作驱动程序的信号,以逐行流式传输结果集。之后,将逐行检索使用该语句创建的任何结果集。

这是否意味着,如果我有1000万行,那么就有1000万次到服务器的往返来获取这些行?这是非常低效的。我如何对< code>ResultSet进行流式处理,但对其进行缓冲,这样我就不必进行这么多次往返了?

EDIT2:似乎当fetchSize设置为Integer时,MySQL会自动进行一些缓冲。最小值。在我的测试中,我能够使用< code>setFetchSize(Integer)在不到20分钟的时间内读取超过4000万行。最小值)。这相当于每秒30,000行。我不知道平均行有多大,但很难想象每秒30,000次往返。

还有一个单独的问题:如果结果集的元素多于fetchSize,MySQL会怎么做?例如,结果集有10M行,fetchSize设置为1000。接下来会发生什么?

共有1个答案

夏朝
2023-03-14

当fetchSize设置为Integer.MIN_VALUE时,MySQL似乎会自动进行一些缓冲。

确实如此,至少有时是这样。我使用Wireshark测试了MySQL Connector/J版本5.1.37的行为。对于表...

CREATE TABLE lorem (
    id INT AUTO_INCREMENT PRIMARY KEY,
    tag VARCHAR(7),
    text1 VARCHAR(255),
    text2 VARCHAR(255)
    )

...使用测试数据...

 id  tag      text1            text2
---  -------  ---------------  ---------------
  0  row_000  Lorem ipsum ...  Lorem ipsum ...
  1  row_001  Lorem ipsum ...  Lorem ipsum ...
  2  row_002  Lorem ipsum ...  Lorem ipsum ...
...
999  row_999  Lorem ipsum ...  Lorem ipsum ...

(where both `text1` and `text2` actually contain 255 characters in each row)

…和代码。。。

try (Statement s = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY)) {
    s.setFetchSize(Integer.MIN_VALUE);
    String sql = "SELECT * FROM lorem ORDER BY id";
    try (ResultSet rs = s.executeQuery(sql)) {

...在s.executeQuery(sql)之后-即在rs.next()被调用之前-MySQL Connector/J已经从表中检索了第一~140行。

实际上,当仅查询标记列时

    String sql = "SELECT tag FROM lorem ORDER BY id";

MySQL Connector/J立即检索了所有1000行,如Wireshark网络帧列表所示:

将查询发送到服务器的第19帧如下所示:

MySQL服务器以第20帧作为响应,该帧以...

...紧随其后的是第21帧,它以...

...依此类推,直到服务器发送了第 32 帧,该帧以

由于唯一的区别是每行返回的信息量,我们可以得出结论,MySQL Connector / J根据每个返回行的最大长度和可用内存量来决定适当的缓冲区大小。

如果结果集的元素比 fetchSize 多,MySQL 会怎么做?例如,结果集有10M行,fetchSize设置为1000。然后会发生什么?

MySQL Connector/J最初检索第一个 fetchSize 行组,然后当 rs.next() 在它们之间移动时,它最终将检索下一组行。即使对于 setFetchSize(1) 也是如此,顺便说一句,这是一次只获取一行的方法。

(注意< code>setFetchSize(n)为n

 类似资料:
  • 正在为以下内容编写javadoc: 但是,将缓冲的输入流传入真的是一个问题吗?因此: 是否将is缓冲到bis中,或者java是否检测到is已缓冲并设置bis=is?如果是,不同的缓冲区大小是否会有所不同?如果没有,为什么不呢<注意:我说的是输入流,但实际上这个问题也适用于输出流

  • 今天早些时候很无聊,我开始思考Java中缓冲和非缓冲字节流的相对性能。作为一个简单的测试,我下载了一个相当大的文本文件,并编写了一个简短的程序来确定缓冲流在复制文件时的效果。进行了四项测试: 使用无缓冲的输入和输出字节流复制文件 毫不奇怪,使用缓冲输入和输出流比使用无缓冲流快几个数量级。然而,真正有趣的事情(至少对我来说)是案例2和案例3之间的速度差异。部分样本结果如下: 对于那些感兴趣的人,可以

  • 问题内容: 我正在开发一个使用大型MySQL表的spring应用程序。加载大表时,我得到一个,因为驱动程序试图将整个表加载到应用程序内存中。 我尝试使用 但是然后我打开的每个ResultSet都挂了; 在网上查看时,我发现发生这种情况是因为它尝试在关闭ResultSet之前尝试加载所有未读的行,但事实并非如此,因为我这样做是: 小表(3行)也会发生挂起,如果我不关闭RecordSet(在一种方法中

  • 我们有一个通过http传输文本数据的站点。其设置方式如下: 它不执行任何服务器端缓冲 当使用普通或FireFox时,文本从第一个字节流到浏览器。但是使用Chrome时,在发送1024字节之前不显示文本。之后,一切瞬间显现。 问题:有没有办法禁用这种缓冲行为? 更多信息:这里是一个简单的ASP。NET页面,该页面演示了以下行为: 具有禁用压缩的web.config: 我也有一个实时重现在http:/

  • MySQL JDBC 连接器定义了两种提取模式: < li >默认的一次获取整个结果集 < li >流,当语句fetchSize设置为整数时。最小值 根据文档,流将单独获取每一行,一次一行。 > 使用流时,每一行都在单独的数据库往返中获取,这是真的吗? MySQL服务器是预先预取结果集,还是一次遍历服务器端游标的一行?

  • 我有一个包含1600万条记录的MySql表,由于一些迁移工作,我正在读取整个MySql表。 以下代码用于在MySql中流式传输大型结果集 但这是一次流式传输一个结果,这是否意味着我们每行都命中MySql服务器 在使用流时,我们可以设置如下语句:setFetchSize(1000); 我想减少到服务器的往返次数,同时流式传输大型 ResultSet