为何执行ResultSet获取大小代码后,迭代耗时大幅降低?
为什么执行ResultSet滚动操作后迭代速度暴增?
先把你的代码贴出来方便大家理解:
int size =0; if (rs != null) { rs.last(); size = rs.getRow(); rs.beforeFirst(); } // 后续迭代逻辑 while (rs.next()) { // 处理每行数据 }
你观察到的迭代耗时从500ms骤降到50ms,核心原因是这段滚动操作彻底改变了JDBC驱动加载结果集的方式:
默认的流式加载拖慢了速度:大多数JDBC驱动在处理默认的
TYPE_FORWARD_ONLY类型ResultSet时,会用流式获取的策略——不会一次性把所有查询结果拉到客户端内存,而是每次只取一小批数据(比如10行,具体由驱动的fetchSize参数控制)。当你调用rs.next()迭代时,每用完当前批次的数据,就得和数据库再通信一次去拉取下一批,频繁的网络交互就是初始迭代慢的元凶。滚动操作触发了全量缓存:当你调用
rs.last()时,驱动必须定位到结果集的最后一行,这就逼着它把所有查询结果一次性加载到客户端的内存里(不然根本不知道最后一行在哪)。之后调用rs.beforeFirst()回到结果集开头,后续的rs.next()就直接从本地内存读数据,完全不用再跟数据库打交道,速度自然就上去了。
还要补充几个关键细节:
- 这种操作能生效的前提是你的ResultSet是可滚动类型(比如
TYPE_SCROLL_INSENSITIVE或TYPE_SCROLL_SENSITIVE)——如果你的代码能执行rs.last(),说明你创建Statement/PreparedStatement时指定了这个类型。 - 别盲目用这种方法:如果结果集特别大(比如几十万行),全量加载会吃掉大量客户端内存,搞不好会触发
OutOfMemoryError。如果只是想知道结果集大小,不如单独执行SELECT COUNT(*) FROM ...查询,避免加载全量数据。
内容的提问来源于stack exchange,提问作者Giacomo Chiavarini
相关产品推荐
相关产品推荐

