バッファキャッシュとは

バッファキャッシュとは可能な限り低速なDISK I/Oの量を減らしメモリ上で処理を完了させ高速化するための目的で確保されるメモリ領域で、 ORACLEデータベース起動時に確保されるSGAと呼ばれるメモリ内に領域が確保されています。 本ページではバッファキャッシュに関連するチューニング方法や確認方法をまとめています。


ORACLEのバッファキャッシュ基礎知識

・バッファキャッシュのサイズには限りがあるため空きがなくなると基本的にはLRU(Least Recently Used)アルゴリズムによって、最も参照頻度が低いブロックからバッファキャッシュから追い出されていきます(エイジアウト)

・エイジアウトのロジックは完璧なLRUアルゴリズムではなく、ORACLE独自のロジックが含まれています。 例えば、バッファキャッシュの2%のサイズを超えるセグメントはラージセグメントとして扱われ、ラージセグメントのフルスキャンにより読み込まれたブロックは既存のバッファキャッシュ上のブロックが多くエイジアウトされてしまうことを防ぐため最もエイジアウトされやすい位置に登録されます。 このため、バッファキャッシュに空きがない状態で巨大なテーブルのフルスキャンを実施してもほぼキャッシュに乗らない場合があります。

・バッファキャッシュ上のブロックはxcur(最新で更新可能)、cr(参照モード)等のステータスを持ちます。同一ブロックに対してxcurステータスのブロックは一つだけですが、crモードのブロックは複数保持する場合があります。 これは異なるSCNの状態のcrモードのブロックを保持することによってUNDOを参照せずにデータを戻すことができるためです。
また、RAC環境においてはさらにscur(複数ノード間で共有可能(sharable)なcurrentブロック)や、PI(Past Image、更新された後に他ノードでさらに更新済みのブロック)等のRAC固有のステータスもあります。

バッファキャッシュを経由しないダイレクト処理

大量データのロード等により大量のブロックを登録する場合バッファキャッシュへの登録やバッファキャッシュからのエイジアウト等の処理自体が遅延の原因になりえます。 こういったケースの場合バッファキャッシュ関連の処理を全てスキップして直接データファイルに登録するダイレクト処理を利用することで従来型処理よりも高速に処理することができます。 ただし、バッファキャッシュに乗らないことが災いして後続処理がDISKアクセス多発により遅延する可能性もあるため総合的にみると従来型処理で処理したほうがよいケースもあります。

・direct read
ダイレクトリードが使用されるのは主にパラレル処理、ラージセグメントに対するフルスキャン(11g~、デフォルト10%で隠しパラメータで制御可能)、direct=yを指定したexp、expdpとなります。

・direct write
ダイレクトライトが使用されるのは主にinsert /*+ append */ into XXX select、insert /*+ APPEND_VALUES */ into XXX values(11g~)、sqlldrのdirect=yです。 ダイレクトライトは既存ブロックに対する更新ができないためupdateやdelete等はダイレクト処理できません。また、insertで追加されるブロックは必ず新規ブロックとして追加されるので APPEND_VALUESヒント付のinsert文を配列等を使用せずに1行ずつループするとデータサイズが膨れ上がり無駄な空き領域が大量にできるので注意が必要です。

ORACLEの外側のキャッシュ

- OSのファイルキャッシュ
OSでもORACLEと同じように高速化を目的としたファイルシステムのキャッシュ機能が動作しており、 WINDOWS以外のOSでファイルシステム上にデータファイル等を配置している場合はデータがORACLEのバッファキャッシュとOSのファイルキャッシュで2重管理され無駄な処理をさせることになるため RAWデバイス(ASM含む)にデータを配置したほうが理想的です(ただし、ASMはASMインスタンスを介してファイルアクセスされるという別のオーバヘッドがあります)。 ファイルシステム上にデータファイルを置いている場合はOSファイルキャッシュによりORACLEのバッファキャッシュ上にブロックがない状態でも性能が早くなる可能性もあるため性能検証には注意する必要があります。

- ストレージ機器のキャッシュ
ほとんどのストレージ機器はキャッシュ機能を備えており、キャッシュによって主に書き込み時のレスポンス向上等を実現しています。ストレージのキャッシュ機能を利用することでパフォーマンスが向上することは間違いないですが、 キャッシュを有効にすることはOS側からのDISK書き込み要求に対して実際にDISKへ書き込みする前にレスポンスを返す(write back方式)ことになるためストレージの障害時にはデータが整合性が取れなくなりリカバリが必要になる可能性が高くなります。 キャッシュ機能はこの欠点にも目をつむれる位の効果がありますが、少なくともアーカイブログ(パフォーマンスよりもデータ保全を重視するならばREDOログも)はwrite backではなくwrite throughで書き込むようにするか別のストレージに配置したほうが無難です。

関連システム統計

バッファキャッシュに関連する主なシステム統計としては以下のようなものがあります。(バージョンによっては存在しないものがあります)
consistent gets from cache
consistent gets - examination
consistent gets direct
physical reads
physical reads cache
physical reads direct
physical read IO requests
physical read bytes
db block changes
consistent changes
recovery blocks read
physical writes
physical writes direct
physical writes from cache
physical write IO requests
physical write bytes
physical writes non checkpoint
summed dirty queue length
DBWR checkpoint buffers written
DBWR thread checkpoint buffers written
DBWR tablespace checkpoint buffers written
DBWR parallel query checkpoint buffers written
DBWR object drop buffers written
DBWR transaction table writes
DBWR undo block writes
DBWR revisited being-written buffer
DBWR make free requests
DBWR lru scans
DBWR checkpoints
prefetch clients - keep
prefetch clients - recycle
prefetch clients - default
prefetch clients - 2k
prefetch clients - 4k
prefetch clients - 8k
prefetch clients - 16k
prefetch clients - 32k
change write time
redo synch writes
redo synch time
exchange deadlocks
free buffer requested
dirty buffers inspected
pinned buffers inspected
hot buffers moved to head of LRU
free buffer inspected
commit cleanout failures: write disabled
commit cleanout failures: block lost
commit cleanout failures: cannot pin
commit cleanout failures: hot backup in progress
commit cleanout failures: buffer being written
commit cleanout failures: callback failure
commit cleanouts
commit cleanouts successfully completed
recovery array reads
recovery array read time
CR blocks created
current blocks converted for CR
switch current to new buffer
write clones created in foreground
write clones created in background
write clones created for recovery
physical reads cache prefetch
physical reads prefetch warmup
prefetched blocks aged out before use
prefetch warmup blocks aged out before use
prefetch warmup blocks flushed out before use
physical reads retry corrupt
physical reads direct (lob)
physical reads direct temporary tablespace
physical writes direct (lob)
physical writes direct temporary tablespace
cold recycle reads
shared hash latch upgrades - no wait
shared hash latch upgrades - wait
physical reads for flashback new
total number of slots
background checkpoints started
background checkpoints completed
number of map operations
number of map misses
lob reads
lob writes
lob writes unaligned
table lookup prefetch client count

バッファキャッシュに乗っているブロックを確認する方法

現在バッファキャッシュに乗っているブロックの情報はV$BHより確認可能であり、 以下のようなSQLにより各セグメントがどの程度バッファキャッシュ上にあるか確認することができます。 (OBJD(data_object_id)列はdba_objectsのdata_object_id列に対応しています)
select objd,count(*) from v$bh where status <> 'free' group by objd;

マニュアル

概要
パフォーマンス・チューニングガイド
★ORACLE案件承ります