我正在使用带存储的proc的CallableStatement来获取数据,ResultSet有12000行,处理需要30秒。我尝试设置获取大小(rs.setFetchSize(500),但仍然需要花费相同的时间来获取整个数据(30秒)。
callableStatement = conn.prepareCall(myProc);
callableStatement.setString("myParam", xyz);
callableStatement.registeroutputParameter("REVTAL", OracleTypes.CURSOR);
callableStatement .setFetchSize(1000); // I have tried with different values
rs = (ResultSet) callableStatement.getObject("REVTAL");
while(rs.next()) {`
myMethodToSetResultIntoList();
}
除了获取大小以外,还有其他可能的方法可以对其进行优化吗?
我已经试过了:
while(rs.next()) {`
logger(); // do nothing
}
它在大约3秒钟内处理了12000行,因此在从resultSet提取数据时浪费了时间。
此外,可以确认setfetchSize()正常工作,因为未设置fetch Size时,它在调试模式下将“ fetchedRowCount”显示为10,而setFetchSize()为x,则显示“ fetchRowCount”为x。
实际的while循环是这样的:
while(rs.next()) {
Myclass mc = new Myclass();
mc.setA(rs.getString("parameterA");
mc.setB(String.valueOf(rs.getLong("parameterB");
//4 more string parameters same
mc.setG(myMethodToConvertDate(rs.getDate("Date");
myList.add(mc);
}
因此,从resultSet检索数据并将其添加到myList大约需要25秒。为此必须有解决方案。
提前致谢
最佳答案
关于fetchSize的一些澄清。在您的代码中,有一个带out参数和CURSOR的CallableStatement。 SetFetchSize对CallableStatement没有影响,因为它仅返回一组结果,即out参数。在这种情况下,只有一个out参数,即CURSOR。 getCursor调用返回一个ResultSet。
最好的是,我记得JDBC规范中没有任何内容说明从CURSOR创建的ResultSet的fetchSize应该是什么。 (我的内存容易出错。)Oracle数据库JDBC驱动程序将CURSOR ResultSet的fetchSize设置为与创建它的Statement相同。
因此,在这种情况下,设置CallableStatement的fetchSize不会对CallableStatement检索到的结果产生任何影响,但是会设置从CURSOR创建的ResultSet的fetchSize。因此,宫本Us木的评论至少就CallableStatement而言是正确的,但您看到的是通过设置fetchSize看到预期行为的评论也是正确的。
遍历CURSOR ResultSet会从数据库中获取所有数据。您声明这大约需要3秒钟。处理行时大约需要20秒。设置fetchSize不会加快(或减慢)行处理速度,而只能加快数据库的获取速度。因此,在限制范围内设置fetchSize不会加快速度。 (这些限制是fetchSize必须足够大以最大程度地减少数据库往返次数,并且必须足够小以保持合理的内存占用。100通常是一个好数字。很少有更大的东西明显更好。)
但是使用fetchSize为1000时,您的代码将在3秒内获取所有行。 100可能会使您的应用程序使用更少的内存,从而使整体运行速度更快,但这是您的问题的第二要因。您真正的问题是为什么要花大约17秒才能处理12,000行?不是获取它们,而是处理它们。这取决于列的数量和类型以及它们的处理方式。您尚未提供有关这方面的任何信息。