Oracle10g AWRに関する検証 その4
<Oracle10g AWR(Automatic Workload Repository)に関する検証 その4>
~自動SQLチューニング機能編~
ペンネーム:ちょびひげ
前回まで、以下の2つ表に関してみてきました。
□V$ACTIVE_SESSION_HISTORY
アクティブなセッションの「待ち」と「CPUを使用している」という情報の履
歴が記録される。これらの情報はデフォルトでは1分に1回、Oracleのバック
グラウンドプロセスによって記録される。
□DBA_HIST_ACTIVE_SESS_HISTORY(WRH$_ACTIVE_SESSION_HISTORY)
v$active_session_historyの情報が定期的に書き込まれるテーブルです。
デフォルトでは単位時間当りにv$active_session_historyの1/10の情報量が
格納されます。メモリ上では保持しきれない為、書き込まれます。
今回からはOEM(Oracle Enterprise Manager 10g)とSQLチューニング用のパ
ッケージであるDBMS_SQLTUNE機能を使って、問題のあるSQLの特定を行なって
いきます。
では早速、OEMでどのように、v$active_session_historyからSQLを取得して
いるのかを見ていきます。検証環境は以下の通りです。
*********************************************************************
OS :HP-UX hp11i B.11.11
Oracle:Release 10.1.0.2.0
上記の環境にOLTP系の一定のトランザクションを実施
*********************************************************************
■OEM(上位SQL)から問題のSQLを特定
OEMではSPOT(現在)とPERIOD(過去のある期間)のSQLが見れます。ではど
のくらいの期間がSPOTかといえば、v$active_session_historyに情報を保持
している期間です。
検証に基づく勘ですが、SPOT(現在)では以下のようなSQLでv$active_sessi
on_historyからSQLの情報を取得しているようです。
SELECT
event#, sql_id, max(sql_plan_hash_value), max(sql_opcode)
, session_id, p1
, current_obj#, module, action, client_id
, DECODE(wait_time, 0, 'W', 'C')
, COUNT(*),SUM(time_waited)
, 'I', service_hash, session_serial#, max(user_id), max(program)
FROM v$active_session_history
WHERE sample_time > :3
AND sample_time <= :4
GROUP BY event#, sql_id, session_id, p1, current_obj#
, module, action, client_id, DECODE(wait_time, 0, 'W', 'C')
, service_hash, session_serial#
ちょっと分かりづらいので重要な部分だけを抜き出し(書き換え)ます。
□最新5分のアクティブセッション情報を取得
SELECT
sql_id
, DECODE(wait_time, 0, 'WAITING', 'ON CPU')
, COUNT(*)
, SUM(time_waited)
FROM v$active_session_history
WHERE sample_time > sysdate - 5/60/24
AND sample_time < sysdate
GROUP BY
sql_id
, DECODE(wait_time, 0, 'WAITING', 'ON CPU')
SQL_ID EVENT COUNT TIME_WAITED
---------------- --------- ---------- ----------------
ON CPU 327 0
WAITING 3 83375
0rb68wt93hyk5 ON CPU 3 0
22v14pywpjbrn ON CPU 6 0
2b064ybzkwf1y ON CPU 1 0
2jka7qqgy3xw7 ON CPU 2 0
2umvfdn2qu9tt ON CPU 4 0
37nvf97dxf5jg ON CPU 1 0
37nvf97dxf5jg WAITING 1 299744
^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^
38scc1w4puyms ON CPU 1 0
3918g7wvyb5bt ON CPU 2 0
3s8mjd045m52c WAITING 1 1373
4wv642fgmjmdm ON CPU 21 0
7u1s6ht5bx6mp ON CPU 5 0
83c1u36qb77zh ON CPU 58 0
8a6vguhsfapdx ON CPU 1 0
9gguxsq7w8cyq ON CPU 2 0
arq6hxb184y28 ON CPU 1 0
axsbhy26rk90y ON CPU 1 0
SQL_ID : SQLを一意に認識する為のカラム
TIME_WAITED : 単位は1/10000秒
イベント(EVENT)が”WAITNG”の場合は、SQLが待ち状態であり、サンプリング
時点での待ち時間の合計(TIME_WAITED)が確認出来ます。
■待ち時間が長いSQLが問題?
上記のSQLを見てどのSQLが問題と思われるでしょうか?
直感的には待ち時間(TIME_WAITED)が最も長いSQL(SQL_IDが37nvf97dxf5jg)
ではないでしょうか。では、v$active_session_historyから実際に何の待ち
なのかを調べて見ます。
※ここでは時間の条件は省きます
□v$active_session_historyより、SQL(SQL_IDが37nvf97dxf5jg)待ちイベ
ントを確認
select SAMPLE_TIME, TIME_WAITED, EVENT
from v$active_session_history
where TIME_WAITED > 0
and DECODE(wait_time, 0, 'WAITING', 'ON CPU') = 'WAITING'
and SQL_ID = '37nvf97dxf5jg'
^^^^^^^^^^^^^
SAMPLE_TIME TIME_WAITED EVENT
----------------------- ----------- ------------------------------
04-08-20 16:37:12.461 299744 enq: TX - row lock contention
04-08-20 16:19:37.691 532661 enq: TX - row lock contention
04-08-20 16:03:40.811 612359 enq: TX - row lock contention
04-08-20 16:01:18.671 354846 enq: TX - row lock contention
SQL_IDが”37nvf97dxf5jg”のSQLの待ちの原因は、row lock contention、つま
り”行ロック”でした。
■OEMでのSQLの待ち率(WAIT%)とは?
OEMでは全体から見たSQLの待ち率が見れます。待ち率が高いSQLほど問題があ
ると言えそうです。では、OEMではどのように待ち率を導き出しているのでし
ょうか?
■TIME_WAITEDから待ち率を計算?
単純に考えれば、TIME_WAITEDの値を元に、全体の待ち時間から、SQL毎の待ち
時間を求めていると考えられます。そうすると、さきほどのロック待ちのSQL
は全体から見た待ち率は100%に近い値になります。
※SQL_IDの無いSQLはここでは無視してください
しかし、OEMでは待ち時間が”299744″のSQL(SQL_IDが37nvf97dxf5jg)と”1373″
のSQL(SQL_IDが3s8mjd045m52c)は同じ待ち率となります。
なぜなら、COUNT数(頻度)が同じだからです。
■COUNT列が意味する事
SQL_IDとEVENTでグルーピングした結果としてのレコード数、つまりサンプリ
ングされる頻度です。頻度が高いと言う事はSQLの実行時間が長い、もしくは
、実行回数が多いと考えられます。
いずれにしも確率の問題で、どちらが正しいとは言い切れません。
なぜなら、v$active_session_historyの情報は1秒に1しかアクシブなセッシ
ョンの情報を取得しない為、1秒以下の短時間の待ちは拾えない確率が非常に
高いからです。ただし、サンプリングの頻度を高くすることにより信頼性は
向上します。もちろん、パフォーマンスの低下という副作用も考慮する必要
はありますが。
以上、夏の終わりを告げるカツオちゃん、茅ヶ崎にて