ひでっぷの技術メモ

はてなダイアリーから移行しました

文キャッシュの使用方法

ある客先で作成したアプリがメモリ・リークするとのことで色々調べていると以下のような情報があった。
Oracle JDBC Drivers README

大きいCHAR列またはVARCHAR列を含む表でPreparedStatementを使用すると、
メモリー・リークが発生します。
この問題は、文キャッシュを使用可能にすると回避できます。

作成したアプリケーションはある期間のログから特定の文字列がはいっている件数をカウントするというもので、確かに長い文字列(100byte)からPreparedStatementを使用してResultSetをとるという処理を頻繁に行うものでした。
これが該当してるっぽいけど、文キャッシュって何?
もうちょっと調べてみたらこんなものだそうです。
Oracle Database JDBC開発者ガイドおよびリファレンス 10g リリース2(10.2) 22.文キャッシュ

文キャッシュにより、繰り返しコールされるループやメソッドなどで何度も使用する実行文がキャッシュされるため、パフォーマンスが向上します。JDBC 3.0では、文キャッシュ・インタフェースが定義されています。

文キャッシュを使用して、次のことを実行できます。

  • カーソル作成の繰返しによるオーバーヘッドを回避します。
  • 文の解析と作成の繰返しを回避します。
  • クライアント内のデータ構造を再利用します。

ほー。ってか文キャッシュを使用する設定をしないとだめなのね・・・。
以下設定方法。

今回は暗黙的文キャッシュを使用。
こちらだとPreparedStatementで使用した文字列を自動的にキャッシュしてくれて、次回PreparedStatement使用時にキャッシュから探してくれる。
使用方法はOracleConnectionクラスにてImplicitiCachingEnabledプロパティを有効にしてキャッシュサイズを設定する。


((OracleConnection)connection).setImplicitiCachingEnabled(true);
((OracleConnection)connection).setStatementCachSize(1024);

キャッシュサイズは1024にしてみた。SQL1文につきキャッシュ1つだから引数を?で表記して後から引数を入れるPreparedStatementの場合は十分だと思う。
以上で設定終わり。
PreparedStatementがcreateされる時にキャッシュから同一文がないか探してくれてcloseする時にキャッシュへ挿入される。


OraclePreparedStatement ps =
connection.preparedStatement("SELECT * FROM hogehoge WHERE ID = ?");

↑キャッシュ内に"SELECT * FROM hogehoge WHERE ID = ?"という文字列がないか探す。
あればキャッシュを使用し、なければ新しく生成する。


ps.close();

↑キャッシュに挿入される。

設定は簡単だけれど、実際に有効になっているのかがよくわからない・・・。
今のところリークしてないようだから有効になってるんだろう。