このエントリは「JPOUG Advent Calendar 2016」の13日目です。
昨日はcharade_oo4oさんの「Oracle on Hyper-V 2016」 でした。
複数のAWRレポートを作成するのは面倒
AWRスナップショットはデフォルトで1時間に1回取得されるので、レポート期間1時間のAWRレポートは1日分で24個になる。
1日分のレポートを1個ずつ作成するのは面倒なので、一度に作成する方法を考えてみた。
考慮する仕様は以下の3つ
- 本日からn日前以降のレポートを全て出力する。(ただし本日分は含まない)
- レポート期間は1時間で連続するスナップショットIDを指定する。
- スナップショットはMMONプロセスで自動的に取得されたものを対象とする。(定常運用をイメージしているので、負荷テスト時のようにスナップショットをアドホックに取得していないことを前提。ちなみに手動で取得すると毎正時の自動取得がスキップされる場合があるので注意。)
作成用スクリプト
以下のPL/SQLスクリプトに適当な名前を付けて保存する。(例では「mkscr.sql」)
set echo off set feedback off set verify off set trimspool on set serveroutput on spool getawrr.sql replace DECLARE num_day NUMBER := &1; CURSOR sid_cur IS select -- es.DBID es.INSTANCE_NUMBER ,to_char(round(bs.END_INTERVAL_TIME,'mi'),'yyyy/mm/dd hh24') BEGIN_HOUR ,bs.SNAP_ID BEGIN_SNAP ,es.SNAP_ID END_SNAP from DBA_HIST_SNAPSHOT bs ,DBA_HIST_SNAPSHOT es where 1=1 and bs.END_INTERVAL_TIME >= trunc(sysdate-num_day) and bs.END_INTERVAL_TIME < trunc(sysdate) -- and trunc(es.END_INTERVAL_TIME,'mi') = trunc(bs.END_INTERVAL_TIME,'mi') + 1/24 and abs(round(es.END_INTERVAL_TIME,'mi') - round(bs.END_INTERVAL_TIME,'mi') < (1/24)*1.1 and bs.SNAP_ID < es.SNAP_ID and bs.DBID = es.DBID and bs.INSTANCE_NUMBER = es.INSTANCE_NUMBER and bs.SNAP_FLAG = 0 and es.SNAP_FLAG = 0 order by bs.END_INTERVAL_TIME; BEGIN FOR sid_rec IN sid_cur LOOP dbms_output.put_line('-- '||sid_rec.BEGIN_HOUR); dbms_output.put_line('define report_type=html'); dbms_output.put_line('define num_days='||num_day); dbms_output.put_line('define begin_snap='||sid_rec.BEGIN_SNAP); dbms_output.put_line('define end_snap='||sid_rec.END_SNAP); dbms_output.put_line('define report_name=awrrpt_'||sid_rec.INSTANCE_NUMBER||'_'||sid_rec.BEGIN_SNAP||'_'||sid_rec.END_SNAP||'.html'); dbms_output.put_line('@?/rdbms/admin/awrrpt.sql'); END LOOP; END; / spool off set echo on set feedback on set verify on
補足説明
- 8行目:n日前の「n」は実行時に引数で置換変数に渡す。
- 20行目:n日前以降の条件。AWRリポジトリに残っている以上の日数も指定できるが、データがないので残っている分しかレポートはできない。
22行目:1時間ごとにスナップショットを取得している場合。30分間隔であれば「1/48」に書き換える。- 23,24行目:22行目の条件だとスナップショット間隔がきっかり1時間でない場合のレポートが欠損してしまうため、10%(1時間であれば6分)未満の誤差にも対応した。
- 27,28行目:PL/SQLパッケージ(DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT)により手動で取得されたスナップショットを除外している。(この条件はなくてもよいかも。)
- 34行目:レポートファイル名は対話型で実行した場合のデフォルト名で出力するようにした。
実行例
実行方法は簡単。作成用スクリプトを実行(1行目)し、SQL*Plusを起動したカレント・ディレクトリに出力されたスクリプト(例では「getawrr.sql」、内容は上書きされるので最後に実行した内容が保存される。)を実行(35行目)するだけでよい。
注意点としては、日数を引数で必ず指定することである。(未指定の場合のハンドリングは特に考慮していない。)
SQL> @mkscr 1 <=== 必ず日数を引数で指定する SQL> set echo off -- 2016/12/06 00 define report_type=html define num_days=1 define begin_snap=4686 define end_snap=4687 define report_name=awrrpt_1_4686_4687.html @?/rdbms/admin/awrrpt.sql -- 2016/12/06 01 define report_type=html define num_days=1 define begin_snap=4687 define end_snap=4688 define report_name=awrrpt_1_4687_4688.html ................................................. -- 2016/12/06 22 define report_type=html define num_days=1 define begin_snap=4708 define end_snap=4709 define report_name=awrrpt_1_4708_4709.html @?/rdbms/admin/awrrpt.sql -- 2016/12/06 23 define report_type=html define num_days=1 define begin_snap=4709 define end_snap=4710 define report_name=awrrpt_1_4709_4710.html @?/rdbms/admin/awrrpt.sql SQL> set feedback on SQL> set verify on SQL> !ls -l getawrr.sql -rw-r--r--. 1 oracle oinstall 4128 12月 7 17:24 2016 getawrr.sql SQL> @getawrr.sql <== 生成されたスクリプトを実行する (以下、AWRレポート作成)
これで複数(1日分であれば24個)のAWRレポートが一気に作成される。(レポート内容によっては時間がかかるので、実行タイミングはDBサーバの負荷状況に留意したほうがよいだろう。)
特定の時間帯だけが必要であれば、該当部分をコピペで選択して実行してもよい。
カレントディレクトリに出力されるので、実行するディレクトリをどこにするかを考慮した方がよいかもしれない。
もっと手抜きして、作成用スクリプトの最終行に「@生成スクリプト名」を追記すれば、一気に作成まで行うことができる。(今回は生成スクリプトの内容を一度確認することも考慮して別に実行することとした。)
明日はYousuke Yadaさんです。