Oracle10gのSQLチューニングについての検証 その4
<Oracle10gのSQLチューニングについての検証 その4>
~v$sql活用編~
ペンネーム: りん
今年も後少しだということに最近気づいたりんです。こんにちは。
1年は早いですね…ラストスパート頑張りましょう。
さて、今回は、PLSQL_EXEC_TIMEについての検証です。
マニュアルには、PL/SQLの実行時間と記載されていますが…
なんの値なんでしょうか?早速見てみましょう。
SQL> begin 2 for cnt in 1..10000 loop 3 update test_table set value = cnt where id = cnt; 4 commit; 5 end loop; 6 end; 7 / PL/SQLプロシージャが正常に完了しました。
実行後のv$sqlビューの情報を確認します。
SQL> select sql_text, cpu_time, elapsed_time, plsql_exec_time from 2 v$sql where sql_text like 'begin%update test_table%'; SQL_TEXT -------------------------------------------------------------------------------- begin for cnt in 1..10000 loop update test_table set value = cnt whe re id = cnt; end loop; commit; end; CPU_TIME ELAPSED_TIME PLSQL_EXEC_TIME ---------- ------------ --------------- 37747674 37747674 326584
以下、トレース情報です。
=====================
PARSING IN CURSOR #1 len=123 dep=0 uid=0 oct=47 lid=0 tim=1074351234399781
hv=1054212170 ad='5bb1c764'
begin
for cnt in 1..10000 loop
update test_table set value = cnt where id = cnt;
end loop;
commit;
end;
END OF STMT
PARSE #1:c=170000,e=169400,p=2,cr=225,cu=0,mis=1,r=0,dep=0,og=1,tim=1074351234399747
BINDS #1:
...
EXEC #1:c=37650000,e=37578274,p=34,cr=230140,cu=10293,mis=0,r=1,dep=0,og=1,
tim=1074351271978309
CPU_TIMEと、ELAPSED_TIMEについては、PARSEとEXECの合算値のようですが…
326584マイクロ秒はどこから来たんでしょうねぇ
0.32秒…
プロファイラではどのように算出されるのでしょうか
少しプロシージャーを変更してやってみます。
declare
rc binary_integer;
exec_n number;
begin
rc := dbms_profiler.start_profiler('Start1','',exec_n);
for i in 1..10000 loop
insert into test_table values ( i,i,i,i,
'データデータデータデータデータデータデータ
データデータデータデータデータデータデータ
データデータデータデータデータデータデータ
データデータデータデータデータデータデータ
データ');←1行です。
commit;
end loop;
dbms_output.put_line ( ' Exec Number : ' || exec_n );
rc := dbms_profiler.stop_profiler;
end;
/
SQL> select sql_text,plsql_exec_time,cpu_time,elapsed_time from
2 v$sql where plsql_exec_time != 0;
SQL_TEXT
------------------------------------------------------------
declare rc binary_integer; exec_n number; begin rc := dbm
s_profiler.start_profiler('Start1','',exec_n); for i in 1..
10000 loop insert into test_table values ( i,i,i,i,'データ
データデータデータデータデータデータデータデータデータデータ
データデータデータデータデータデータデータデータデータデータ
データデータデータデータデータデータデータデータ'); commit
; end loop; dbms_output.put_line ( ' Exec Number : ' || ex
ec_n ); rc := dbms_profiler.stop_profiler; end;
PLSQL_EXEC_TIME CPU_TIME ELAPSED_TIME
--------------- ---------- ------------
1545390 23250000 42638849
1 select
2 runid,
3 sum(total_time)/1000 total_time_micro
4 from
5 plsql_profiler_data
6 where
7 runid=5
8 group by
9* runid
SQL> /
RUNID TOTAL_TIME_MICRO
---------- ----------------
5 38701834
やはり、PLSQL_EXEC_TIMEは全部の実行時間というわけではなさそうです。
CPU_TIMEよりも短い時間で終了しているようですし…
もう1度、dbms_profilerを除外してやってみましょう
declare
rc binary_integer;
exec_n number;
begin
for i in 1..10000 loop
insert into test_table values (
i,i,i,i,
'データデータデータデータデータデータ
データデータデータデータデータデータ
データデータデータデータデータデータ
データデータデータデータデータデータ
データデータデータデータデータ');
commit;
end loop;
end;
/
SQL> select sql_text,plsql_exec_time,cpu_time,elapsed_time from
2 v$sql where sql_text like 'declare%';
SQL_TEXT
------------------------------------------------------------
declare rc binary_integer; exec_n number; begin for i in
1..10000 loop insert into test_table values ( i,i,i,i,'デ
ータデータデータデータデータデータデータデータデータデータデ
ータデータデータデータデータデータデータデータデータデータデ
ータデータデータデータデータデータデータデータデータ'); co
mmit; end loop; end;
PLSQL_EXEC_TIME CPU_TIME ELAPSED_TIME
--------------- ---------- ------------
1195325 21790000 38434761
では、出力したトレースファイルから
PL/SQLブロックに記述しているINSERT文とCOMMITを除外してみると、再帰SQL
文の合計経過時間は977448マイクロ秒で、似たような数字になります。
PLSQL_EXEC_TIMEとは、PLSQLブロックで記述したSQL文以外のロジックでの
実行時間ということになりそうですね。
では、再帰SQL文の合計値ということなのでしょうか?
試しに、以下のPLSQLブロックを作成して実行してみます。
declare v_test number; begin for i in 1..10000 loop v_test := v_test + 1; end loop; end; /
V$SQLの結果は以下の通りです。
SQL> select sql_text,plsql_exec_time,cpu_time,elapsed_time from
2 v$sql where sql_text like 'declare%';
SQL_TEXT
------------------------------------------------------------
declare v_test number; begin for i in 1..100000 loop v_t
est := v_test + 1; end loop; end;
PLSQL_EXEC_TIME CPU_TIME ELAPSED_TIME
--------------- ---------- ------------
11221 20000 98299
このPL/SQLブロックのトレースを見ると…
Parsing…86892マイクロ秒 Exec…11407マイクロ秒
でした。
当然の結果ですが、PLSQL_EXEC_TIMEとトレースのEXECの大きな開きはありま
せんでした。ELAPSED_TIMEには、ParsingやEXEC、WAITも含まれますが
PLSQL_EXEC_TIMEというのは、PL/SQLブロックのロジックを実行していた
純粋な時間…つまり、SQLの実行時間やWAITなどを抜いた値のようですね。
…ということは、Oracle10gから追加されたWAIT_TIMEやEXEC_TIMEなどの
カラムは、SQL文以外の時間であると考えると、すっきりするかもしれません。
4回に渡って検証した今回のメルマガのまとめとしては
Oracle10gからV$SQLに追加されたApplication_Wait_TimeやPLSQL_EXEC_TIMEは
SQL文の実行以外にかかった時間を表すもの…ということですね。
どこにチューニングポイントがあるのか?を、ざっくり判断する材料に
使えそうです。
寒くなってきました茅ヶ崎にて