【Oracle】AWR・ASH完全ガイド|スナップショット管理・レポートの読み方・ASHで過去の問題を特定する方法まで解説

【Oracle】AWR・ASH完全ガイド|スナップショット管理・レポートの読み方・ASHで過去の問題を特定する方法まで解説 Oracle

「昨夜の深夜2時にシステムが遅かった」という問い合わせを受けたとき、そのときのセッション・SQL・待機状況を後から調べる手段が AWR(Automatic Workload Repository)ASH(Active Session History)です。

AWR はインスタンス全体の統計スナップショットを定期的に取得し、ASH はアクティブセッションを1秒ごとにサンプリングして過去の状態を再現できます。どちらも Oracle Enterprise Edition の機能(Diagnostics Pack ライセンス必要)で、DBA_HIST_* ビュー群としてアクセスできます。

この記事でわかること

  • AWR スナップショットの仕組みと管理(取得間隔・保存期間の変更)
  • 手動でスナップショットを取得する方法(DBMS_WORKLOAD_REPOSITORY)
  • AWR レポートの生成方法と主要セクションの読み方
  • ASH(V$ACTIVE_SESSION_HISTORY・DBA_HIST_ACTIVE_SESS_HISTORY)で過去の問題を特定する
  • ADDM(自動データベース診断モニター)の診断結果の確認方法
  • DBA_HIST_SQLSTAT・DBA_HIST_SYSTEM_EVENT を使った SQL・待機の長期分析
Diagnostics Pack ライセンスが必要
AWR・ASH・ADDM の使用には Oracle Enterprise Edition に加えてDiagnostics Pack(Oracle Database Management Packs)のライセンスが必要です。ライセンスなしで DBA_HIST_* ビューにアクセスすることは契約違反になる場合があります。必ずライセンスを確認してから使用してください。
スポンサーリンク

AWR の仕組みとスナップショット管理

MMON バックグラウンドプロセスが定期的に(デフォルト:60分ごと)統計情報を SYSAUX 表領域に書き出します。このひとかたまりのデータを スナップショット と呼び、デフォルトで 8日間(691,200秒)保存されます。

現在の AWR スナップショット設定を確認する(DBA権限必要)
-- 取得間隔と保存期間を確認
SELECT
    snap_interval,            -- スナップショット取得間隔
    retention,                -- 保存期間
    topnsql                   -- AWR に保存するトップSQL件数
FROM DBA_HIST_WR_CONTROL;

-- スナップショットの一覧と取得時刻を確認
SELECT
    snap_id,
    instance_number,
    TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS begin_time,
    TO_CHAR(end_interval_time,   'YYYY-MM-DD HH24:MI') AS end_time
FROM DBA_HIST_SNAPSHOT
ORDER BY snap_id DESC
FETCH FIRST 10 ROWS ONLY;
AWR スナップショット設定を変更する(DBA権限必要)
-- 取得間隔を 30分、保存期間を 14日に変更
BEGIN
    DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(
        retention => 14 * 24 * 60,   -- 保存期間(分)= 14日
        interval  => 30,             -- 取得間隔(分)= 30分
        topnsql   => 100             -- トップSQL保存件数(デフォルト30)
    );
END;
/

-- 即座にスナップショットを手動取得する
BEGIN
    DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;
END;
/
-- または
EXEC DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT;

-- 古いスナップショットを手動削除する
BEGIN
    DBMS_WORKLOAD_REPOSITORY.DROP_SNAPSHOT_RANGE(
        low_snap_id  => 100,  -- 削除開始スナップショットID
        high_snap_id => 150   -- 削除終了スナップショットID
    );
END;
/

AWR レポートの生成と主要セクションの読み方

AWR レポートは2つのスナップショット間の差分統計をまとめたレポートです。SQL*Plus やスクリプトから生成できます。

SQL*Plus から AWR レポートを生成する
-- SQL*Plus から対話式でレポートを生成(スナップショットIDを選択する)
@$ORACLE_HOME/rdbms/admin/awrrpt.sql

-- HTML 形式のレポートを直接生成する(snap_id を直接指定)
SELECT OUTPUT
FROM TABLE(
    DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML(
        l_dbid       => (SELECT dbid FROM V$DATABASE),
        l_inst_num   => 1,
        l_bid        => 200,   -- 開始スナップショットID(begin)
        l_eid        => 210    -- 終了スナップショットID(end)
    )
);

AWR レポートの主要セクション

セクション名 内容 チューニングでの注目点
DB Time 期間中の総 DB 処理時間(CPU + 非アイドル待機) DB Time が大きいほど負荷が高い
Top 10 Foreground Events by Total Wait Time 待機時間が多い上位イベント(Idle 除く) 最重要セクション。ボトルネックの待機イベントを特定する
SQL ordered by Elapsed Time 実行時間の合計が多い SQL Top 50 チューニング対象 SQL の優先度付けに使う
SQL ordered by Gets バッファ読み込みが多い SQL 論理 I/O が高い非効率 SQL の特定
SQL ordered by Reads 物理読み込みが多い SQL フルスキャンなど I/O バウンドの SQL の特定
Instance Efficiency バッファキャッシュヒット率・ライブラリキャッシュヒット率など 各ヒット率が 95%以上かを確認
Load Profile 期間あたりの SQL 実行数・ハードパース数・トランザクション数など ハードパース数が多ければバインド変数の未使用が疑われる

DBA_HIST_SQLSTAT で SQL の長期パフォーマンス推移を確認する

特定の SQL の実行統計の推移を確認する
-- sql_id を指定して日次の平均実行時間を確認する
SELECT
    TO_CHAR(sn.begin_interval_time, 'YYYY-MM-DD HH24') AS hour,
    s.plan_hash_value,
    s.executions_delta                                  AS exec_count,
    ROUND(s.elapsed_time_delta
          / NULLIF(s.executions_delta, 0) / 1000000, 2) AS avg_elapsed_sec,
    ROUND(s.buffer_gets_delta
          / NULLIF(s.executions_delta, 0), 0)           AS avg_gets
FROM DBA_HIST_SQLSTAT s
JOIN DBA_HIST_SNAPSHOT sn
  ON s.snap_id = sn.snap_id AND s.instance_number = sn.instance_number
WHERE s.sql_id = 'abc123xyz'   -- 確認したい sql_id を指定
  AND sn.begin_interval_time >= SYSDATE - 7
ORDER BY sn.snap_id;

-- ある期間のトップ SQL(経過時間合計の Top 10)
SELECT
    s.sql_id,
    ROUND(SUM(s.elapsed_time_delta) / 1000000, 2)   AS total_elapsed_sec,
    SUM(s.executions_delta)                          AS total_execs,
    ROUND(SUM(s.elapsed_time_delta)
          / NULLIF(SUM(s.executions_delta), 0) / 1000000, 4) AS avg_elapsed_sec,
    MAX(SUBSTR(t.sql_text, 1, 60))                  AS sql_preview
FROM DBA_HIST_SQLSTAT s
JOIN DBA_HIST_SNAPSHOT sn
  ON s.snap_id = sn.snap_id AND s.instance_number = sn.instance_number
LEFT JOIN DBA_HIST_SQLTEXT t ON s.sql_id = t.sql_id
WHERE sn.begin_interval_time BETWEEN
      TO_DATE('2024-04-01', 'YYYY-MM-DD') AND
      TO_DATE('2024-04-02', 'YYYY-MM-DD')
  AND s.executions_delta > 0
GROUP BY s.sql_id
ORDER BY total_elapsed_sec DESC
FETCH FIRST 10 ROWS ONLY;

ASH(Active Session History)で過去の問題を再現する

ASH は アクティブセッションを1秒ごとにサンプリングして記録します。インメモリの V$ACTIVE_SESSION_HISTORY(最近数十分)と、それを定期的に AWR に書き出した DBA_HIST_ACTIVE_SESS_HISTORY(最大8日間)があります。

「昨夜2時に遅かった」という時刻を指定して、そのときどのセッションが・何のSQLで・何を待っていたかを後から特定できます。

ASH で特定時刻のボトルネックを特定する
-- 指定した時刻帯(例: 昨夜2時台)に最も待機が多かったイベントを確認
SELECT
    event,
    wait_class,
    COUNT(*)                AS sample_count,
    ROUND(COUNT(*) * 100.0
        / SUM(COUNT(*)) OVER (), 1) AS pct
FROM DBA_HIST_ACTIVE_SESS_HISTORY
WHERE sample_time BETWEEN
      TO_TIMESTAMP('2024-04-01 02:00', 'YYYY-MM-DD HH24:MI') AND
      TO_TIMESTAMP('2024-04-01 03:00', 'YYYY-MM-DD HH24:MI')
  AND session_type = 'FOREGROUND'    -- ユーザーセッションのみ
  AND session_state = 'WAITING'      -- 待機中のサンプルのみ
GROUP BY event, wait_class
ORDER BY sample_count DESC;

-- 同時刻帯でどの SQL が最も多くサンプリングされたか(= 最も処理時間を使ったか)
SELECT
    ash.sql_id,
    COUNT(*)                    AS samples,
    MAX(SUBSTR(t.sql_text, 1, 70)) AS sql_preview
FROM DBA_HIST_ACTIVE_SESS_HISTORY ash
LEFT JOIN DBA_HIST_SQLTEXT t ON ash.sql_id = t.sql_id
WHERE ash.sample_time BETWEEN
      TO_TIMESTAMP('2024-04-01 02:00', 'YYYY-MM-DD HH24:MI') AND
      TO_TIMESTAMP('2024-04-01 03:00', 'YYYY-MM-DD HH24:MI')
  AND ash.session_type = 'FOREGROUND'
GROUP BY ash.sql_id
ORDER BY samples DESC
FETCH FIRST 10 ROWS ONLY;
ASH でリアルタイムの状況を確認する(V$ACTIVE_SESSION_HISTORY)
-- 直近 10 分間のトップ待機(インメモリの ASH)
SELECT
    event,
    COUNT(*)  AS samples
FROM V$ACTIVE_SESSION_HISTORY
WHERE sample_time >= SYSDATE - 10/1440   -- 過去10分
  AND session_type = 'FOREGROUND'
  AND session_state = 'WAITING'
GROUP BY event
ORDER BY samples DESC
FETCH FIRST 10 ROWS ONLY;

-- 直近 10 分でアクティブだったユーザー・SQL を確認
SELECT
    ash.user_id,
    u.username,
    ash.sql_id,
    COUNT(*) AS samples
FROM V$ACTIVE_SESSION_HISTORY ash
JOIN DBA_USERS u ON ash.user_id = u.user_id
WHERE ash.sample_time >= SYSDATE - 10/1440
  AND ash.session_type = 'FOREGROUND'
GROUP BY ash.user_id, u.username, ash.sql_id
ORDER BY samples DESC;

ADDM の自動診断結果を確認する

ADDM(Automatic Database Diagnostic Monitor)は AWR のスナップショットを分析してパフォーマンス問題を自動診断し、改善アクションを提案します。AWR スナップショットが取得されるたびに自動的に実行されます。

ADDM の診断結果を確認する(DBA権限必要)
-- 最近の ADDM タスクの一覧
SELECT
    task_name,
    description,
    created,
    status
FROM DBA_ADVISOR_TASKS
WHERE advisor_name = 'ADDM'
ORDER BY created DESC
FETCH FIRST 5 ROWS ONLY;

-- 特定の ADDM タスクの診断結果(推奨事項)を確認
SELECT
    f.type,
    f.impact,           -- ベネフィット推定(DB Time の削減率 %)
    f.message
FROM DBA_ADVISOR_FINDINGS f
WHERE f.task_name = 'ADDM:12345678'  -- DBA_ADVISOR_TASKS の task_name を指定
ORDER BY f.impact DESC;

-- 特定の ADDM 推奨事項(アクション)を確認
SELECT
    r.rank,
    r.benefit,
    r.message
FROM DBA_ADVISOR_RECOMMENDATIONS r
WHERE r.task_name = 'ADDM:12345678'
ORDER BY r.benefit DESC;

よく使う分析パターン

障害発生前後のスナップショットを特定する

障害時刻に対応するスナップショットIDを特定する
-- 障害発生時刻(例: 2024-04-01 02:30)を挟むスナップショットを特定
SELECT
    snap_id,
    TO_CHAR(begin_interval_time, 'YYYY-MM-DD HH24:MI') AS begin_time,
    TO_CHAR(end_interval_time,   'YYYY-MM-DD HH24:MI') AS end_time
FROM DBA_HIST_SNAPSHOT
WHERE begin_interval_time BETWEEN
      TO_DATE('2024-04-01 02:00', 'YYYY-MM-DD HH24:MI') AND
      TO_DATE('2024-04-01 04:00', 'YYYY-MM-DD HH24:MI')
ORDER BY snap_id;
-- → 得られたスナップショットIDを使って AWR レポートを生成

AWR の保存領域(SYSAUX)を確認する

AWR が使用している SYSAUX 表領域の容量を確認する
-- SYSAUX 内の AWR コンポーネントの使用量を確認
SELECT
    occupant_name,
    ROUND(space_usage_kbytes / 1024, 1) AS usage_mb
FROM V$SYSAUX_OCCUPANTS
WHERE occupant_name LIKE 'SM/%'   -- SM/AWR, SM/ASH など
ORDER BY space_usage_kbytes DESC;

まとめ

  • AWR スナップショット:デフォルト 60 分ごとに取得、8 日間保存。DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS で設定変更できる
  • AWR レポート:2スナップショット間の差分統計。Top 10 Foreground Events と SQL ordered by Elapsed Time が最重要セクション
  • DBA_HIST_SQLSTAT:特定の SQL の実行統計の時系列変化を確認できる。プラン変更の検出にも使える
  • ASH(DBA_HIST_ACTIVE_SESS_HISTORY):過去の特定時刻の待機状況・アクティブ SQL を後から再現できる。障害の事後分析に必須
  • ADDM:AWR から自動的にパフォーマンス問題を診断して推奨事項を提示する。DBA_ADVISOR_FINDINGS で確認する

待機イベントの意味と対処法は 待機イベント(Wait Events)完全ガイドを参照してください。AWR の分析対象になった SQL のプランは DBMS_XPLAN完全ガイドで詳細確認できます。遅い SQL の V$SQL を使ったリアルタイム特定方法は 遅いSQLを特定する方法完全ガイドを参照してください。