CallableStatement的性能下降

Sam*_*ain 5 java oracle stored-procedures jdbc callable-statement

我在Oracle 11g中有一个存储过程,我使用Oracle瘦数据库驱动程序和CallableStatement从Java程序调用.在同一连接上循环调用此存储过程数千次.

callableStatement.execute()在<200毫秒的第10-20电话呼叫的回报,但是,性能开始随着时间的推移.200次通话后,callableStatement.execute()现在需要600ms,并继续降级.

如果我定期关闭连接,执行时间将恢复到正常的<200ms范围.显然,JDBC连接中的某些内容被错误地缓存,尽管文档声明CallableStatements未被缓存.

在C程序中使用Oracle OCI驱动程序运行相同的存储过程不会导致性能下降,并且会在<200ms内连续返回.

有没有人注意到这种行为或对Java的解决方法有任何想法?

编辑:这是多次运行的代码部分; 连接是共享的,每次循环都会创建CallableStatement.如果CallableStatement被缓存,则没有任何改进.

   oracle_conn_time = System.currentTimeMillis();
   OracleConnection oracle_conn = (OracleConnection) conn.getMetaData().getConnection();
   oracle_conn.setStatementCacheSize(1);
   oracle_conn_time = System.currentTimeMillis() - oracle_conn_time;

   list_time = System.currentTimeMillis();
   var_args= oracle_conn.createARRAY("ARG_LIST", args.toArray());
   list_time = System.currentTimeMillis() - list_time;

   sql       = "{? = call perform_work(?,?,?,?)}";

prepare_time = System.currentTimeMillis();
ocs = (OracleCallableStatement) oracle_conn.prepareCall(sql);
prepare_time = System.currentTimeMillis() - prepare_time;

bind_time = System.currentTimeMillis();
    ocs.registerOutParameter(1, OracleTypes.ARRAY, "RESPONSEOBJ");

    ocs.setInt(  2, 77);
    ocs.setInt(  3, 123456);
    ocs.setArray(4, var_args);
    ocs.setInt(  5, 123456789);
    bind_time = System.currentTimeMillis() - bind_time;

//execute_time is the only timer that shows degradation
execute_time = System.currentTimeMillis();
    ocs.execute();
execute_time = System.currentTimeMillis() - execute_time;

results_time = System.currentTimeMillis();
    Array return_objs = ocs.getArray(1);
results_time = System.currentTimeMillis() - results_time;

oracle_time = System.currentTimeMillis() - oracle_time;
    parse_time = System.currentTimeMillis();

    Clob[] clobs = (Clob[]) return_objs.getArray();

    return_objs.free();

//Removed clob management code

parse_time = System.currentTimeMillis() - parse_time;
Run Code Online (Sandbox Code Playgroud)

Sam*_*ain 0

当存储过程返回一个 Clob 数组时,代码只是直接释放该数组,而不是底层的 Clob 对象。

添加对 Clob 对象的调用free消除了性能下降。

我假设当 Clob 对象被垃圾收集时,free本质上是在 中调用的finalize,但我怀疑 Oracle Connection 对象持有对所使用的任何 Clob 对象的引用,从而防止它被垃圾收集。我的想法很愚蠢,但希望这能帮助别人避免在未来被绊倒。

Array return_objs = ocs.getArray(1);

Clob[] clobs = (Clob[]) return_objs.getArray();

return_objs.free();

for(int i = 0; i < clobs.length; i++ )
{
    //Utilize clob

    clobs[i].free();
}
Run Code Online (Sandbox Code Playgroud)