了解 SQL Server JDBC 驱动程序中 Statement.setFetchSize(nSize) 方法的功能
P粉463811100
2023-08-27 17:05:57
<p>我有一个非常大的表,每天都有数百万条记录,每天结束时我都会提取前一天的所有记录。我这样做是这样的:</p>
<pre class="brush:php;toolbar:false;">String SQL = "select col1, col2, coln from mytable where timecol = yesterday";
Statement.executeQuery(SQL);</pre>
<p>问题是这个程序需要大约 2GB 内存,因为它将所有结果放入内存中然后对其进行处理。 </p>
<p>我尝试设置 <code>Statement.setFetchSize(10)</code> 但它从操作系统中获取完全相同的内存,没有任何区别。我为此使用<em>Microsoft SQL Server 2005 JDBC 驱动程序</em>。</p>
<p>是否有任何方法可以像 Oracle 数据库驱动程序那样以小块形式读取结果,当执行查询时仅显示几行,并且当您向下滚动时会显示更多结果?</p>
在 JDBC 中,
setFetchSize(int)
方法对于 JVM 内的性能和内存管理非常重要,因为它控制从 JVM 到数据库的网络调用数量以及相应的数据量。用于结果集处理的 RAM。本质上,如果调用 setFetchSize(10) 并且驱动程序忽略它,则可能只有两个选项:
RESULT-SET 是为响应查询而在数据库上编组的行数。 ROW-SET 是每次从 JVM 调用到 DB 时从 RESULT-SET 中提取的行块。 这些调用的数量以及处理所需的 RAM 取决于 fetch-size 设置。
因此,如果 RESULT-SET 有 100 行并且 fetch-size 为 10, 在任何给定时间,都会有 10 个网络调用来检索所有数据,使用大约 10*{row-content-size} RAM。
默认的 fetch-size 是 10,这个值相当小。 在发布的案例中,驱动程序似乎忽略了获取大小设置,在一次调用中检索所有数据(需要大量 RAM,最佳最小网络调用)。
在
ResultSet.next()
下发生的情况是,它实际上并没有从 RESULT-SET 中一次获取一行。它从(本地)ROW-SET 获取该数据,并在本地客户端上的数据耗尽时从服务器获取下一个 ROW-SET(不可见)。所有这些都取决于驱动程序,因为设置只是一个“提示”,但在实践中我发现这就是许多驱动程序和数据库的工作原理(在许多版本的 Oracle、DB2 和 MySQL 中得到验证)。 p>