为了账号安全,请及时绑定邮箱和手机立即绑定

Statement.setFetchSize(nSize)方法在SQL Server JDBC驱动

Statement.setFetchSize(nSize)方法在SQL Server JDBC驱动

开心每一天1111 2019-09-02 16:18:49
我有这个非常大的桌子,每天有数百万条记录,每天结束时我都会提取前一天的所有记录。我这样做:String SQL =  "select col1, col2, coln from mytable where timecol = yesterday";Statement.executeQuery(SQL);问题是这个程序需要2GB的内存,因为它会将所有结果都记在内存中然后处理它。我尝试设置Statement.setFetchSize(10)但它从操作系统获取完全相同的内存它没有任何区别。我正在使用Microsoft SQL Server 2005 JDBC驱动程序。是否有任何方法可以在小块中读取结果,例如Oracle数据库驱动程序在执行查询时只显示几行,当您向下滚动时会显示更多结果?
查看完整描述

3 回答

?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

在JDBC中,该setFetchSize(int)方法对于JVM中的性能和内存管理非常重要,因为它控制从JVM到数据库的网络调用的数量,以及相应的用于ResultSet处理的RAM量。

本质上,如果调用setFetchSize(10)并且驱动程序忽略它,则可能只有两个选项:

  1. 尝试使用不同的JDBC驱动程序来支持fetch-size提示。

  2. 查看Connection上的驱动程序特定属性(创建Connection实例时的URL和/或属性映射)。

RESULT-SET是响应查询而在DB上编组的行数。ROW-SET是从JVM到DB的每次调用从RESULT-SET中取出的行块。处理所需的这些调用数和生成的RAM取决于fetch-size设置。

因此,如果RESULT-SET有100行且fetch-size为10,那么将有10次网络调用来检索所有数据,在任何给定时间使用大约10 * {row-content-size} RAM。

默认的fetch-size是10,相当小。在发布的情况下,似乎驱动程序忽略了fetch-size设置,在一次调用中检索所有数据(大RAM要求,最佳最小网络调用)。

下面发生的ResultSet.next()是它实际上并没有从RESULT-SET一次获取一行。它从(本地)ROW-SET中获取它,并在本地客户端上耗尽时从服务器获取下一个ROW-SET(不可见)。

所有这一切都取决于驱动程序,因为设置只是一个“提示”,但实际上我发现这是它如何适用于许多驱动程序和数据库(在许多版本的Oracle,DB2和MySQL中验证)。


查看完整回答
反对 回复 2019-09-02
?
撒科打诨

TA贡献1934条经验 获得超2个赞

fetchSize参数是JDBC驱动程序的提示,指示要从数据库中一次获取的许多行。但是司机可以自由地忽略这一点并做它认为合适的事情。某些驱动程序(如Oracle的驱动程序)以块的形式获取行,因此您可以读取非常大的结果集而无需大量内存。其他驱动程序只需一次读取整个结果集,我猜你的驱动程序正在做什么。

您可以尝试将驱动程序升级到SQL Server 2008版本(可能更好)或开源jTDS驱动程序。


查看完整回答
反对 回复 2019-09-02
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

您需要确保关闭 Connection上的自动提交,否则setFetchSize将不起作用。

dbConnection.setAutoCommit(false);

编辑:记得当我使用此修复程序时它是Postgres特定的,但希望它仍然适用于SQL Server。


查看完整回答
反对 回复 2019-09-02
  • 3 回答
  • 0 关注
  • 2197 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信