我必须改进一些从Java程序调用Oracle存储过程的代码。目前代码真的非常慢:在我的开发机器上高达大约8秒钟。在同一台机器上,如果我直接调用一个执行相同处理并返回相同数据的SQL查询,则需要100 ms ...为什么从Oracle存储过程中检索ResultSet非常慢?
该代码创建一个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 ms。
代码有什么问题吗?我如何改进它?如果我没有任何其他解决方案,我会直接在SQL中执行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'? – 2010-05-27 15:31:25
我必须将CallableStatement强制转换为OracleCallableStatement,但我使用的是DBCP,而CallableStatement实际上是DBCP提供的“代理”,所以我会得到一个异常(我试过了)。 – 2010-05-27 15:47:50
对于抓取,要通过网络进行优化,您应该使用setRowPrefetch。这产生了巨大的影响。虽然setFetchSize约为20-30%,但在大型数据集上预取可高达10倍。 – zhrist 2016-08-11 11:44:12