1.

Oracle Database Buffer Cache(バッファキャッシュ)の仕組みとチューニング

編集
この記事の要点
  • Database Buffer Cache: Oracle が SGA 内に持つ「データブロックのキャッシュ」。ディスク I/O を減らす
  • 構成: DEFAULT / KEEP / RECYCLE プール、ブロックサイズ別プール (DB_2K_CACHE_SIZE 等)
  • アルゴリズム: 修正版 LRU (Touch Count 方式)。よく使うブロックほどキャッシュに残る
  • パラメータ: DB_CACHE_SIZE / SGA_TARGET / MEMORY_TARGET
  • ヒット率の確認: v$sysstat から 1 - (physical reads / (db block gets + consistent gets))90% 以上が目安

Database Buffer Cache とは

Oracle Database の Database Buffer Cache(または単に「バッファキャッシュ」)は、データファイルから読み込んだデータブロックをメモリ上に保持する SGA (System Global Area) の主要構成要素です。次回同じブロックを要求されたとき、ディスクではなくメモリから返すことで I/O コストを大幅に削減します。

RDBMS のパフォーマンスは「ディスク I/O をいかに減らすか」が鍵で、Buffer Cache のサイジングとヒット率は最重要チューニング項目のひとつです。

SGA の中での位置付け

SGA (System Global Area)
├── Database Buffer Cache    ← 本記事のテーマ
├── Shared Pool
│   ├── Library Cache (実行計画/PL/SQL)
│   └── Data Dictionary Cache
├── Redo Log Buffer
├── Large Pool
├── Java Pool
└── Streams Pool

Buffer Cache の構成(プール)

プール用途パラメータ
DEFAULT標準。明示しないオブジェクトはここDB_CACHE_SIZE
KEEP常にキャッシュに残したい(マスタテーブル等)DB_KEEP_CACHE_SIZE
RECYCLE使ったらすぐ捨てたい(大量バッチ)DB_RECYCLE_CACHE_SIZE
2K / 4K / 8K / 16K / 32K非標準ブロックサイズ用DB_nK_CACHE_SIZE

プールを指定するには CREATE / ALTER 時に STORAGE 句:

-- KEEP プールに常駐させたいマスタテーブル
ALTER TABLE m_currency STORAGE (BUFFER_POOL KEEP);

-- RECYCLE プール(大量バッチ用)
ALTER TABLE log_archive STORAGE (BUFFER_POOL RECYCLE);

LRU と Touch Count(Oracle の置換アルゴリズム)

従来の LRU (Least Recently Used) ではフルテーブルスキャンが発生するとキャッシュ全体が押し流されてしまいます。Oracle はこれを防ぐためTouch Count 方式の修正 LRUを採用しています:

  1. 初めて読み込んだブロックは LRU の冷い端 (Cold Head) に置く
  2. 使われるたびに Touch Count が増える
  3. 3 回以上使われたらホットエンド側 (Hot Tail) へ昇格
  4. 解放時は冷い端から捨てる

これにより、「一度しか読まれない大量ブロック」がホットなブロックを追い出すのを防いでいます。

キャッシュサイズの設定

-- 現在の Buffer Cache サイズ確認
SHOW PARAMETER db_cache_size;
SHOW PARAMETER sga_target;
SHOW PARAMETER memory_target;

-- 動的に変更(spfile 利用時)
ALTER SYSTEM SET db_cache_size = 4G SCOPE=BOTH;

-- KEEP / RECYCLE プールも別途
ALTER SYSTEM SET db_keep_cache_size    = 512M SCOPE=BOTH;
ALTER SYSTEM SET db_recycle_cache_size = 256M SCOPE=BOTH;

-- 自動メモリ管理(推奨): SGA_TARGET を設定すれば DB_CACHE_SIZE は自動調整
ALTER SYSTEM SET sga_target    = 8G SCOPE=BOTH;
ALTER SYSTEM SET sga_max_size  = 8G SCOPE=SPFILE;  -- 要再起動

ヒット率の計算

Buffer Cache Hit Ratio」はキャッシュがどれくらい効いているかの指標:

SELECT
    name,
    value
FROM v$sysstat
WHERE name IN ('db block gets', 'consistent gets', 'physical reads');

-- Hit Ratio の計算式
SELECT
    ROUND(
        (1 - (
            (SELECT value FROM v$sysstat WHERE name = 'physical reads')
            / (
                (SELECT value FROM v$sysstat WHERE name = 'db block gets')
                + (SELECT value FROM v$sysstat WHERE name = 'consistent gets')
            )
        )) * 100, 2
    ) AS hit_ratio_percent
FROM dual;

目安: 90% 以上が望ましい。95% 以上ならかなり良好。70% 以下は明らかに小さすぎ。

注意: ヒット率「だけ」を見るのは罠です。低速 SQL が大量のキャッシュアクセスを発生させてヒット率を稼いでいる可能性があります。AWR Reportv$sql も併用するのが定石。

v$bh: バッファごとの内容を見る

-- バッファに乗っているオブジェクトと件数
SELECT
    o.object_name,
    o.object_type,
    COUNT(*) AS blocks
FROM v$bh b
JOIN dba_objects o ON b.objd = o.data_object_id
WHERE b.status != 'free'
GROUP BY o.object_name, o.object_type
ORDER BY blocks DESC;

-- ダーティブロック(変更済でまだディスクに書かれていない)の数
SELECT COUNT(*) AS dirty_blocks
FROM v$bh
WHERE dirty = 'Y';

v$db_cache_advice: 最適サイズの推奨

Oracle が「キャッシュサイズを増減したらヒット率がどう変わるか」シミュレーションしてくれます:

SELECT
    size_for_estimate         AS cache_size_mb,
    buffers_for_estimate      AS buffers,
    estd_physical_read_factor AS read_factor,  -- 1 が現在値
    estd_physical_reads       AS estd_reads
FROM v$db_cache_advice
WHERE name = 'DEFAULT'
ORDER BY size_for_estimate;

estd_physical_read_factor が現在値 1 に対し、サイズを倍にしても 0.95 程度しか改善しないなら、メモリ追加してもあまり意味がないと判断できます。

マルチ Buffer Pool の使い分け

-- マスタ系(小さく頻繁にアクセスされる)→ KEEP
ALTER TABLE m_branch    STORAGE (BUFFER_POOL KEEP);
ALTER TABLE m_currency  STORAGE (BUFFER_POOL KEEP);
ALTER INDEX pk_m_branch STORAGE (BUFFER_POOL KEEP);

-- ログ系(大量・一度しか読まない)→ RECYCLE
ALTER TABLE access_log STORAGE (BUFFER_POOL RECYCLE);

-- 確認
SELECT segment_name, buffer_pool
FROM dba_segments
WHERE owner = 'MYAPP';

キャッシュフラッシュ(テスト時)

-- バッファキャッシュをすべて破棄(テスト用、本番では使わない)
ALTER SYSTEM FLUSH BUFFER_CACHE;

-- Shared Pool もクリア
ALTER SYSTEM FLUSH SHARED_POOL;

FAQ

Q: Buffer Cache と OS のファイルキャッシュは別?
A: 別物です。Oracle 自身のキャッシュ + OS ページキャッシュの 2 段構成。Direct I/O を使うと OS キャッシュをバイパスします。

Q: ヒット率は高いのに遅い
A: 大量の Logical Read を発生させる SQL がある可能性。v$sqlbuffer_gets 上位を確認し、実行計画を見直し。

Q: Memory Target と SGA Target のどちらを使う?
A: 11g 以降は MEMORY_TARGET (Automatic Memory Management) で SGA+PGA を一括管理可能。ただし HugePages 利用時は SGA_TARGET 推奨。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. データベースバッファキャッシュ
  2. 共有プール
  3. REDOログバッファ
  4. ラージプール