我有包含 1600 万条记录的 MySql 表,由于一些迁移工作,我正在读取整个 Mysql 表。
以下代码用于在 MySql 中流式传输大型 ResultSet
statement = connection.createStatement(
java.sql.ResultSet.TYPE_FORWARD_ONLY,
java.sql.ResultSet.CONCUR_READ_ONLY);
statement.setFetchSize(Integer.MIN_VALUE);
Run Code Online (Sandbox Code Playgroud)
但这是一次流式传输一个结果,这是否意味着我们正在为每一行访问 MySql 服务器
在使用流式传输时,我们可以设置类似这样的语句:setFetchSize(1000);
我想在流式传输大型结果集时减少到服务器的往返次数
我假设您使用的是 MySQL 官方提供的 JDBC 驱动程序 Connector/J。
您明确告诉 JDBC(和 MySQL)逐行流式传输结果statement.setFetchSize(Integer.MIN_VALUE);
来自MYSQL 文档:
默认情况下,ResultSets 被完全检索并存储在内存中。在大多数情况下这是最有效的操作方式,并且由于MySQL网络协议的设计更容易实现。如果您正在使用具有大量行或较大值的结果集,并且无法在 JVM 中为所需的内存分配堆空间,则可以告诉驱动程序一次将结果流回一行。
要启用此功能,您需要按以下方式创建一个 Statement 实例:
Run Code Online (Sandbox Code Playgroud)stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY, java.sql.ResultSet.CONCUR_READ_ONLY); stmt.setFetchSize(Integer.MIN_VALUE);只进、只读结果集与获取大小 Integer.MIN_VALUE 的组合充当驱动程序的信号,以逐行流式传输结果集。此后,将逐行检索使用该语句创建的任何结果集。
Integer.MIN_VALUEMySQL 会忽略除获取大小之外的任何值,并应用标准行为。整个结果集将由 JDBC 驱动程序获取。
要么不使用setFetchSize(),以便 JDBC 驱动程序将使用默认值 ( 0),要么显式设置该值0。使用 的值0还将确保 JDBC 不使用 MySQL 游标,这可能会发生,具体取决于您的 MySQL 和 Connector/J 版本和配置。