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 交谈时挂起

在 Java JDBC 中将行插入没有更新方法的 ResultSet

JDBC——ResultSet结果集对象

使用JDBC从数据库中查询数据