JDBC ResultSet 方法 next() 需要 30 秒来获取 12000 行
Posted
技术标签:
【中文标题】JDBC ResultSet 方法 next() 需要 30 秒来获取 12000 行【英文标题】:JDBC ResultSet method next() is taking 30 seconds to fetch 12000 rows 【发布时间】:2017-08-18 13:53:50 【问题描述】:我正在使用带有存储过程的 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();
除了 fetch Size 之外,还有什么可能的方法来优化它吗?
我试过这个:
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 秒。必须有一个解决方案。
提前致谢
【问题讨论】:
我认为您只有一个返回值,即CURSOR
。所以setFetchSize()
不会有任何效果,因为它只加载一行...试试SELECT * FROM "myProc"(?)
Iterating a ResultSet using the JDBC for Oracle takes a lot of time about 16s?的可能重复
我认为 setFetchSize() 正在按预期工作,我已经尝试调试我的代码,并且在 rowCount 中它实际上显示了我在 setFetchSize() 中设置的数字。
我已经尝试过上述线程提供的解决方案,提供的解决方案是 setFetchSize()。
Java 中没有While
【参考方案1】:
关于 fetchSize 的一点说明。在您的代码中有一个带有 out 参数和 CURSOR 的 CallableStatement。 SetFetchSize 对 CallableStatement 没有影响,因为它只返回一组结果,即 out 参数。在这种情况下,只有一个输出参数,即 CURSOR。 getCursor 调用返回一个 ResultSet。
我记得最好在 JDBC 规范中没有说明从 CURSOR 创建的 ResultSet 的 fetchSize 应该是什么。 (我记错了。)Oracle 数据库 JDBC 驱动程序将 CURSOR ResultSet 的 fetchSize 设置为与创建它的 Statement 相同。
因此,在这种情况下,设置 CallableStatement 的 fetchSize 对 CallableStatement 检索到的结果没有任何作用,但它确实设置了从 CURSOR 创建的 ResultSet 的 fetchSize。因此,Usagi Miyamoto 的评论至少在 CallableStatement 方面是正确的,但您关于通过设置 fetchSize 看到预期行为的评论也是正确的。
遍历 CURSOR ResultSet 会从数据库中获取所有数据。您说这大约需要 3 秒。当您处理行时,大约需要 20 秒。设置 fetchSize 不会加快(或减慢)行处理速度,只会加快数据库提取速度。所以在限制内设置 fetchSize 不会加快速度。 (这些限制是 fetchSize 必须足够大以最大程度地减少数据库往返次数,并且必须足够小以保持合理的内存占用。100 通常是一个不错的数字。很少有更大的数字明显更好。)
但是如果 fetchSize 为 1000,您的代码将在 3 秒内获取所有行。 100 可能会让您的应用程序总体上运行得更快,因为它使用更少的内存,但这对您的问题来说是次要的。你真正的问题是为什么处理 12,000 行需要大约 17 秒?不是获取它们,而是处理它们。这是列的数量和类型以及如何处理它们的函数。您没有提供这方面的任何信息。
【讨论】:
以上是关于JDBC ResultSet 方法 next() 需要 30 秒来获取 12000 行的主要内容,如果未能解决你的问题,请参考以下文章
Java -- JDBC 学习--通过 ResultSet 执行查询操作
MYSQL 之 JDBC: 增删改查通过ResultSet执行查询操作
ResultSet.next() 在使用 jdbc 与 oracle 11.2 交谈时挂起