Buffer Cacheのヒット率だけを見て安心していたら、実はPGAでのソート処理が原因だったという苦い経験があります。メモリとI/Oの統計を切り分けて読む重要性を、そのときの反省から書いています。
メモリ(SGA / PGA)
図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 = 1、WHERE 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不足かどうかを先に判断する |