Oracle Databaseのパフォーマンスを考えるうえで、メモリー設計は非常に重要です。
適切なメモリーが割り当てられていれば、データファイルへの物理I/O、SQLのハードパース、ソートやハッシュ結合に伴う一時表領域へのI/Oを削減できます。
一方で、メモリーを増やせば必ず高速化するわけではありません。
たとえば、物理I/Oの増加はバッファキャッシュ不足だけでなく、非効率なSQL、索引不足、大規模な全表走査、ワークロードの変化などでも発生します。共有プールのハードパースも、共有プール不足だけでなく、リテラルSQLの大量発行、オブジェクトの変更、実行環境の違いなどが原因になることがあります。
したがって、Oracle Databaseのメモリーチューニングでは、次の順序を守ることが重要です。
症状を確認
↓
待機イベント・統計情報・アドバイザを確認
↓
原因がメモリー不足かを判断
↓
SGAまたはPGAを変更
↓
変更前後の性能を比較
本記事では、Oracle Database 19cを対象として、SGAとPGAの違い、主要なメモリーコンポーネント、自動メモリー管理、確認用SQL、代表的なトラブルへの対処方法を解説します。


💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?
- Oracle Databaseのメモリー構造
- 1. データベース・バッファ・キャッシュ
- 2. 共有プール
- 3. REDOログ・バッファ
- 4. ラージ・プール
- 5. Javaプール
- 6. In-Memory領域
- PGA_AGGREGATE_TARGETは上限ではない
- AMM:自動メモリー管理
- ASMM:自動共有メモリー管理
- Linux環境ではどちらを選ぶべきか
- 実行権限とCDB環境での注意点
- 1. SGA全体の概要を確認する
- 2. メモリー関連パラメータを確認する
- 3. SGAコンポーネントの現在サイズを確認する
- 4. SGAのサイズ変更履歴を確認する
- 5. バッファキャッシュの拡張効果を確認する
- 6. 共有プールのアドバイス情報を確認する
- 7. ハードパースの発生状況を確認する
- 8. PGAの使用状況を確認する
- 9. Optimal、One-pass、Multi-passの回数を確認する
- 10. PGA_AGGREGATE_TARGETの変更効果を確認する
- 11. PGAを多く使用しているプロセスを確認する
- 手順1:変更前の値を記録する
- 手順2:OS側のメモリーを確認する
- 手順3:Oracleのアドバイザを確認する
- 手順4:一度に複数のパラメータを変更しない
- 手順5:変更後の差分を確認する
- 手順6:改善しなければ元に戻す
- エラーメッセージ
- 主な原因
- 確認例
- 対処方針
- エラーメッセージ
- 主な原因
- 注意点
- エラーメッセージ
- Q1. バッファキャッシュは大きいほど高速になりますか
- Q2. ASMMではDB_CACHE_SIZEやSHARED_POOL_SIZEを0にすべきですか
- Q3. PGA_AGGREGATE_TARGETを超えることはありますか
- Q4. TEMP表領域を使用していればPGA不足ですか
- Q5. ORA-04031が発生したら共有プールをフラッシュすればよいですか
Oracle Databaseのメモリー構造
Oracle Databaseインスタンスが使用する主要なメモリー領域は、次の2つです。
- SGA:複数のOracleプロセスで共有するメモリー
- PGA:Oracleプロセスごとに使用するプライベートメモリー
Oracle Databaseでは、SGAと各プロセスのPGAを組み合わせてSQLを処理します。SGAはインスタンス起動時に確保されますが、AMMまたはASMMを使用している場合、一部のコンポーネントは稼働中に動的に拡大・縮小されます。PGAはサーバープロセスやバックグラウンドプロセスごとに確保されます。
メモリー構造の全体図
+------------------------------------------------------------------+
| Oracle Databaseインスタンス |
+------------------------------------------------------------------+
| |
| +--------------------------- SGA -----------------------------+ |
| | 複数のOracleプロセスで共有 | |
| | | |
| | ・データベース・バッファ・キャッシュ | |
| | ・共有プール | |
| | ・REDOログ・バッファ | |
| | ・ラージ・プール | |
| | ・Javaプール | |
| | ・Streamsプール | |
| | ・In-Memory領域など | |
| +--------------------------------------------------------------+ |
| |
| +--------- PGA ---------+ +--------- PGA ---------+ |
| | サーバープロセス1用 | | サーバープロセス2用 | …… |
| | | | | |
| | ・ソート作業領域 | | ・ソート作業領域 | |
| | ・ハッシュ作業領域 | | ・ハッシュ作業領域 | |
| | ・カーソル実行情報 | | ・カーソル実行情報 | |
| +-----------------------+ +-----------------------+ |
| |
+------------------------------------------------------------------+
| メモリー領域 | 主な用途 | 共有範囲 |
|---|---|---|
| SGA | データブロック、SQL、実行計画、データディクショナリ情報、REDOなどの保持 | インスタンス内のOracleプロセスで共有 |
| PGA | ソート、ハッシュ結合、カーソル実行状態、プロセス固有情報の保持 | 原則としてOracleプロセス単位 |
専用サーバー構成では、サーバープロセスとユーザーセッションがおおむね1対1で対応します。一方、共有サーバー構成では、セッション状態を保持するUGAの一部または全部がSGA側に配置されるため、「PGAは常にセッション単位」と考えるのは正確ではありません。PGAは、基本的にはプロセス単位のプライベートメモリーです。
SGAの主要コンポーネント
SGAは、用途の異なる複数のメモリーコンポーネントで構成されています。
+------------------------------------------------------------------+
| SGA |
+------------------------------------------------------------------+
| データベース・バッファ・キャッシュ |
| └ データファイルから読み込んだデータブロックを保持 |
+------------------------------------------------------------------+
| 共有プール |
| ├ ライブラリ・キャッシュ:SQL、PL/SQL、実行計画 |
| └ データディクショナリ・キャッシュ:表や列などの定義情報 |
+------------------------------------------------------------------+
| REDOログ・バッファ |
| └ オンラインREDOログへ書き込む前のREDOエントリを保持 |
+------------------------------------------------------------------+
| ラージ・プール、Javaプール、Streamsプール、In-Memory領域など |
+------------------------------------------------------------------+
| 固定SGA |
| └ インスタンス内部の管理情報 |
+------------------------------------------------------------------+
Oracle公式マニュアルでは、バッファキャッシュ、共有プール、REDOログ・バッファ、ラージ・プール、Javaプール、In-Memory領域などが主要なSGAコンポーネントとして説明されています。
1. データベース・バッファ・キャッシュ
データベース・バッファ・キャッシュは、データファイルから読み込んだデータブロックのコピーを保持する領域です。
SQLが必要とするブロックがバッファキャッシュに存在すれば、データファイルから改めて読み込む必要がありません。そのため、適切なサイズのバッファキャッシュは、物理I/Oの削減に大きく貢献します。
ただし、物理読取りが多いという理由だけで、すぐにDB_CACHE_SIZEやSGA_TARGETを増やすべきではありません。
物理読取りが多くなる原因には、次のようなものがあります。
- バッファキャッシュが小さい
- 全表走査を繰り返すSQLがある
- 必要な索引が存在しない
- 読み込むデータ量そのものが増加した
- バッチ処理とオンライン処理が同じ時間帯に集中している
- SQLの実行計画が変化した
バッファキャッシュを増やす前に、V$DB_CACHE_ADVICEの予測値や、負荷の高いSQL、待機イベントを確認します。V$DB_CACHE_ADVICEでは、キャッシュサイズを変更した場合の推定物理読取り回数を確認できます。
バッファキャッシュ不足を疑う症状
・db file sequential readなどの物理I/O待機が多い
・同じデータブロックが繰り返しデータファイルから読み込まれている
・DB Cache Adviceでキャッシュ拡張による物理読取り削減が予測される
キャッシュ・ヒット率だけで判断せず、「バッファキャッシュを増やした場合に、実際の処理時間や物理読取りがどれだけ減るか」を確認することが重要です。
2. 共有プール
共有プールには、主に次の領域が含まれます。
- ライブラリ・キャッシュ
- データディクショナリ・キャッシュ
- サーバー結果キャッシュなど
ライブラリ・キャッシュには、解析済みSQL、PL/SQLコード、実行計画などが保持されます。同一のSQLを共有できれば、Oracle Databaseは毎回ハードパースを実行する必要がなくなり、CPU、メモリー、ラッチなどの使用量を削減できます。
ハードパースが増える主な原因
共有プールが小さいことだけが原因とは限りません。
ハードパース増加
├─ 共有プールが小さく、SQLがキャッシュから追い出される
├─ リテラル値だけが異なるSQLが大量に発行される
├─ SQL文字列、空白、大文字・小文字などが異なる
├─ 参照先スキーマやセッション環境が異なる
├─ DDLや統計情報更新などでカーソルが無効化される
└─ アプリケーションがカーソルを再利用していない
特にOLTPシステムでは、次のようにリテラル値を直接指定したSQLを大量に発行すると、異なるSQLとして処理されやすくなります。
SELECT employee_name
FROM employees
WHERE employee_id = 100;
SELECT employee_name
FROM employees
WHERE employee_id = 101;
バインド変数を使用すると、SQLを共有しやすくなります。
SELECT employee_name
FROM employees
WHERE employee_id = :employee_id;
Oracle公式マニュアルでも、共有カーソルを利用するため、可能な場合はリテラルではなくバインド変数を使用することが推奨されています。ただし、データ分布に大きな偏りがある分析系SQLでは、リテラル値を使用した方が適切な選択性を見積もれるケースもあります。そのため、すべてのSQLを機械的にバインド変数化するのではなく、ワークロードの特性を考慮します。
3. REDOログ・バッファ
REDOログ・バッファは、データベースに対する変更内容を表すREDOエントリを、オンラインREDOログファイルへ書き込む前に保持する循環バッファです。
LGWRプロセスは、REDOログ・バッファの内容をオンラインREDOログファイルへ書き込みます。
大量更新処理などでREDO生成量が多く、LGWRの書込みが追い付かない場合には、log buffer space待機が発生することがあります。
ただし、log buffer spaceが発生したからといって、必ずLOG_BUFFERを大きくすれば解決するわけではありません。
確認すべき項目は次のとおりです。
- REDOログの格納先ストレージが遅くないか
- LGWRのI/O待機が増えていないか
- 短時間に大量のREDOが生成されていないか
- オンラインREDOログの切替えが過剰に発生していないか
redo buffer allocation retriesが増加していないか
LOG_BUFFERは動的に変更できない初期化パラメータであり、デフォルト値はSGAサイズやCPU数などに基づいて決定されます。また、REDOログ・バッファはASMMによる自動サイズ変更の対象外です。
4. ラージ・プール
ラージ・プールは、共有プールから大きな連続メモリーを確保することによる断片化を避けるための任意の領域です。
主に次の処理で使用されます。
- 共有サーバー構成のセッションメモリー
- パラレル実行のメッセージバッファ
- RMANのI/Oバッファ
- 一部の大きなメモリー割当て
ASMMを使用している場合、ラージ・プールはSGA_TARGETの範囲内で自動調整されます。LARGE_POOL_SIZEに0より大きい値を設定した場合、その値はASMMにおける下限値として扱われます。
5. Javaプール
Javaプールは、Oracle Database内のJava Virtual MachineでJavaコードを実行するために使用されます。
Javaストアドプロシージャなど、データベース内Java機能を使用していない環境では、Javaプールの重要度は比較的低くなります。ASMM環境でJAVA_POOL_SIZEを指定した場合、その値は自動調整時の下限値になります。
6. In-Memory領域
In-Memory領域は、Oracle Database In-Memoryで使用する列指向のデータを保持するSGA領域です。
通常のバッファキャッシュには行形式のデータが保持されますが、In-Memory Column Storeでは分析処理に適した列形式でもデータを保持します。
データファイル
│
├─ バッファキャッシュ:行形式
│
└─ In-Memory領域 :列形式
Oracle Database 19cのライセンス体系では、完全なOracle Database In-MemoryはEnterprise Edition向けの有償オプションです。
一方、Enterprise Editionでは、一定の制限付きでIn-Memory機能を試せる「Database In-Memory Base Level」が用意されています。Base Levelでは、In-Memory領域がCDB当たり最大16GBに制限されるなどの条件があります。Standard Edition 2では、Database In-Memory Base Levelを利用できません。ライセンス条件は更新される可能性があるため、導入時点のOracle Database Licensing Information User Manualを必ず確認してください。
PGAの構造と役割
PGAは、サーバープロセスやバックグラウンドプロセスが使用するプライベートメモリーです。
+----------------------------------------------------------+
| PGA |
+----------------------------------------------------------+
| プライベートSQL領域 |
| ├ カーソル実行状態 |
| ├ バインド変数 |
| └ SQL実行時の制御情報 |
+----------------------------------------------------------+
| SQLワークエリア |
| ├ ソート処理 |
| ├ ハッシュ結合 |
| ├ ビットマップ処理 |
| └ その他のメモリー集中型SQL演算子 |
+----------------------------------------------------------+
| プロセス固有の管理情報 |
+----------------------------------------------------------+
PGAのSQLワークエリアは、次のような処理で使用されます。
ORDER BYによるソートGROUP BYによる集計- ハッシュ結合
- ビットマップ処理
- ウィンドウ関数や分析処理
- 一部の索引作成処理
Oracle Databaseでは、ワークエリアの実行状態を次の3種類に分類します。
| 実行モード | 状態 |
| Optimal | 必要な作業を主にメモリー内で処理できる |
| One-pass | ワークエリアが最適サイズより小さく、入力データに対して追加のパスが1回必要 |
| Multi-pass | ワークエリアがさらに小さく、複数回の追加パスが必要 |
One-passは完全なメモリー内処理ではありません。Optimalより少ないメモリーで処理するため、追加の読取り・書込みが発生し、応答時間が長くなります。Multi-passはさらに大きな性能低下を招くため、可能な限り回避すべきです。
PGAが十分
└─ Optimal
└─ 少ない追加I/Oで処理
PGAが不足
├─ One-pass
│ └─ 一時表領域を使用した追加処理
│
└─ Multi-pass
└─ 複数回の追加処理が発生し、大幅に遅延
PGA_AGGREGATE_TARGETは上限ではない
PGA_AGGREGATE_TARGETは、インスタンス全体で使用するPGAの目標値です。
ただし、これは絶対的な上限ではありません。
PGA_AGGREGATE_TARGETで主に制御されるのは、ソートやハッシュ結合などの調整可能なワークエリアです。PL/SQL、Java、その他の調整不能なPGAメモリーが増加した場合、実際のPGA使用量がPGA_AGGREGATE_TARGETを超えることがあります。
絶対的な上限を設定するパラメータが、PGA_AGGREGATE_LIMITです。
PGA_AGGREGATE_LIMITを超過すると、Oracle Databaseは、調整不能なPGAを多く使用しているセッションのコールを中断します。それでも使用量が減らない場合は、対象セッションを終了します。
AMMとASMMの違い
Oracle Databaseには、SGAとPGAを管理する複数の方式があります。
AMM:自動メモリー管理
AMMでは、次のパラメータを使用します。
MEMORY_TARGET
MEMORY_MAX_TARGET
MEMORY_TARGETでSGAとインスタンスPGAの合計目標値を設定すると、Oracle DatabaseがSGAとPGAの間でメモリーを動的に再配分します。
+--------------------- MEMORY_TARGET ----------------------+
| |
| SGA インスタンスPGA |
| +-------------+ +------------------+ |
| | | ←調整→ | | |
| +-------------+ +------------------+ |
| |
+---------------------------------------------------------+
AMMのメリット
- SGAとPGAをまとめて管理できる
- ワークロードに応じてSGAとPGAの配分が変化する
- 小規模環境や検証環境で管理しやすい
AMMの注意点
Linuxでは、AMMとHugePagesを併用できません。AMMを使用すると、SGAは主に/dev/shmを使用して確保され、HugePagesには割り当てられません。
ASMM:自動共有メモリー管理
ASMMでは、SGAとPGAを分けて設定します。
SGA_TARGET
SGA_MAX_SIZE
PGA_AGGREGATE_TARGET
PGA_AGGREGATE_LIMIT
SGA_TARGETでSGA全体のサイズを指定すると、Oracle Databaseがバッファキャッシュ、共有プール、ラージ・プール、Javaプールなどのサイズを自動調整します。
PGAは、PGA_AGGREGATE_TARGETを使用して別に管理します。
+------------------- SGA_TARGET --------------------+
| バッファキャッシュ ←→ 共有プール ←→ その他 |
+---------------------------------------------------+
+-------------- PGA_AGGREGATE_TARGET ---------------+
| 各OracleプロセスのPGAに対する目標値 |
+---------------------------------------------------+
ASMMのメリット
- SGAとPGAの配分をDBAが明示的に設計できる
- SGA内の主要コンポーネントは自動調整される
- Linux環境でHugePagesを利用できる
- SGAとPGAのどちらが増えたかを把握しやすい
ASMMの注意点
- SGAとPGAの間では、AMMのような自動的な融通は行われない
- ワークロードに応じて、SGAとPGAの配分をDBAが評価する必要がある
- SGAを増やしすぎると、PGAやOS用メモリーを圧迫する
Linux環境ではどちらを選ぶべきか
Linuxで大きなSGAを使用し、HugePagesを利用する場合は、AMMではなくASMMを選択します。
ただし、「Linuxなら必ずASMM」「HugePagesはすべての環境で必須」と一律に考えるべきではありません。
次の条件を基に判断します。
| 条件 | 検討する方式 |
| 小規模な検証環境 | AMMまたはASMM |
| Windows環境 | AMMも選択肢 |
| LinuxでHugePagesを使用 | ASMM |
| 大規模な本番環境 | ASMMを中心に検討 |
| SGAとPGAを明示的に管理したい | ASMM |
OracleのLinux向けマニュアルでは、HugePagesを使用する場合にAMMを無効化する必要があると説明されています。また、HugePagesだけで物理メモリーを使い切らず、通常ページ用のメモリーを確保する必要があります。
ASMM使用時の個別パラメータ
ASMMでは、次の主要コンポーネントがSGA_TARGETの範囲内で自動調整されます。
DB_CACHE_SIZESHARED_POOL_SIZELARGE_POOL_SIZEJAVA_POOL_SIZESTREAMS_POOL_SIZE
個別パラメータに0より大きい値を設定すると、原則として固定値ではなく、自動調整時の下限値として使用されます。
たとえば、次の設定の場合を考えます。
SGA_TARGET = 16G
DB_CACHE_SIZE = 8G
SHARED_POOL_SIZE = 2G
この場合、ASMMはおおむね次の制約で動作します。
SGA全体 :16GB
バッファキャッシュ:最低8GB
共有プール :最低2GB
残り :ワークロードに応じて自動配分
個別パラメータを過剰に大きく設定すると、Oracle Databaseが自動調整できる範囲が狭くなります。
明確な最低保証値が必要な場合を除き、個別コンポーネントの下限を必要以上に設定しないことが重要です。
メモリー不足時の症状と確認ポイント
| 症状 | 疑う領域 | 最初に確認する項目 |
| 物理読取りが多い | バッファキャッシュ | SQL、待機イベント、V$DB_CACHE_ADVICE |
| ハードパースが多い | 共有プールまたはアプリケーション | バインド変数、parse count (hard)、カーソル共有不可理由 |
| TEMPへのI/Oが多い | PGA | One-pass、Multi-pass、V$PGA_TARGET_ADVICE |
log buffer spaceが多い | REDOログ・バッファまたはLGWR I/O | REDO生成量、LGWR待機、ストレージ性能 |
| ORA-04031 | SGA内の対象プール | エラーメッセージのヒープ名、トレース、メモリー設定 |
| ORA-04030 | プロセスのプライベートメモリー | OSメモリー、プロセスPGA、OS制限 |
| ORA-04036 | PGA上限超過 | PGA_AGGREGATE_LIMIT、大量消費セッション |
実践:メモリー確認用SQL
実行権限とCDB環境での注意点
動的パフォーマンスビューを参照するには、通常、次のいずれかの権限が必要です。
- SYSDBA
SELECT_CATALOG_ROLE- 必要な
V_$ビューに対する個別のSELECT権限 SELECT ANY DICTIONARY
本番環境では、必要以上に強い権限を付与せず、参照に必要な権限のみを付与することを推奨します。
SGAとインスタンスPGAはインスタンス単位の情報です。CDB環境でインスタンス全体を確認する場合は、基本的にCDB$ROOTへ接続して実行します。PDB単位のメモリー制限を確認する場合は、CON_IDやPDB側の初期化パラメータも確認してください。V$PGASTATなどの累積値はインスタンス起動時から蓄積されます。
1. SGA全体の概要を確認する
SHOW SGA;
SQL*PlusのSHOW SGAコマンドでは、SGAの概要を次のような区分で確認できます。
Total System Global Area
Fixed Size
Variable Size
Database Buffers
Redo Buffers
これはSQL文ではなく、SQL*Plusのコマンドです。
2. メモリー関連パラメータを確認する
SELECT
name,
display_value,
isdefault,
issys_modifiable
FROM
v$parameter
WHERE
name IN (
'memory_target',
'memory_max_target',
'sga_target',
'sga_max_size',
'db_cache_size',
'shared_pool_size',
'large_pool_size',
'java_pool_size',
'streams_pool_size',
'log_buffer',
'pga_aggregate_target',
'pga_aggregate_limit'
)
ORDER BY
name;
このSQLで、AMMとASMMのどちらが使用されているかを判断できます。
AMMの代表的な状態
MEMORY_TARGET > 0
ASMMの代表的な状態
MEMORY_TARGET = 0
SGA_TARGET > 0
PGA_AGGREGATE_TARGET > 0
3. SGAコンポーネントの現在サイズを確認する
SELECT
component,
ROUND(current_size / 1024 / 1024, 2) AS current_mb,
ROUND(min_size / 1024 / 1024, 2) AS min_mb,
ROUND(max_size / 1024 / 1024, 2) AS max_mb,
ROUND(user_specified_size / 1024 / 1024, 2)
AS user_specified_mb
FROM
v$sga_dynamic_components
WHERE
current_size > 0
ORDER BY
current_size DESC;
V$SGA_DYNAMIC_COMPONENTSでは、動的SGAコンポーネントの現在サイズや、インスタンス起動後に記録された最小・最大サイズを確認できます。
4. SGAのサイズ変更履歴を確認する
SELECT
component,
oper_type,
oper_mode,
ROUND(initial_size / 1024 / 1024, 2) AS initial_mb,
ROUND(target_size / 1024 / 1024, 2) AS target_mb,
ROUND(final_size / 1024 / 1024, 2) AS final_mb,
status,
start_time,
end_time
FROM
v$sga_resize_ops
ORDER BY
start_time DESC
FETCH FIRST 20 ROWS ONLY;
自動メモリー管理によって、どのコンポーネントが拡大・縮小されたかを確認できます。
頻繁に拡大と縮小を繰り返している場合は、SGA全体が不足しているか、個別コンポーネントに設定した下限値が自動調整を妨げていないかを確認します。
5. バッファキャッシュの拡張効果を確認する
SELECT
size_for_estimate AS cache_size_mb,
size_factor,
estd_physical_reads,
estd_physical_read_factor,
estd_physical_read_time
FROM
v$db_cache_advice
WHERE
name = 'DEFAULT'
AND block_size = (
SELECT TO_NUMBER(value)
FROM v$parameter
WHERE name = 'db_block_size'
)
ORDER BY
size_for_estimate;
主に確認する列は次のとおりです。
| 列 | 内容 |
CACHE_SIZE_MB | 評価対象となるキャッシュサイズ |
SIZE_FACTOR | 現在サイズに対する倍率 |
ESTD_PHYSICAL_READS | 推定物理読取り数 |
ESTD_PHYSICAL_READ_FACTOR | 現在に対する推定物理読取り倍率 |
ESTD_PHYSICAL_READ_TIME | 推定物理読取り時間 |
バッファキャッシュを増やしても推定物理読取り数がほとんど減らない場合、キャッシュ拡張による効果は限定的と考えられます。
6. 共有プールのアドバイス情報を確認する
SELECT
shared_pool_size_for_estimate AS shared_pool_mb,
shared_pool_size_factor,
estd_lc_size,
estd_lc_memory_objects,
estd_lc_time_saved,
estd_lc_time_saved_factor
FROM
v$shared_pool_advice
ORDER BY
shared_pool_size_for_estimate;
V$SHARED_POOL_ADVICEでは、共有プールのサイズを変更した場合に、ライブラリ・キャッシュによって節約される推定解析時間などを確認できます。
7. ハードパースの発生状況を確認する
SELECT
name,
value
FROM
v$sysstat
WHERE
name IN (
'parse count (total)',
'parse count (hard)',
'execute count',
'session cursor cache hits'
)
ORDER BY
name;
parse count (hard)が多い場合は、共有プールのサイズだけでなく、アプリケーションがバインド変数やカーソルキャッシュを使用しているかも確認します。
同一に見えるSQLが共有されない理由は、V$SQL_SHARED_CURSORなどで調査できます。Oracle公式マニュアルでも、共有されないSQLの理由を確認するためにこのビューを使用する方法が案内されています。
8. PGAの使用状況を確認する
SELECT
name,
CASE
WHEN unit = 'bytes'
THEN ROUND(value / 1024 / 1024, 2)
ELSE value
END AS value,
CASE
WHEN unit = 'bytes'
THEN 'MB'
ELSE unit
END AS unit
FROM
v$pgastat
WHERE
name IN (
'aggregate PGA target parameter',
'aggregate PGA auto target',
'total PGA allocated',
'total PGA inuse',
'maximum PGA allocated',
'total freeable PGA memory',
'over allocation count',
'global memory bound',
'cache hit percentage',
'extra bytes read/written'
)
ORDER BY
name;
元記事にあるcurrent PGA allocatedという統計名は、Oracle Database 19cのV$PGASTATでは使用しません。現在の割当量はtotal PGA allocatedで確認します。
特に重要な統計は次のとおりです。
| 統計名 | 確認内容 |
total PGA allocated | 現在割り当てられているPGA |
maximum PGA allocated | 起動後の最大PGA割当量 |
aggregate PGA auto target | 自動ワークエリアに使用可能なPGA |
over allocation count | PGA目標値を守れず追加割当てした回数 |
global memory bound | 個々のワークエリアに割り当てられる最大サイズ |
extra bytes read/written | Optimalで処理できず追加処理されたデータ量 |
over allocation countが増加している場合は、PGA_AGGREGATE_TARGETが不足している可能性があります。ただし、値は起動後の累積値なので、1回の取得だけでなく、一定時間ごとの差分を確認してください。
9. Optimal、One-pass、Multi-passの回数を確認する
SELECT
name,
value
FROM
v$sysstat
WHERE
name IN (
'workarea executions - optimal',
'workarea executions - onepass',
'workarea executions - multipass'
)
ORDER BY
name;
Multi-passが発生している場合は、PGA不足によって大きな性能低下が発生している可能性があります。
ただし、これらの値もインスタンス起動後の累積値です。問題が発生した時間帯の差分や、対象SQLのV$SQL_WORKAREAを確認する必要があります。
10. PGA_AGGREGATE_TARGETの変更効果を確認する
SELECT
ROUND(pga_target_for_estimate / 1024 / 1024)
AS target_mb,
pga_target_factor,
estd_pga_cache_hit_percentage,
estd_overalloc_count,
ROUND(estd_extra_bytes_rw / 1024 / 1024)
AS estd_extra_rw_mb
FROM
v$pga_target_advice
ORDER BY
pga_target_for_estimate;
V$PGA_TARGET_ADVICEでは、PGA_AGGREGATE_TARGETを変更した場合の次の値を予測できます。
- PGAキャッシュ・ヒット率
- 過剰割当て回数
- 追加の読取り・書込み量
- 推定処理時間
ESTD_OVERALLOC_COUNTが0になり、追加メモリーによる改善効果が頭打ちになる付近を候補として検討します。
11. PGAを多く使用しているプロセスを確認する
SELECT
s.sid,
s.serial#,
s.username,
s.program,
p.spid,
ROUND(p.pga_used_mem / 1024 / 1024, 2) AS used_mb,
ROUND(p.pga_alloc_mem / 1024 / 1024, 2) AS allocated_mb,
ROUND(p.pga_max_mem / 1024 / 1024, 2) AS max_mb
FROM
v$process p
LEFT JOIN
v$session s
ON
s.paddr = p.addr
ORDER BY
p.pga_alloc_mem DESC
FETCH FIRST 20 ROWS ONLY;
インスタンス全体のPGAが多い場合は、どのプロセスまたはセッションが使用しているかを確認します。
V$PROCESS_MEMORYを使用すると、PGAをSQL、PL/SQL、Javaなどのカテゴリ別に確認できます。
安全なメモリーチューニング手順
メモリーパラメータは、次の手順で変更します。
手順1:変更前の値を記録する
SELECT
name,
display_value
FROM
v$parameter
WHERE
name IN (
'sga_target',
'sga_max_size',
'pga_aggregate_target',
'pga_aggregate_limit'
)
ORDER BY
name;
手順2:OS側のメモリーを確認する
Linuxでは、次のような情報を確認します。
free -m
vmstat 1
grep -i huge /proc/meminfo
確認するポイントは次のとおりです。
- 空きメモリーだけでなく、availableメモリー
- スワップイン・スワップアウト
- HugePagesの総数と空き数
- 他のOracleインスタンスやアプリケーションの使用量
- プロセス数の増加
- コンテナやcgroupによるメモリー制限
手順3:Oracleのアドバイザを確認する
SGA全体 :V$SGA_TARGET_ADVICE
バッファキャッシュ:V$DB_CACHE_ADVICE
共有プール :V$SHARED_POOL_ADVICE
PGA :V$PGA_TARGET_ADVICE
手順4:一度に複数のパラメータを変更しない
たとえば、PGA不足が疑われる場合は、最初にPGA_AGGREGATE_TARGETだけを変更します。
ALTER SYSTEM SET pga_aggregate_target = 4G
SCOPE = BOTH;
数値は例です。実際の値は、物理メモリー、同時接続数、SQLワークロード、アドバイザの結果に基づいて決定してください。
手順5:変更後の差分を確認する
・処理時間
・待機イベント
・TEMP使用量
・物理読取り
・ハードパース
・One-pass、Multi-pass
・PGAの最大使用量
・OSのスワップ
手順6:改善しなければ元に戻す
ALTER SYSTEM SET pga_aggregate_target = <変更前の値>
SCOPE = BOTH;
オンライン変更が可能なパラメータであっても、縮小対象のメモリーがすぐに解放できない場合や、Oracle内部のリサイズ処理が完了するまで時間がかかる場合があります。V$SGA_RESIZE_OPSなどで変更状態を確認してください。
ORA-04031の原因と対処
エラーメッセージ
ORA-04031: unable to allocate ... bytes of shared memory
ORA-04031は、必要な共有メモリーを確保できなかった場合に発生します。
必ずしも共有プールだけで発生するわけではありません。エラーメッセージに表示されるヒープ名やプール名を確認し、共有プール、ラージ・プール、Streamsプール、In-Memory領域など、どの領域で不足したかを判断します。
主な原因
- SGA全体が小さい
- 共有プールなど特定のプールが小さい
- 共有されないSQLが大量に存在する
- 多数の子カーソルが生成されている
- 大きな連続メモリーを確保できない
- メモリーリークまたはOracle Databaseの不具合
- Streamsプールなど、別のSGA領域が不足している
確認例
SELECT
component,
current_size,
min_size,
max_size
FROM
v$sga_dynamic_components
ORDER BY
current_size DESC;
SELECT
request_misses,
request_failures,
last_failure_size
FROM
v$shared_pool_reserved;
対処方針
1. アラートログとトレースファイルを確認
2. ORA-04031に表示されたプール名を確認
3. SQL共有状況や子カーソル数を確認
4. SGAおよび対象プールのサイズを確認
5. アドバイザを確認
6. 必要に応じてSGA_TARGETまたは対象プールを拡張
7. 再発する場合はOracle Supportへの調査依頼を検討
ALTER SYSTEM FLUSH SHARED_POOLについて
ALTER SYSTEM FLUSH SHARED_POOL;
このコマンドは、共有プール内の未固定オブジェクトをフラッシュします。
ただし、通常の根本対策として安易に実行すべきではありません。
実行後は、多くのSQLで再解析が必要になり、CPU負荷やハードパースが一時的に増加する可能性があります。共有プール不足の原因が、リテラルSQL、多数の子カーソル、無効化、メモリーリークなどである場合、フラッシュしても再発します。
影響を理解したうえでの一時的な復旧・切り分け手段として扱い、根本原因を調査してください。
ORA-04030の原因と対処
エラーメッセージ
ORA-04030: out of process memory when trying to allocate ...
ORA-04030は、Oracleプロセスがプライベートメモリーを確保できなかった場合に発生します。
Oracle公式のエラー説明では、OSメモリーの枯渇、またはプロセス単位のプライベートメモリー制限への到達が主な原因とされています。
主な原因
- OSの物理メモリー不足
- スワップ領域を含む仮想メモリー不足
- プロセス単位のメモリー制限
ulimitやcgroupの制限- 1つのプロセスが大量のPGAを使用
- 大量のPL/SQLコレクション
- 非効率なソートやハッシュ処理
- 過剰なパラレル実行
- Oracle Databaseまたはアプリケーションのメモリーリーク
注意点
ORA-04030に対して、無条件にPGA_AGGREGATE_TARGETを増やすのは危険です。
PGA_AGGREGATE_TARGETを増やすと、各ワークエリアへ割り当てられるPGAが増え、OSメモリー不足を悪化させる可能性があります。
最初に、次の点を確認します。
・どのOracleプロセスでエラーが発生したか
・そのプロセスのPGA使用量
・ホスト全体のメモリー使用量
・OSのプロセス制限
・実行SQLやPL/SQL
・同時実行数とパラレル度
・アラートログ、トレースファイル
ORA-04036の原因と対処
エラーメッセージ
ORA-04036:
PGA memory used by the instance or PDB exceeds PGA_AGGREGATE_LIMIT
ORA-04036は、インスタンスまたはPDBのPGA使用量がPGA_AGGREGATE_LIMITを超えた場合に発生します。
確認する項目は次のとおりです。
SHOW PARAMETER pga_aggregate_limit
SELECT
name,
value,
unit
FROM
v$pgastat
WHERE
name IN (
'total PGA allocated',
'maximum PGA allocated',
'total PGA inuse'
);
単純に上限を引き上げる前に、PGAを大量に使用したセッション、SQL、PL/SQL、パラレル実行を特定します。
OSメモリー枯渇とスワップを防ぐ
SGAとPGAの合計を、物理メモリーの限界近くまで設定してはいけません。
Oracle Databaseのメモリー以外にも、次の領域が必要です。
- OSカーネル
- OracleプロセスのPGA
- Oracle Grid Infrastructure
- ASM
- ファイルシステムキャッシュ
- 監視エージェント
- バックアップソフト
- セキュリティソフト
- 他のデータベースやアプリケーション
Oracle公式のベストプラクティスでも、SGAとPGAの割当て合計を物理メモリーより小さくし、OSや他のプロセスに必要なメモリーを確保するよう説明されています。
ただし、「必ず物理メモリーの20%をOS用に残す」など、すべての環境に適用できる固定比率はありません。
OracleのPGAチューニングガイドでは、初期見積りの例としてOSなどに20%を確保する考え方が示されていますが、これはあくまで初期設計の例です。実際には、OS、接続数、PGAの変動、HugePages、ASM、バックアップ、監視ソフトなどを含めて設計します。
物理メモリー
│
├─ OS・カーネル・通常ページ
├─ Oracle SGA
├─ Oracle PGA
├─ Grid Infrastructure・ASM
├─ バックアップ・監視プロセス
└─ 予備メモリー
OSで継続的なスワップが発生すると、Oracle Databaseの応答時間が大きく悪化する可能性があります。SGA全体が実メモリーに収まるように設計することが重要です。
エディションによる違い
SGA、PGA、AMM、ASMMなどの基本的なメモリー管理機能は、Oracle Databaseの基本機能であり、Enterprise EditionとStandard Edition 2の両方で使用できます。
一方、In-Memory関連機能にはエディションおよびライセンス上の制限があります。
| 機能 | Enterprise Edition | Standard Edition 2 |
| SGA・PGAの基本機能 | 利用可能 | 利用可能 |
| AMM | 利用可能 | 利用可能 |
| ASMM | 利用可能 | 利用可能 |
| 自動PGAメモリー管理 | 利用可能 | 利用可能 |
| Oracle Database In-Memory | 原則として有償オプション | 利用不可 |
| Database In-Memory Base Level | 制限付きで利用可能 | 利用不可 |
ライセンス条件は契約形態、クラウドサービス、Release Updateなどによって異なる場合があります。最終的な判断には、利用中の契約書および最新のOracle公式ライセンス情報を使用してください。
よくある質問
Q1. バッファキャッシュは大きいほど高速になりますか
一定の範囲までは、バッファキャッシュを大きくすることで物理読取りを削減できる可能性があります。
ただし、ワークロードで再利用されないブロックを大量に読み込んでいる場合や、すでに必要なデータが十分キャッシュされている場合は、拡張しても効果は限定的です。
V$DB_CACHE_ADVICEで、サイズを増やした場合の推定物理読取り数を確認してください。
Q2. ASMMではDB_CACHE_SIZEやSHARED_POOL_SIZEを0にすべきですか
特別な下限値が必要なければ、Oracle Databaseによる自動調整を優先できます。
ただし、特定のアプリケーションが必要とする最低サイズが分かっている場合は、個別パラメータに下限値を設定できます。
個別パラメータに設定した値は、ASMM環境では原則として最低保証値として扱われます。
Q3. PGA_AGGREGATE_TARGETを超えることはありますか
あります。
PGA_AGGREGATE_TARGETは目標値であり、絶対的な上限ではありません。また、すべてのPGAメモリーがこのパラメータで調整できるわけではありません。
絶対的な上限を設定する場合は、PGA_AGGREGATE_LIMITを使用します。
Q4. TEMP表領域を使用していればPGA不足ですか
必ずしもPGA不足とは限りません。
処理対象が非常に大きい場合、適切なPGAが設定されていてもOne-passで実行されることがあります。
次の情報を組み合わせて判断します。
workarea executions - onepassworkarea executions - multipassextra bytes read/writtenover allocation countV$PGA_TARGET_ADVICE- 対象SQLの実行計画と処理データ量
特にMulti-passが継続的に発生している場合は、PGA不足や過剰な同時実行を疑います。
Q5. ORA-04031が発生したら共有プールをフラッシュすればよいですか
共有プールのフラッシュは一時的な切り分け手段であり、根本対策ではありません。
フラッシュ後にはSQLの再解析が集中する可能性があります。
次のような根本原因を調査してください。
- 共有されないSQL
- 多数の子カーソル
- 共有プールまたは他のSGA領域の不足
- DDLなどによるカーソル無効化
- アプリケーション設計
- Oracle Databaseの不具合やメモリーリーク
まとめ:Oracleメモリーチューニングの原則
Oracle Databaseのメモリーチューニングでは、次の点が重要です。
- SGAは共有メモリー、PGAはプロセス単位のプライベートメモリーとして理解する
- 物理I/Oが多いという理由だけでバッファキャッシュを増やさない
- ハードパースでは、共有プールのサイズとSQLの共有性を分けて調査する
- PGAではOptimal、One-pass、Multi-passの発生状況を確認する
PGA_AGGREGATE_TARGETは上限ではなく目標値である- 絶対上限には
PGA_AGGREGATE_LIMITを使用する - LinuxでHugePagesを使用する場合はAMMではなくASMMを使用する
- アドバイザの予測値と実際の処理時間を基にサイズを決定する
- メモリー変更前後の統計情報を保存して比較する
- SGAやPGAを増やしてOSのスワップを発生させない
適切なメモリーチューニング
=
Oracleの統計情報
+
OSのメモリー状態
+
SQL・ワークロードの分析
+
変更前後の比較
メモリーサイズを勘や固定比率だけで決めるのではなく、V$DB_CACHE_ADVICE、V$SHARED_POOL_ADVICE、V$PGA_TARGET_ADVICEなどの情報と、実際のワークロードを基に判断することが、安定したOracle Database運用につながります。
※本記事はOracle Database 19cを対象としています。Release Update、OS、エディション、ライセンス、CDB/PDB構成によって動作や利用条件が異なる場合があるため、実環境への変更前に該当バージョンのOracle公式マニュアルを確認してください。

💰 【PR】Oracleエンジニアの市場価値、調べてみませんか?
Oracleのスキルは需要が高く、特定の資格や経験を持っていると年収が大幅にアップするケースがあります。まずはIT専門のエージェントで非公開求人をチェックしてみませんか?

コメント