参数
fetchSize
Statement接口中是这样解释的:
为JDBC 驱动程序提供一个提示,它提示此Statement 生成的ResultSet 对象需要更多行时应该从数据库获取的行数。指定的行数仅影响使用此语句创建的结果集合。如果指定的值为 0,则忽略该提示。默认值为 0。
ResultSet中是这样解释的:
为 JDBC 驱动程序设置此ResultSet 对象需要更多行时应该从数据库获取的行数。如果指定的获取大小为零,则 JDBC 驱动程序忽略该值,随意对获取大小作出它自己的最佳猜测。默认值由创建结果集的Statement 对象设置。获取大小可以在任何时间更改。
网上有下面这样的一段摘录1:
缺省时,驱动程序一次从查询里获取所有的结果。这样可能对于大的数据集来说是不方便的, 因此 JDBC 驱动提供了一个用于设置从一个数据库游标抽取若干行的 ResultSet 的方法。在连接的客户端这边缓冲了一小部分数据行,并且在用尽之后, 则通过重定位游标检索下一个数据行块。
摘录2:
setFetchSize 最主要是为了减少网络交互次数设计的。访问ResultSet时,如果它每次只从服务器上取一行数据,则会产生大量的开销。setFetchSize的意 思是当调用rs.next时,ResultSet会一次性从服务器上取得多少行数据回来,这样在下次rs.next时,它可以直接从内存中获取出数据而不 需要网络交互,提高了效率。 这个设置可能会被某些JDBC驱动忽略的,而且设置过大也会造成内存的上升。
注:不同数据库实现不同,如mysql默认一次取回全部,如需生效则要使用下面的方式;
区别
1.常规查询,一次性读取 数据到 JVM 内存中,或者分页读取; 2.流式查询,建立长连接,利用服务端游标,每次读取一条加载到 JVM 内存;
流式查询有一点需要注意:必须先读取(或关闭)结果集中的所有行,
然后才能对连接发出任何其他查询,否则将引发异常;
使用流式查询,则要保持对产生结果集的语句所引用的表的并发访问,
因为其 查询会独占连接,所以必须尽快处理;
3.游标查询,和流式一样,通过 fetchSize 参数,控制一次读取多少条数据;
流式查询、游标查询可以避免 OOM,数据量大可以考虑此方案。
但是这两种方式会占用数据库连接,使用中不会释放,
所以线上针对大数据量业务用到游标和流式操作,一定要进行并发控制
适合场景
一次性查询大量不分页数据,使用后就释放,避免oom;如使用工具将数据写入excel;
编码方式
1.使用游标迭代器Cursor
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE)
Cursor<WfGoodsOrderEntity> queryCursor();
Cursor<WfGoodsOrderEntity> cursor = orderDao.queryCursor();
LongAdder adder = new LongAdder();
cursor.forEach(wfGoodsOrderEntity -> {
});
注意,由于需要始终保持数据库连接,需要配合使用@Transactional
2.使用ResultHandler
@Options(resultSetType = ResultSetType.FORWARD_ONLY, fetchSize = Integer.MIN_VALUE)
void queryCursor2(ResultHandler<WfGoodsOrderEntity>result);
<select id="queryCursor2" resultType="com.wfcm.entity.WfGoodsOrderEntity">
select
*
from
wf_goods_order
</select>
orderDao.queryCursor2(resultContext -> {
WfGoodsOrderEntity resultObject = resultContext.getResultObject();
});
本文由 GY 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2022/05/06 14:18