【发布时间】:2011-02-24 17:15:04
【问题描述】:
我必须改进一些从 Java 程序调用 Oracle 存储过程的代码。目前代码真的很慢:在我的开发机器上最多大约 8 秒。在同一台机器上,如果我直接调用一个执行相同处理并返回相同数据的 SQL 查询,则需要不到 100 毫秒...
代码创建一个 CallableStatement,将输出参数之一注册为 Oracle 游标,然后使用语句的 getObject 方法检索游标并将其解析为 ResultSet:
cstmt = conn.prepareCall("{ call PKG_ESPECEW.P_ListEspece( ?, ?, ?, ?, ?, ? ) }");
cstmt.registerOutParameter(4, oracle.jdbc.OracleTypes.CURSOR);
[...]
cstmt.executeQuery();
rs = (ResultSet)cstmt.getObject(4);
rs.setFetchSize(1000); //supposed to help ?
options = new HashMap<String, String>(1000);
rs.next() //added that to measure exactly the length of the first call
while(rs.next()) {
[...]
}
我在代码中添加了一些时间戳,以了解哪个部分花费了这么长时间。结果:对rs.next() 的第一次调用最多需要几秒钟。结果集是平均的,从 10 到几千行。正如我之前所说,处理来自常规 PreparedStatement 的类似结果集需要 10-100 毫秒,具体取决于大小。
代码有什么问题吗?我该如何改进它?如果我没有任何其他解决方案,我会在关键的地方直接执行 SQL,但我更喜欢允许我不重写所有过程的解决方案!
这里是存储过程的定义:
PROCEDURE P_ListEspece(P_CLT_ID IN ESPECE.ESP_CLT_ID%TYPE, -- Langue de l'utilisateur
P_ESP_GROUP_CODE IN ESPECE.ESP_CODE%TYPE,-- Code du groupe ou NULL
P_Filter IN VARCHAR2, -- Filtre de la requête
P_Cursor OUT L_CURSOR_TYPE, -- Curseur
P_RecordCount OUT NUMBER, -- Nombre d'enregistrement retourne
P_ReturnStatus OUT NUMBER); -- Code d'erreur
【问题讨论】:
-
有什么理由不使用
OracleCallableStatement.getCursor而不是getObject? -
我必须将 CallableStatement 转换为 OracleCallableStatement,但我使用的是 DBCP,而 CallableStatement 实际上是 DBCP 提供的“代理”,所以我会得到一个异常(我试过了)。跨度>
-
对于获取,要通过网络优化它,您应该使用 setRowPrefetch。这具有巨大的影响。使用 setFetchSize 大约为 20-30% 时,Prefetch 在大型数据集上可以达到 10 倍。