「DB重い、でも原因がわからない」——AWR(Automatic Workload Repository)レポートを読めるようになれば、パフォーマンス問題の原因が見えてきます。本記事ではAWRの見方・読み方・活用法を現場目線で解説します。
目次
1. AWRとは何か(3分で理解) {#about}
AWR(Automatic Workload Repository)は、Oracleが定期的(デフォルト1時間ごと)にパフォーマンス統計を自動収集・保存する仕組みです。
定期スナップショット取得
↓
AWRリポジトリ(SYSAUX表領域)に蓄積
↓
2スナップショット間の比較レポート出力
↓
「この1時間に何が起きていたか」を解析AWRで分かること:
- DBが重かった時間帯のTOP SQL
- CPUを食ったSQLとI/Oを食ったSQL
- どの待機イベントで詰まっていたか
- バッファキャッシュヒット率・解析比率などの主要指標
2. AWRレポートを出力する方法 {#generate}
SQL*Plusから出力する(最も確実)
-- DBA権限のユーザーで接続してから実行
@$ORACLE_HOME/rdbms/admin/awrrpt.sql対話形式の入力例:
Enter value for report_type: html ← html または text
Enter value for num_days: 1 ← 直近N日分のスナップショットを表示
Enter value for begin_snap: 1050 ← 開始スナップショットID
Enter value for end_snap: 1051 ← 終了スナップショットID
Enter value for report_name: awr_report ← ファイル名スナップショットIDを確認するSQL
SELECT
SNAP_ID,
TO_CHAR(BEGIN_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI') AS 開始時刻,
TO_CHAR(END_INTERVAL_TIME, 'YYYY-MM-DD HH24:MI') AS 終了時刻
FROM
DBA_HIST_SNAPSHOT
WHERE
BEGIN_INTERVAL_TIME >= SYSDATE - 2 -- 直近2日
ORDER BY
SNAP_ID DESC;SQLでAWRレポートを直接生成する
-- HTMLレポートをCLOBで取得
SELECT OUTPUT FROM TABLE(
DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML(
l_dbid => (SELECT DBID FROM V$DATABASE),
l_inst_num => 1,
l_bid => 1050, -- 開始スナップショットID
l_eid => 1051 -- 終了スナップショットID
)
);3. レポートの読み方:まず見るべき5つのセクション {#reading}
AWRレポートは200ページを超えることもありますが、最初に見るべきは5箇所です。
① Load Profile(負荷プロフィール)
Load Profile Per Second Per Transaction
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
DB Time(s): 12.5 0.8 ← 重要!
DB CPU(s): 8.3 0.5
Redo size: 523,124 34,200
Logical reads: 456,234 29,810
Physical reads: 8,123 530 ← 多いと要注意
Executes (SQL): 1,234 80
Transactions: 15DB Time が高い → DBが何らかの処理で忙しい
Physical reads が多い → キャッシュにないデータを大量に読んでいる(フルスキャン疑い)
② Instance Efficiency Percentages(効率指標)
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 99.98 Redo NoWait %: 100.00
Buffer Hit %: 98.23 ← 98%以上が目安(低いとI/Oが多い)
Library Hit %: 97.45 ← 95%以上が目安(低いとSQL解析が多い)
Execute to Parse %: 87.34 ← 高いほどバインド変数活用できている③ Top 10 Foreground Events(上位待機イベント)
Top 10 Foreground Events by Total Wait Time
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Event Waits Time(s) Avg Wait
--- ----- ------- --------
db file sequential read 45,123 1,234 27ms ← I/O待ち(インデックス読み)
db file scattered read 8,234 456 55ms ← I/O待ち(フルスキャン)
enq: TX - row lock contention 1,023 234 229ms ← ロック待ち!
log file sync 456 89 195ms ← COMMIT待ち④ SQL Statistics(SQLの統計)
重いSQL上位が複数の切り口でランキングされます。
⑤ Memory Statistics(メモリ統計)
SGAのコンポーネント別使用状況。
4. Top SQL:重いSQLを特定する {#top-sql}
AWRレポートの「SQL Statistics」セクションには以下のランキングがあります。
| セクション名 | 意味 | 見るべきとき |
|---|---|---|
| SQL by Elapsed Time | 合計経過時間が長いSQL | 全体的に遅い |
| SQL by CPU Time | CPU使用時間が多いSQL | CPU使用率が高い |
| SQL by Gets | バッファGets数が多いSQL | メモリ圧迫 |
| SQL by Reads | 物理読み込みが多いSQL | I/Oが遅い |
| SQL by Executions | 実行回数が最多のSQL | 頻繁に呼ばれるSQL |
| SQL by Parse Calls | 解析回数が多いSQL | バインド変数未使用の疑い |
AWRデータからSQLを直接取得する
-- 指定期間の重いSQLをAWRから取得
SELECT
s.SQL_ID,
ROUND(s.ELAPSED_TIME_DELTA / 1000000, 1) AS 経過秒,
s.EXECUTIONS_DELTA AS 実行回数,
ROUND(s.ELAPSED_TIME_DELTA / DECODE(s.EXECUTIONS_DELTA, 0, 1, s.EXECUTIONS_DELTA) / 1000000, 2) AS 平均秒,
SUBSTR(t.SQL_TEXT, 1, 100) AS SQL先頭
FROM
DBA_HIST_SQLSTAT s
JOIN DBA_HIST_SQLTEXT t ON s.SQL_ID = t.SQL_ID
WHERE
s.SNAP_ID BETWEEN 1050 AND 1051
AND s.EXECUTIONS_DELTA > 0
ORDER BY
経過秒 DESC
FETCH FIRST 20 ROWS ONLY;5. 待機イベント:ボトルネックを特定する {#wait-events}
待機イベントはDBがどこで「詰まっているか」を示す最重要指標です。
主要待機イベントの意味と対処
| 待機イベント | 意味 | 主な原因 | 対処 |
|---|---|---|---|
db file sequential read | インデックス経由のI/O待ち | I/Oサブシステムが遅い | ストレージ改善・適切なインデックス |
db file scattered read | フルスキャンのI/O待ち | フルスキャンSQL多数 | SQLチューニング・インデックス追加 |
enq: TX - row lock contention | 行ロック待ち | ロックの競合 | ロックしているセッションを調査 |
log file sync | REDOログのCOMMIT待ち | COMMIT頻度が多すぎる | バッチコミット間隔を調整 |
latch: shared pool | Shared Pool競合 | バインド変数未使用 | バインド変数を使用 |
direct path read | 並列スキャンI/O | 大量データのフルスキャン | 並列度の調整 |
CPU | CPU使用中(待機なし) | CPU処理が支配的 | SQLのCPU処理最適化 |
待機イベントをSQLで取得する
-- AWRスナップショット期間の待機イベントTop10
SELECT
e.EVENT_NAME,
e.TOTAL_WAITS_FG,
ROUND(e.TIME_WAITED_MICRO_FG / 1000000, 1) AS 待機秒,
ROUND(e.TIME_WAITED_MICRO_FG / NULLIF(e.TOTAL_WAITS_FG, 0) / 1000, 2) AS 平均待機ms
FROM
DBA_HIST_SYSTEM_EVENT e
WHERE
e.SNAP_ID = 1051
AND e.WAIT_CLASS != 'Idle'
ORDER BY
待機秒 DESC
FETCH FIRST 10 ROWS ONLY;6. AWRスナップショットの管理 {#snapshots}
スナップショットの保持期間と間隔を確認・変更する
-- 現在の設定確認
SELECT SNAP_INTERVAL, RETENTION FROM DBA_HIST_WR_CONTROL;
-- 間隔を30分に、保持期間を30日に変更
EXEC DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(
retention => 30 * 24 * 60, -- 30日(分単位)
interval => 30 -- 30分ごと
);手動でスナップショットを取得する
-- 今すぐスナップショットを取得
EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;古いスナップショットを削除する
-- SNAP_ID 1000〜1010 を削除
EXEC DBMS_WORKLOAD_REPOSITORY.DROP_SNAPSHOT_RANGE(
low_snap_id => 1000,
high_snap_id => 1010
);7. ASHレポートとの違いと使い分け {#ash}
| AWR | ASH | |
|---|---|---|
| 正式名称 | Automatic Workload Repository | Active Session History |
| 対象 | スナップショット期間全体の集計 | 直近数十分〜数時間の詳細 |
| 時間単位 | 時間単位(デフォルト1時間) | 秒単位(10秒ごとのサンプリング) |
| 主な用途 | 長期傾向の分析・定常的な重いSQL特定 | 特定の瞬間に何が起きたか特定 |
| レポート出力 | awrrpt.sql | ashrpt.sql |
「あの時間帯に急に遅くなった」→ ASHレポートを使う
-- ASHレポートを出力
@$ORACLE_HOME/rdbms/admin/ashrpt.sql8. まとめ:AWR活用の流れ {#summary}
パフォーマンス問題発生
│
├── Step1: 問題発生時刻のスナップショットIDを確認
│ DBA_HIST_SNAPSHOT
│
├── Step2: AWRレポートを出力
│ @$ORACLE_HOME/rdbms/admin/awrrpt.sql
│
├── Step3: Load Profile → DB Timeとフィジカルリードを確認
│
├── Step4: Top 10 Foreground Events → 待機イベントを確認
│ ├── I/O待ちが多い → SQL Statisticsへ
│ ├── ロック待ちが多い → V$LOCKでロック調査
│ └── CPU待ちが多い → CPU消費SQLを確認
│
├── Step5: SQL Statistics → 重いSQLを特定
│ → 実行計画を確認してチューニング
│
└── Step6: 改善後に再度AWRを取得して比較関連記事:









コメント