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文の実行以外にかかった時間を表すもの…ということですね。
どこにチューニングポイントがあるのか?を、ざっくり判断する材料に
使えそうです。
寒くなってきました茅ヶ崎にて