【发布时间】:2015-01-17 01:12:36
【问题描述】:
我从 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 **/
...
}
问题在于,对于某些特定记录,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 过程中将其转换为字符串(通过将其与 ' ' 连接),假设类型转换可能会导致此问题,但对情况没有影响。 为什么会这样?
【问题讨论】:
-
我想,将您的 fetch 大小设置得如此之高会浪费内存,并且可能会花费大量时间来设置和拆除结构。您是从最终选择列表中排除
r,还是删除rownum <= 25过滤器;大概你那里有一个order by,你也要删除它吗? -
@AlexPoole :我已将获取大小设置为不同的值(10、25、...),但没有任何区别。我只是从最终选择列表中排除 r 并且查询正文保持不变。感觉是ref cursor to ResultSet转换导致这个问题,但是找不到原因。
-
也许你有一个糟糕的查询执行计划,其中包括
r;如果您使用的是 10g,我想知道绑定变量窥视,特别是如果它是间歇性的。您能否检查两个查询的执行计划(使用相同的绑定值)? -
在会话上运行 oracle 跟踪并在其上运行 tkprof。
-
我在外部 oracle SP 中调用 SP 之前和之后记录,日志时间显示 SP 已在 DB 级别在适当的时间执行。另外,正如我所说,从数据库客户端(如navicat)调用SP时不会发生这种情况。我在navicat中获取光标并对其进行迭代,一切都很好,没有人受伤。但是 java 中的相同 SP 调用(使用 JDBC)会导致上述问题。所以这似乎不是一个执行计划 DB-Side 问题。但无论如何我都会听从你的建议以获取更多线索。
标签: java oracle jdbc resultset slowdown