5

Oracle シン データベース ドライバと CallableStatement を使用して Java プログラムから呼び出している Oracle 11g のストアド プロシージャがあります。このストアド プロシージャは、同じ接続のループで何千回も呼び出されます。

最初の 10 ~ 20 回のcallableStatement.execute()呼び出しでは 200 ミリ秒未満で呼び出しが返されますが、時間の経過とともにパフォーマンスが低下し始めます。200 回の呼び出しの後、callableStatement.execute()現在 600 ミリ秒かかっており、劣化が続いています。

定期的に接続を閉じると、実行時間は通常の 200 ミリ秒未満の範囲に戻ります。ドキュメントには CallableStatements がキャッシュされていないと記載されていますが、JDBC 接続で何かが正しくキャッシュされていないことは明らかです。

C プログラムで Oracle OCI ドライバーを使用して同じストアド プロシージャを実行すると、パフォーマンスの低下は見られず、200 ミリ秒未満で継続的に戻ります。

この動作に気付いた人はいますか、または 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;
4

1 に答える 1

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();
}
于 2013-12-09T14:24:05.577 に答える