[Oracle] データベース・バッファ・キャッシュの中身を知る方法 | Archive Redo Blog

Archive Redo Blog

DBエンジニアのあれこれ備忘録

データベース・バッファ・キャッシュのヒット率が低く、パフォーマンスが出ない場合、普通はデータベース・バッファ・キャッシュのサイズを増やすことによって対処しますが、全表走査が多く行われていることなどが原因でデータベース・バッファ・キャッシュが無駄なデータによって占有されている場合は、無駄なデータが不用意にキャッシュされないようデータ構造やアプリケーションを改善することによって、キャッシュヒット率を向上させることも可能です。


というか、その方が無駄にリソースが消費されないためベターでしょう。

このようなチューニングを行う場合、データベース・バッファ・キャッシュに実際にどのようなデータがどれだけキャッシュされているかを知ることができればより効率よくチューニングを行うことができます。



データベース・バッファ・キャッシュの中身はX$BHというテーブルを見ればわかるようです。


X$BHにはデータベース・バッファ・キャッシュに格納されているデータブロックのヘッダー情報が格納されています。

これらのブロックが実際にどのオブジェクトのデータブロックなのかを辿るためにはOBJ列を使います。


OBJはDBA_OBJECTSのOBJECT_IDを示しているので、以下のようにX$BHとDBA_OBJECTSと結合すれば、データベース・バッファ・キャッシュにどのテーブルのブロックがどれだけ格納されているかが一目瞭然です。

select b.obj, o.object_name, count(*) blocks, b.lru_flag, b.tch
  from x$bh b
  left outer join dba_objects o
    on b.obj = o.object_id
  group by b.obj, o.object_name, b.lru_flag, b.tch


なお、この例ではLRU_FLAGとTCHという列を追加しています。LRU_FLAGは、該当ブロックがLRU(Last Recent Used)リストの中でどのように見られているかを表すフラグで、8は残留候補、2は追い出し候補、0はどちらでもないブロックを表しています。


TCHは該当ブロックがキャッシュ上で利用された回数を表しています。

これらの情報を見ながら、大量のブロックがキャッシュされているオブジェクトを見つけ、それらがキャッシュされる必要のない無駄なデータなのかどうかを確認し、無駄なようであれば、それらのデータがキャッシュされないようデータを削除したり、読み込まないようにアプリケーションやSQLの実行計画を調整したりすればいいわけです。

と言っても、なかなか一筋縄ではいかないでしょうが、データベース・バッファ・キャッシュにそれなりの容量を確保しているにもかかわらず、極端にキャッシュヒット率が低い場合や、データベース・バッファ・キャッシュのサイズを大きくしてもキャッシュヒット率があまり改善しない場合は、何かとんでもなく無駄なデータがキャッシュされている可能性もあるので調べてみる価値はあるでしょう。