对于oracle引用游标,ResultSet.next()太慢了

时间:2014-11-19 13:34:53

标签: java oracle jdbc resultset slowdown

我从java调用oracle过程并返回一个ref游标作为结果。我将ref光标转换为ResultSet,迭代从它开始。

String query = "{call ...(...)}";
CallableStatement stmt = conn.prepareCall(query,ResultSet.TYPE_FORWARD_ONLY,
                ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(10000); 
.
.
.
stmt.registerOutParameter(x, OracleTypes.CURSOR);
stmt.execute();
Resultset rs = (ResultSet) stmt.getObject(x);

while (rs.next()) {    /** Problem occurs here **/
    ...
}

问题是某些特定记录的SOMETIMES(并非总是)ResultSet.next()方法花费的时间太长(如100秒)。需要提及的是,返回记录的数量最多为25,并且数据库中的相同查询行为正常执行(在大约6秒内执行)。

当我调查更多时,我发现我的返回光标中有一列如果删除了这个问题就不会发生。该列实际上是ROWNUM(),它包含在结果游标中。

--ORACLE Query snippet:
OPEN result_cursor FOR 
SELECT "FirstName","LastName", r 
  FROM (SELECT ROWNUM r, *
         ... -- query details
         WHERE ROWNUM <= 25)

我甚至没有触摸ResultSet中的那个字段,但它仍然会导致这个问题(这似乎不公平:()。我试图将它转换为Oracle过程中的字符串(通过将其与&#39连接) ;&#39;),假设类型转换可能会导致此问题,但它在情况上没有任何区别。 为什么会这样?

1 个答案:

答案 0 :(得分:1)

您正在谈论的字段ROWNUM()是一个可更改的值,因为可能会插入可能实际更改绝对行号的行 - 然后需要在执行获取操作时重新计算,以解释任何自上次提取调用以来,从游标返回的表中插入或删除。每次调用rs.next()都会导致获取操作,因为这个列是一个可更改的值,即使你很快得到了其余的结果。

这是因为在导航ResultSet时使用引用游标KEEPS THE SELECT OPEN。