ヘッダーをスキップ
Oracle Database JDBC開発者ガイドおよびリファレンス
11gリリース1(11.1)
E05720-02
  目次
目次
索引
索引

戻る
戻る
次へ
次へ
 

20 文キャッシュと結果セット・キャッシュ

この章では、Oracle Java Database Connectivity(JDBC)拡張要素である文キャッシュの利点と使用方法について説明します。

この章では、次の項目について説明します。


注意:

Oracle9iリリース2(9.2)以上では、Oracle9iリリース1(9.0.1)でサポートされていたApplication Program Interface(API)にかわり、Oracle JDBCによって、新しい文キャッシュ・インタフェースと実装が提供されています。以前のAPIは非推奨となりました。

文キャッシュについて

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

文キャッシュでは、次のことができます。

この項には、次の項目が含まれます。


注意:

暗黙的文キャッシュの使用を強くお薦めします。Oracle JDBCドライバは暗黙的文キャッシュが有効になっているという前提で設計されています。このため、文キャッシュを使用しないとパフォーマンスに悪影響を及ぼします。

文キャッシュの基本

アプリケーションでは、特定の物理接続に関連付けられている文をキャッシュするために文キャッシュを使用します。このキャッシュはOracleConnectionオブジェクトに関連付けられています。OracleConnectionには、文キャッシュを有効にするメソッドが含まれています。文キャッシュを有効にすると、closeメソッドをコールするときに文オブジェクトがキャッシュされます。

物理接続ごとに独自のキャッシュがあるため、複数の物理接続に対して文キャッシュを有効にすると複数のキャッシュが存在することになります。接続キャッシュで文キャッシュを有効にすると、基礎となる物理接続で有効な文キャッシュが論理接続で利用されます。接続キャッシュによって保持されている論理接続で文キャッシュを有効にしようとすると、例外が発生します。

文キャッシュには、暗黙的文キャッシュと明示的文キャッシュの2つのタイプがあります。文キャッシュの各タイプは、互いに関係なく有効化または無効化できます。いずれかを有効化するか、いずれも有効化しないか、または両方とも有効化することができます。両方のタイプの文キャッシュで、接続ごとに1つのキャッシュが共有されます。

暗黙的文キャッシュ

暗黙的文キャッシュを有効にすると、JDBCでは、プリコンパイルされたSQL文またはコール可能文の文オブジェクトのcloseメソッドをコールしたときに、その文が自動的にキャッシュされます。プリコンパイルされたSQL文およびコール可能文のキャッシュおよび取出しには、標準の接続オブジェクトおよび文オブジェクト・メソッドを使用します。

暗黙的文キャッシュはSQL文字列をキーとして使用しますが、プレーン文はSQL文字列を使用せずに作成されるため、プレーン文は暗黙的にキャッシュされません。このため、暗黙的文キャッシュは、SQL文字列を使用して作成されるOraclePreparedStatementおよびOracleCallableStatementオブジェクトにのみ適用されます。暗黙的文キャッシュをOracleStatementで使用することはできません。OraclePreparedStatementまたはOracleCallableStatementを作成するとき、JDBCドライバはキャッシュを自動的に検索し、一致する文を探します。一致基準は、次のとおりです。

  • 文内のSQL文字列は、キャッシュのSQL文字列と同一である必要があります。

  • 文の種類は、同じにする必要があります。つまり、プリコンパイルされたSQL文またはコール可能文にします。

  • 文によって生成される結果セットのスクロール可能な型は、同じにする必要があります。つまり、forward-onlyまたはscrollableにします。

キャッシュ検索中に一致するものが見つかった場合は、キャッシュされた文が戻されます。一致するものが見つからなかった場合は、新しい文が作成されて戻されます。どちらの場合でも、文は、そのカーソルおよび状態とともに、文オブジェクトのcloseメソッドをコールするとキャッシュされます。

キャッシュされたOraclePreparedStatementまたはOracleCallableStatementオブジェクトが取り出されると、状態およびデータ情報は自動的に再初期化されて、デフォルト値にリセットされますが、メタデータは保存されます。最大サイズに準拠するため、最低使用頻度(LRU)アルゴリズムを使用してキャッシュから文が削除されます。


注意:

JDBCドライバは、メタデータをクリアしません。メタデータはパフォーマンスの理由から保存されますが、セマンティクスへの影響はありません。暗黙的キャッシュによる文は、新たに作成された場合と同様に動作します。

特定の文を暗黙的なキャッシュの対象から外すことができます。

明示的文キャッシュ

明示的文キャッシュによって、プリコンパイルされたSQL文およびコール可能文を選択してキャッシュし、取り出すことができます。明示的文キャッシュは、ユーザーが指定する任意のJava Stringであるキーに依存します。


注意:

プレーン文はキャッシュできません。

明示的文キャッシュでは、メタデータの他に文データおよび状態が保持されるため、メタデータのみを保持する暗黙的文キャッシュよりもパフォーマンスの点では優れています。ただし、明示的文キャッシュでは再使用するための3つのタイプの情報がすべて保存されるため、このタイプのキャッシュを使用する場合には注意が必要です。文の前の使用で保持されているデータと状態の内容がわからない場合があるからです。

暗黙的文キャッシュと明示的文キャッシュは次の点が異なります。

  • 文の取出し

    暗黙的文キャッシュの場合は、文をキャッシュから取り出すための特別な処理は不要です。かわりに、prepareStatementまたはprepareCallをコールするたびに、JDBCでは一致する文についてキャッシュが自動的にチェックされ、見つかった場合はその文が戻されます。しかし、明示的文キャッシュの場合は、専用のOracle WithKeyメソッドを使用して、文オブジェクトをキャッシュし、取り出します。

  • キーの指定

    暗黙的文キャッシュでは、プリコンパイルされたSQL文またはコール可能文のSQL文字列がキーとして使用され、ユーザーは特にアクションを実行する必要はありません。これに対し明示的文キャッシュでは、キーとして使用するJava Stringを指定する必要があります。

  • 文の戻り

    暗黙的文キャッシュの実行中に、JDBCドライバでキャッシュ内に一致する文を見つけられない場合は、新しい文が自動的に作成されます。しかし、明示的文キャッシュの実行中にJDBCドライバでキャッシュ内に一致する文を見つけられない場合は、NULL値が戻されます。

表20-1で、暗黙的文キャッシュと明示的文キャッシュで使用されるメソッドの違いを比較します。

表20-1 文キャッシュで使用されるメソッドの比較


割当て キャッシュへの挿入 キャッシュからの取出し

暗黙的

prepareStatement prepareCall

close

prepareStatement prepareCall

明示的

createStatement prepareStatement prepareCall

closeWithKey

getStatementWithKey getCallWithKey


文キャッシュの使用方法

この項では、次の項目について説明します。

文キャッシュの有効化および無効化

OracleConnection APIを使用する場合は、暗黙的および明示的な文キャッシュは、互いに関係なく有効化または無効化できます。いずれかを有効化するか、いずれも有効化しないか、または両方とも有効化することができます。

暗黙的文キャッシュの有効化

暗黙的文キャッシュの有効化には、次の2つの方法があります。

  • 接続でsetImplicitCachingEnabled(true)をコールする方法。

  • ImplicitCachingEnabledプロパティをtrueに設定してOracleDataSource.getConnectionをコールする方法。このImplicitCachingEnabledを設定するには、OracleDataSource.setImplicitCachingEnabled(true)をコールします。

これらのメソッドの1つをコールすることに加えて、物理接続でOracleConnection.setStatementCacheSizeをコールする必要もあります。引数にはキャッシュ内の文の最大数を指定します。0(ゼロ)を指定すると、キャッシングは行われません。

暗黙的キャッシが有効化されているかどうかを判断するには、getImplicitCachingEnabledをコールします。暗黙的キャッシが有効な場合はtrueが、それ以外の場合はfalseが戻されます。


注意:

文キャッシュを有効にすると、暗黙的文キャッシュと明示的文キャッシュの両方が有効化されます。

暗黙的文キャッシュの無効化

暗黙的文キャッシュを無効化するには、接続でsetImplicitCachingEnabled(false)をコールするか、またはImplicitCachingEnabledプロパティをfalseに設定します。

明示的文キャッシュの有効化

明示的文キャッシュを有効化するには、最初に文キャッシュ・サイズを設定する必要があります。キャッシュ・サイズを設定するために、物理接続でOracleConnection.setStatementCacheSizeをコールします。引数にはキャッシュ内の文の最大数を指定します。0(ゼロ)を指定すると、キャッシングは行われません。キャッシュ・サイズのチェックには、次のようにgetStatementCacheSizeメソッドを使用します。

System.out.println("Stmt Cache size is " +
   ((OracleConnection)conn).getStatementCacheSize());

次のコードでは、キャッシュ・サイズを10の文に指定します。

((OracleConnection)conn).setStatementCacheSize(10);

接続でsetExplicitCachingEnabled(true)をコールすることにより、明示的文キャッシュを有効化します。

明示的キャッシが有効化されているかどうかを判断するには、getExplicitCachingEnabledをコールします。明示的キャッシが有効な場合はtrueが、それ以外の場合はfalseが戻されます。


注意:

  • 特定の物理接続に対しては、暗黙的キャッシュと明示的キャッシュを別々に有効化します。このため、同じセッション中で暗黙的文キャッシュと明示的文キャッシュの両方を実行できるわけです。

  • 暗黙的文キャッシュと明示的文キャッシュは同じキャッシュを共有します。文キャッシュのサイズ設定では、この点を考慮してください。


明示的文キャッシュの無効化

setExplicitCachingEnabled(false)をコールすることにより、明示的文キャッシュを無効化します。キャッシュを無効化またはクローズすると、そのキャッシュは消去されます。次の例では、明示的文キャッシュを無効化します。

((OracleConnection)conn).setExplicitCachingEnabled(false);

キャッシュされた文のクローズ

文をクローズし、それが確実にキャッシュに戻されないようにするには次の操作を行います。

  • その文のキャッシュを無効にします。

    stmt.setDisableStatementCaching(true);
    
  • 文オブジェクトのcloseメソッドをコールします。

    stmt.close();
    

キャッシュされた文の物理的なクローズ

暗黙的文キャッシュを有効にすると、文の物理的なクローズを手動で実行できなくなります。文オブジェクト・キャッシュのcloseメソッドは、文をクローズするのではなく、キャッシュします。文は、次の3つの条件で自動で物理的にクローズされます。

  • 関連付けられている接続がクローズされた場合。

  • キャッシュがそのサイズ制限に達し、LRUアルゴリズムにより、最低使用頻度の文オブジェクトが優先的に取得される場合。

  • 文キャッシュが無効にされている文でcloseメソッドをコールした場合。

暗黙的文キャッシュの使用方法

暗黙的文キャッシュを有効にすると、デフォルトではすべてのプリコンパイルされたSQL文およびコール可能文が自動的にキャッシュされます。暗黙的文キャッシュでは、次の手順が実行されます。

  1. 暗黙的文キャッシュを有効にします。

  2. 標準メソッドの1つを使用して文を割り当てます。

  3. キャッシュの対象としない特定の文に対する暗黙的文キャッシュを無効化します。これは、オプションの手順です。

  4. closeメソッドを使用して文をキャッシュします。

  5. 暗黙的にキャッシュされた文を取り出すには、適切な標準のprepareメソッドをコールします。

暗黙的キャッシュのための文の割当て

暗黙的文キャッシュに文を割り当てるには、通常prepareStatementまたはprepareCallメソッドを使用します。

次のコードでは、pstmtと呼ばれる新しい文オブジェクトを割り当てます。

PreparedStatement pstmt = conn.prepareStatement    ("UPDATE emp SET ename = ? WHERE rowid = ?");

特定の文に対する暗黙的文キャッシュの無効化

ある接続の暗黙的文キャッシュを有効にすると、デフォルトでは、その接続のすべてのコール可能文およびプリコンパイルされたSQL文が自動的にキャッシュされます。特定のコール可能文またはプリコンパイルされたSQL文が暗黙的にキャッシュされないようにするには、文オブジェクトのsetDisableStatementCachingメソッドを使用します。キャッシュ領域を管理するためには、使用頻度の低い文でsetDisableStatementCachingメソッドをコールします。

次のコードでは、pstmtに対する暗黙的文キャッシュを無効化します。

PreparedStatement pstmt = conn.prepareStatement("SELECT 1 from DUAL");
((OraclePreparedStatement)pstmt).setDisableStmtCaching(true);
pstmt.close();

注意:

JSE 6を使用している場合は、標準JDBC 4.0メソッドsetPoolableを使用して文キャッシュを無効にします。
PreparedStatement.setPoolable(false);

次のコマンドを使用してStatementオブジェクトがプール可能かどうかを確認します。

Statement.isPoolable();

文の暗黙的なキャッシュ

割り当てられた文をキャッシュするには、文オブジェクトのcloseメソッドをコールします。OraclePreparedStatementまたはOracleCallableStatementオブジェクトでcloseメソッドをコールすると、この文のキャッシュを無効化していないかぎり、JDBCドライバではこの文がキャッシュ内に自動的に挿入されます。

次のコードでは、pstmt文をキャッシュします。

pstmt.close ();

暗黙的にキャッシュされた文の取出し

暗黙的にキャッシュされた文を取り出すには、文の種類に応じて、prepareStatementまたはprepareCallメソッドをコールします。

次のコードでは、prepareStatementメソッドを使用して、キャッシュからpstmtを取り出します。

pstmt = conn.prepareStatement ("UPDATE emp SET ename = ? WHERE rowid = ?");

文を割り当てたり、暗黙的にキャッシュされた文を取り出すメソッドについて、表20-2で説明します。

表20-2 文の割当ておよび暗黙的文キャッシュで使用されるメソッド

メソッド 暗黙的文キャッシュの機能

prepareStatement

目的のキャッシュされたOraclePreparedStatementオブジェクトを検索して戻すキャッシュ検索を実行します。一致するオブジェクトが見つからない場合は、新しいOraclePreparedStatementオブジェクトを割り当てます。

prepareCall

目的のキャッシュされたOracleCallableStatementオブジェクトを検索して戻すキャッシュ検索を実行します。一致するオブジェクトが見つからない場合は、新しいOracleCallableStatementオブジェクトを割り当てます。


明示的文キャッシュの使用方法

明示的文キャッシュを有効にすると、プリコンパイルされたSQL文またはコール可能文を明示的にキャッシュできます。明示的文キャッシュでは、次の処理が行われます。

  1. 明示的文キャッシュを有効にします。

  2. 標準メソッドの1つを使用して文を割り当てます。

  3. 文を明示的にキャッシュするには、closeWithKeyメソッドを使用して、キーを付けてその文をクローズします。

  4. 明示的にキャッシュされた文を取り出すには、適切なWithKeyメソッドをコールして、適切なキーを指定します。

  5. オープンしている、明示的にキャッシュされた文を再キャッシュするには、closeWithKeyメソッドを使用して文を再度クローズします。キャッシュされた文をクローズするたびに、そのキーを使用して文を再キャッシュします。

明示的なキャッシュのための文の割当て

明示的文キャッシュに文を割り当てるには、通常createStatementprepareStatementまたはprepareCallメソッドを使用します。

次のコードでは、pstmtと呼ばれる新しい文オブジェクトを割り当てます。

PreparedStatement pstmt =    conn.prepareStatement ("UPDATE emp SET ename = ? WHERE rowid = ?");

文の明示的なキャッシュ

割り当てられた文を明示的にキャッシュするには、文オブジェクトのcloseWithKeyメソッドをコールして、キーを指定します。キーは、ユーザーが指定する任意のJava Stringです。closeWithKeyメソッドは、文をそのままキャッシュします。つまり、データ、状態およびメタデータはクリアされずに保持されます。

次のコードでは、"mykey"キーを使用してpstmt文をキャッシュします。

((OraclePreparedStatement)pstmt).closeWithKey ("mykey");

明示的にキャッシュされた文の取出し

明示的にキャッシュされた文を再度コールするには、文の種類によって、getStatementWithKeyまたはgetCallWithKeyメソッドをコールします。

指定したキーを使用して文を取り出す場合は、指定したキーに基づいて、JDBCドライバがキャッシュ内でその文を検索します。一致する文が見つかった場合、一致する文は、状態、データおよびメタデータとともに戻されます。情報は、文が最後にクローズしたときの状態で戻されます。一致する文が見つからない場合は、JDBCドライバでnullが戻されます。

次のコードでは、getStatementWithKeyメソッドで"mykey"キーを使用して、キャッシュからpstmtを再度コールします。pstmt文オブジェクトは"mykey"キーでキャッシュされていました。

pstmt = ((OracleConnection)conn).getStatementWithKey ("mykey");

pstmt文オブジェクトでcreationStateメソッドをコールすると、メソッドはEXPLICITを戻します。


重要:

明示的にキャッシュされた文を取り出す場合は、キーを指定するときに文の種類に適したメソッドを使用してください。たとえば、prepareStatementメソッドを使用して文を割り当てた場合は、getStatementWithKeyメソッドを使用してキャッシュから文を取り出します。JDBCドライバでは、戻される文の種類が検証されません。

明示的にキャッシュされた文を取り出す場合に使用するメソッドについて、表20-3で説明します。

表20-3 明示的にキャッシュされた文を取り出す場合に使用するメソッド

メソッド 明示的文キャッシュの機能

getStatementWithKey

キャッシュからプリコンパイルされたSQL文を取り出すのに必要なキーを指定します。

getCallWithKey

キャッシュからコール可能文を取り出すのに必要なキーを指定します。


文オブジェクトの再利用

JDBC 3.0の仕様で導入された文プーリングでは、アプリケーションは、Connectionオブジェクトの使用と同様にしてPreparedStatementオブジェクトを再利用することができます。PreparedStatementオブジェクトは、複数の論理接続が透過的に再利用できます。

この項には、次の項目が含まれます。

プールされた文の使用

StatementインタフェースからisPoolableメソッドをコールすることによって、データソースが文プーリングをサポートするかどうかを認識できます。戻り値がtrueの場合、アプリケーションはPreparedStatementオブジェクトがプールされていることを認識しています。アプリケーションはまた、StatementインタフェースからsetPoolableメソッドをコールすることによって、文がプールされるようにするかどうかを指定することができます。

プールされた文の再利用はアプリケーションに対して完全に透過的です。つまり、PreparedStatementオブジェクトが文プーリングに参加してもしなくても、アプリケーション・コードは変わりません。アプリケーションがPreparedStatementオブジェクトをクローズする場合、それを再利用するには、やはりConnection.prepareStatementメソッドをコールする必要があります。


注意:

文がどのようにプールされるかをアプリケーションが直接制御することはありません。文のプールはPooledConnectionオブジェクトに関連付けられています。このオブジェクトの動作は、それを作成したConnectionPoolDataSourceオブジェクトのプロパティによって決まります。

プールされた文のクローズ

アプリケーションがプールする文をクローズする方法は、プールされていない文をクローズする方法とまったく同じです。文がクローズされると、それがプールされた文かどうかに関係なく、アプリケーションがその文を使用することはできません。それを再利用しようとすると例外が発生します。目に見える唯一の相違は、プールされている物理文をアプリケーションが直接クローズすることができないということです。それを実行するのはプール・マネージャです。メソッドPooledConnection.closeAllは指定された物理接続上でオープンされているすべての文をクローズします。これにより、それらの文に関連付けられているリソースが解放されます。

次のメソッドは、プールされた文をクローズすることができます。

  • close

    このjava.sql.Statementインタフェース・メソッドはアプリケーションによってコールされます。文がプールされる場合、アプリケーションが使用する論理文はクローズされますが、プールされた物理文はクローズされません。

  • close

    このjava.sql.Connectionインタフェース・メソッドはアプリケーションによってコールされます。このメソッドは、文を使用する接続がプールされるかどうかに応じて、異なる動作をします。

    • プールされていない接続

      このメソッドは、物理接続が作成したすべての接続とすべての文をクローズします。こうする必要があるのは、外部的に管理されているリソースをいつ解放できるかは、ガーベジ収集メカニズムで検出できないためです。

    • プールされた接続

      このメソッドは論理接続とそれが戻した論理文をクローズしますが、その基礎となるPooledConnectionオブジェクトや、関連付けられているプールされた文はオープンされた状態に残します。

  • PooledConnection.closeAll

    このメソッドは、PooledConnectionオブジェクトによってプールされる物理文をすべてクローズするために接続プール・マネージャによってコールされます。

結果セット・キャッシュ

アプリケーションでは、データベースに問合せを繰返し送信することがあります。繰返しの問合せのレスポンス時間を改善するには、問合せの結果、問合せフラグメントおよびPL/SQLファンクションをメモリーにキャッシュできます。結果キャッシュには、すべてのセッションにわたって共有される問合せの結果が格納されます。これらの問合せを繰返し実行すると、結果がキャッシュ・メモリーから直接取り出されます。

結果が問合せ結果キャッシュに格納されることを示すには、問合せまたは問合せフラグメントに結果キャッシュのヒントで注釈を付ける必要があります。

問合せ結果セットは、次の方法でキャッシュできます。

サーバー側キャッシュ

Oracle Database 11gリリース1(11.1)では、両方のJDBC型でサーバー側結果セット・キャッシュがサポートされています。サーバー側結果キャッシュは、現在の問合せ、問合せフラグメントおよびPL/SQLファンクションの結果をメモリーにキャッシュし、その問合せ、問合せフラグメントまたはPL/SQLファンクションをその後実行する際に、キャッシュした結果を使用するためのものです。キャッシュした結果はSGAの結果キャッシュ・メモリー部分に存在します。結果キャッシュを作成したときに使用されたデータベース・オブジェクトが正常に変更されると、キャッシュされた結果は自動的に無効になります。サーバー側キャッシュには、次の2つのタイプがあります。

  • SQL問合せ結果キャッシュ

  • PL/SQLファンクション結果キャッシュ


関連項目:

  • SQL問合せ結果キャッシュの詳細は、『Oracle Databaseパフォーマンス・チューニング・ガイド』を参照してください。

  • PL/SQLファンクション結果キャッシュの詳細は、『Oracle Database PL/SQL言語リファレンス』を参照してください。


クライアント結果キャッシュ

Oracle Database 11gリリース1(11.1)では、JDBC OCIクライアントに対してクライアント結果キャッシュのサポートが導入されています。クライアント結果キャッシュは、問合せ結果セットをキャッシュすることで、次回以降の問合せ実行がサーバーから行をフェッチせずキャッシュされた結果にアクセスすることを可能にし、アプリケーションのパフォーマンスを改善します。これにより、キャッシュされた結果を取り出すためにサーバーに何度もラウンドトリップを行うことがなくなり、CPUの使用量が減少します。クライアント結果キャッシュでは、キャッシュされた結果セットに影響を与える可能性のあるすべてのセッション状態やデータベース変更と一致するように、結果セットを透過的に維持します。これにより、回数の多いクライアントのSQL問合せ実行や行のフェッチでの応答時間が大幅に改善されます。消費されるCPU時刻が減少するため、サーバーでのスケーラビリティは向上します。