Buffer Cacheのヒット率だけを見て安心していたら、実はPGAでのソート処理が原因だったという苦い経験があります。メモリとI/Oの統計を切り分けて読む重要性を、そのときの反省から書いています。

メモリ(SGA / PGA)

メモリ・IO統計図

図1: SGA/PGAメモリ構成とI/O統計の見方

Oracle データベースのメモリ構造はSGAとPGAの2層に分かれています。AWRレポートではそれぞれのヒット率・割当量・Spill件数を確認し、チューニングが必要かどうかを判断します。

Buffer Cache

頻繁にアクセスするデータブロックをキャッシュする領域。物理ディスクへのアクセスを減らし、応答速度を向上させる最も基本的なメモリコンポーネントです。

ヒット率 95% 以上が理想。それより低い場合は Buffer Cache が小さすぎる可能性がある。

Buffer Cache Hit Ratio が 95% を下回る場合、次のアプローチを検討します。

  • Buffer Cache サイズの拡大: DB_CACHE_SIZE パラメータを増やす。自動メモリ管理(AMM)使用時は MEMORY_TARGET を増やす。
  • フルスキャンのSQLを減らす: Physical Reads Top 10 SQL を参照し、インデックスを追加するかクエリを改善する。
  • Keep Buffer の活用: 頻繁にアクセスする小テーブルを Keep Buffer Pool に固定する。

現在の Buffer Cache ヒット率は次のクエリで確認できます。

SELECT 1 - (physical_reads / (db_block_gets + consistent_gets)) AS hit_ratio
FROM   v$buffer_pool_statistics
WHERE  name = 'DEFAULT';

Shared Pool

SQLの解析結果(実行計画)をキャッシュする領域。バインド変数を使わないSQLはこのキャッシュを使い回せないため、毎回新しく解析(ハードパース)が走ります。

  • Library Cache Hit Ratio を確認
  • 低い場合はハードパースが多発している可能性
  • バインド変数の使用、Shared Pool の拡大を検討

Library Cache Hit Ratio が低い典型的な原因はリテラル値を直接SQLに埋め込む実装です。WHERE id = 1WHERE id = 2... のように値が毎回異なるSQLは別物として扱われ、キャッシュが効きません。アプリケーション側でバインド変数(Javaなら PreparedStatement)を使用するよう改修することで大幅に改善できます。

PGA

各セッションのソート・ハッシュ結合用ワーク領域。Oracle はセッションごとに PGA を割り当て、ソートや結合の中間データをここに保持します。PGA が不足するとディスク(TEMP表領域)にデータを書き出すため、I/O負荷が急増します。

Over Allocation 数が 0 に近い ことを確認。
0より大きいと、ワーク領域がディスクに溢れている(Spill to Disk)兆候。

PGA Over-Allocation が頻発している場合、PGA_AGGREGATE_TARGET(または AMM の MEMORY_TARGET)を増やすか、大量データのソートを伴うSQLの実行計画を見直します。

I/O統計のポイント

物理読み取り(Physical Reads)

ディスクから実際に読み込んだブロック数。多いほどBuffer Cacheが効いていないことを示します。ただし、バッチ処理や分析クエリでは大量の物理読み込みが本質的に必要なケースもあり、業務の性質と合わせて判断します。

物理書き込み(Physical Writes)

ディスクへ書き出したブロック数。DBWR(データベースライタープロセス)によるデータブロックの書き出しと、LGWR(ログライタープロセス)によるREDOログの書き出しに大別されます。Physical Writes が突出して多い場合、DBWR や LGWR の I/O スループットがボトルネックになっている可能性があります。

Redo Size

生成された Redo ログの量。COMMIT 頻度・DML 量の指標になります。

  • Redo Size が異常に大きい ⇒ 大量DMLが走っている
  • Redo Size / commit数 で1コミットあたりの変更量がわかる

Redo Size が大きすぎてI/Oがボトルネックになっている場合、次の対処が有効です。バッチ処理でのコミット間隔を広げてREDOの生成頻度を下げる、あるいはREDOログのディスクをSSDや高速ストレージに移動させることで書き込み遅延を改善できます。

Tablespace I/O Stats

表領域ごとのI/O分布。特定の表領域にI/Oが集中していないかを確認します。

I/O 集中は 特定のデータファイルやディスク群の問題である場合が多い。
Tablespace I/O Stats で表領域別の偏りを確認し、ホットな表領域があれば物理ディスクの分散を検討する。

典型的な対処

I/O集中先 原因の可能性 対処
USERS表領域業務テーブルへのI/Oが多いインデックス追加・SQLチューニング
TEMP表領域ソート・ハッシュのSpillが多いPGA増強・ソートを伴うSQLの見直し
UNDO表領域長いトランザクション・大量DMLコミット間隔の調整・UNDO_RETENTION 見直し
REDO/Archiveログコミット頻度が高い・DML量が多いコミット頻度削減・ログディスクのI/O改善

AWRからメモリ状況を確認するクエリ

AWRビューを直接クエリすることで、過去のメモリ統計を数値で確認できます。

-- 過去のBuffer Cache Hit Ratioをスナップショット単位で確認
SELECT s.snap_id,
       s.begin_interval_time,
       ROUND(1 - (n2.value - n1.value) /
             NULLIF((n3.value - n1_bg.value) + (n4.value - n1_cg.value), 0), 4) * 100 AS hit_ratio_pct
FROM   dba_hist_snapshot s
JOIN   dba_hist_sysstat n1  ON n1.snap_id = s.snap_id AND n1.stat_name = 'physical reads'
-- ※ 実際は複数ビューを JOIN する詳細なクエリが必要
ORDER  BY s.snap_id DESC
FETCH  FIRST 10 ROWS ONLY;

メモリの詳細な傾向分析を行う場合は EM Cloud Control(Enterprise Manager)の「Performance Hub」を使うと、時系列グラフで視覚的に確認できます。

メモリ・I/O診断でよくある誤り

誤り何が起きるか正しい対処
Buffer Cache Hit Ratio が高いので「I/O問題なし」と判断する Direct Path Read(パラレルクエリや大量フルスキャン)はBuffer Cacheを迂回するためHit Ratioが高くても物理I/Oが発生している Tablespace I/O StatsでPhysical Readsの絶対値と分布を確認する
Shared Pool Free % が低いのでShared Poolをすぐ増やす ハードパース多発が根本原因の場合はプールを増やしても断片化が進むだけで改善しない Hard Parsesとバインド変数使用状況を確認してから対処する
TEMP表領域への書き込みが多いのでストレージを強化する PGAの作業領域が不足してディスクSortが発生しているケースはPGA増強の方が効果的 Over-Allocation Count と % Multipass Execsを確認してPGA不足かどうかを先に判断する