パフォーマンス・チューニング入門:アクティブ・セッション履歴
著者:Arup Nanda
過去の特定の時点で発生したパフォーマンス問題の根本原因を、セッションが切断された後で特定する。
パフォーマンス・チューニングをテーマにした以前の2つの記事(パフォーマンス・チューニング入門とパフォーマンス・チューニング入門:過去を診断)では、現在発生しているパフォーマンス・ボトルネックの原因を特定する方法と、過去に発生した問題の概要を確認する方法を説明しました。多くのケースでは、パフォーマンス問題の解決に役立つ情報をこれらのプロセスで取得できますが、過去の特定の時点で発生したことを正確に知りたい場合もあるでしょう。この記事では、過去に発生した正確なイベント・シーケンスを現行セッションではなく履歴セッションで特定する方法を説明します。
この記事の例を実行するには、setup.sqlスクリプトを実行します。このスクリプトによって、ARUPというユーザーと3つの表(TEST1、TEST2、およびTEST3)が作成されます。ほとんどないと思いますが、ARUPというユーザーがすでに存在する場合は、スクリプトを修正し、別の名前でユーザーを作成し、ARUPとなっているすべての箇所をその名前に置き換えてください。setup.sqlによって作成されるサンプル・データベースがデータベース内に占める領域は200MB未満です。
setup.sqlスクリプトを実行したら、ARUPで接続して4つのSQL*Plusセッションを開きます。そのうち3つのセッションで、test1.sql、test2.sql、upd1.sqlの各スクリプトをそれぞれ実行します。UNIXベースのシステムでupd1.sqlを実行する1つのセッションの例を次に示します。
# sqlplus arup/arup SQL> @upd1.sql
4つ目のセッションで再度upd1.sqlを実行します。すでに3つ目のセッションでupd1.sqlを実行しているため、この最後のセッションはハングします。upd1.sqlはTEST1表の1つの行を更新しますが、コミットを実行しないため、行がロックされたままになるのです。4つ目のセッションで同じスクリプトを実行すると、同じ行の更新が試行されます。ところがその行は3つ目のセッションでロックされているため、4つ目のセッションは、そのロックが解除されて行をロックできる状態になるまで待機します。
test1.sqlスクリプトとtest2.sqlスクリプトは大量のCPUを消費するように設計されているため、最初の2つのセッションはCPUの競合が原因で遅くなります。この2つのセッションの実行には非常に時間がかかります。
すべてのセッションを約10分間待機させてから、セッション1と2で[Ctrl]と[C]を押してスクリプトを停止し、それぞれのSQL*Plusセッションを終了します。セッション3で、commitと入力して[Enter]を押します。これにより行のロックが解除され、セッション4で"1 row updated"と表示されるのを確認できます。SQL*Plusセッション3と4を終了します。これで、ARUPで接続していたセッションはすべて閉じられ、過去のものになりました。
セットアップでは、4つのセッションのうち3つでパフォーマンス問題を擬似的に発生させる方法を紹介しました。これらが標準的なビジネス・アプリケーションであった場合は、アプリケーションに速度低下の兆候が現れ、それぞれのアプリケーション所有者やユーザーの怒りを買い、DBAであるあなたに無用な注目が集まっていたことでしょう。そのような注目を集めてしまったとして、あなたは次に何をすべきでしょうか。
パフォーマンス・チューニングに関する以前の2つの記事では、セッションのパフォーマンス問題の原因につながる手がかりを探す方法を説明しました。あいにく、このケースではそのテクニックが役に立ちません。V$SESSIONビューにはセッションのパフォーマンス問題の理由が表示されますが、この記事で問題を引き起こしていたセッションはすでに存在しません。他の重要なビューであるV$SESSION_EVENTには、セッションが待機していたすべての待機イベントが表示されますが、V$SESSIONビューと同様で、セッションが今もなおデータベース内でアクティブでなければ、このビューにはデータが表示されません。V$SESSTATビューにはセッションのリソース使用率が表示されるため、REDOやメモリなどのリソースをどのセッションがどの程度消費していたかを知る手がかりが得られます。しかしながら、パフォーマンス問題が発生したセッションはすべて過去のものであるため、これらのビューを調べても問題を解決できません。ある時点で発生した特定のイベントを、履歴セッションで判断する必要があります。トレースを有効にしていればトレース・ファイルでイベントを表示できたでしょうが、こうした問題を事前に予測していませんでした。また、トレースによってパフォーマンスが低下する可能性があるため、トレースを有効にしていませんでした。では、そうした古いセッションで発生したパフォーマンス問題の原因を今突き止めるにはどうしたらよいのでしょうか。
幸い、古いセッションのパフォーマンス問題は、Oracle Databaseのアクティブ・セッション履歴という機能を使用して簡単に調査できます。アクティブ・セッション履歴を使用するには、Oracle Database 10g Release 1から提供されているOracle Databaseのライセンス・オプションのOracle Diagnostics Packが必要ですのでご注意ください。
アクティブ・セッション履歴を有効にすると、1秒ごとにデータベースがポーリングされるため、アクティブ・セッションが識別され、ユーザーID、状態、接続元のマシン、実行中のSQLといった各関連情報がダンプされ、データベース・インスタンスのシステム・グローバル領域(SGA)内にあるASHバッファと呼ばれる特別な領域に格納されます。そのため、セッションが今現在データベース・インスタンスに存在していなくても、セッションの情報はASHバッファに取得されています。また、アクティブ・セッション履歴によってアクティビティが1秒ごとに記録されるため、セッションで実行されたアクティビティのスナップショットを秒単位で表示できます。つまり、アクティブ・セッション履歴はセッションのアクティビティを単一の写真ではなくムービーで表示してくれるのです(ASHバッファが一杯になると、データはディスクに書き込まれるようになり、スナップショットは1秒ごとではなく10秒ごとに取得されます。)
ASHバッファの内容はV$ACTIVE_SESSION_HISTORYというビューで調査できます。次に、V$ACTIVE_SESSION_HISTORYビューの重要な列をいくつか示します。
SAMPLE_ID:アクティブ・セッション履歴レコードの一意の識別子。
SAMPLE_TIME:すべてのアクティブ・セッションでこのデータが取得された時刻。
USER_ID:このセッションを作成したデータベース・ユーザーの、数字で表されたユーザーID(ユーザー名ではない)。
SESSION_ID:このセッションのセッションID(SID)。
SESSION_STATE:サンプルが取得されたときのセッションの状態。セッションが待機中だった場合はWAITINGと表示されます。それ以外の場合はON CPUと表示され、セッションが生産的に動作していたことが示されます。
EVENT:セッションの状態(SESSION_STATE列)がWAITINGの場合は、セッションが待機していたイベントがこの列に表示されます。
TIME_WAITED:セッションの状態がWAITINGの場合は、サンプルが取得された時点までに費やされた待機時間がこの列に表示されます。
WAIT_TIME:セッションが生産的に動作している(WAITING状態でない)場合は、セッションが前回の待機イベントを待機した時間がこの列に表示されます。
SQL_ID:サンプル取得時にセッションで実行されていたSQL文のID。
SQL_CHILD_NUMBER:カーソルの子番号。カーソルにバージョンが1つしかない場合、子番号は0になります。
V$ACTIVE_SESSION_HISTORY列の意味を知っていれば、履歴セッションが何を待機していたのか特定できます。特定を始めるには、パフォーマンスが低下したSQL文を実行していたアプリケーション所有者またはユーザーに次の2つのことを質問する必要があります。
ARUPユーザーでsetupスクリプトを実行したため、最初の質問の答えはARUPです。続いて、次のSQLを発行してARUPユーザーのUSER_IDを検索する必要があります。
select user_id
from dba_users
where username = 'ARUP';
USER_ID
—————————————
92
では、パフォーマンスの問題が発生したのは9月29日の午後4時55分から午後5時05分の間だったとユーザーから報告を受けたとします。この情報をもとにV$ACTIVE_SESSION_HISTORYビューを問い合せ、この期間内のARUPセッション(USER_ID 92を使用)のアクティビティを検索できます(リスト1を参照)。(スペースの関係で、出力結果は省略されています。)アクティブ・セッション履歴にはすべてのアクティブ・セッションに関する情報が収集されるため、セッションを識別するSID(SESSION_IDの下に表示)、収集時刻(SAMPLE_TIMEの下に表示)で出力結果を並べ替える必要があります。
では、出力結果の最初の行を調べてみましょう。この行には、SESSION_ID 39のセッションが、2012年9月29日の午後04時55分02秒379に、"enq: TX - row lock contention"イベントを待機していたことが示されています。セッションの状態はWAITINGであったため、WAIT_TIME列の値に意味はないので、この列は0と表示されています。アクティブ・セッション履歴に状態が取得されたときもセッションの状態はWAITINGであったため、TIME_WAITED列が0と表示されています。セッションが最終的にロックを取得したら、実行すべき処理を実行できる状態になり、待機するのを中止します。この時点で、セッションが待機していた合計時間がアクティブ・セッション履歴で更新されました。それが、リスト1の出力結果の太字で示されている最初の行(サンプル取得時刻:29-SEP-12 05.16.52.078)で、合計時間は1,310,761,160マイクロ秒(TIME_WAITED列に表示)、約22分と表示されています。これは何度も話しているアクティブ・セッション履歴のとても重要なプロパティです。WAIT_TIME列が0の意味は、セッションがまったく待機しなかったということではありません。前の行のWAIT_TIME列とTIME_WAITED列の値が0であるため、セッションがなんらかのイベントを1秒より長く待機していたことを意味するに過ぎません。実際の合計待機時間を判断するには、そのセッションで最後に出現した待機イベント(EVENT列の値)をアクティブ・セッション履歴で調べる必要があります。
午後04時55分02秒379から午後05時16分52秒078までロックを取得できなかったのが遅延の原因であるとユーザーに説明した場合、ユーザーはその時刻にセッションで実行されていたSQL文が何だったのかと質問する可能性があります。これはリスト1の出力結果から極めて簡単に取得できます。SESSION_ID 39のセッションは、SQL_IDがfx60htyzmz6wvで子番号(CH#)が0のSQL文を実行していました。
このSQL文のテキストは次の問合せを使用して取得できます。
select SQL_TEXT
from v$sql
where sql_id = 'fx60htyzmz6wv';
SQL_TEXT
————————————————————————————————————————————————
update test1 set status = 'D' where object_id = :b1
SQL文には、行をロックする必要があるUPDATEが含まれています。行が別のセッションによってロックされていたため、このセッション(SESSION_ID 39)はロックを取得できず、待機することが必要になりました。当然ユーザーは次にこう質問するでしょう。SQL文とセッションが待機していた表と行は具体的にどれで、行をロックしていたセッションはどれなのですか。これらも、リスト2に示している問合せを使用して、とても簡単に検索できます。BLOCKING_SESSION列はロックを保持していたセッションを示しています。このケースではSESSION_IDが43のセッションです。リスト2の出力結果には、行がロックされていた表のオブジェクトID(CURRENT_OBJ#)と、行の情報を取得するのに必要な他の情報も表示されています。リスト2の出力結果のデータをもとに、リスト3に示している問合せを使用して、ロックされていた行のROWIDを取得できます。ROWIDがAAAdvSAAHAAABGPAAwの行は、SESSION_ID 43のセッションによりロックされており、SESSION_ID 39のセッションから更新をリクエストされていました。これで、セッション(SESSION_ID 39)が遅くなっていた理由(ロックを取得できるまで22分間待機していました)、このセッションが実行していたSQL文、ロックを取得しようとしていた具体的な行に関する情報が手に入りました。これで、SESSION_ID 39のセッションで発生したパフォーマンス問題の根本原因を究明できました。
コード・リスト3:特定の行情報の取得
select
owner||'.'||object_name||':'||nvl(subobject_name,'-') obj_name,
dbms_rowid.rowid_create (
1,
o.data_object_id,
row_wait_file#,
row_wait_block#,
row_wait_row#
) row_id
from v$session s, dba_objects o
where sid = &sid
and o.data_object_id = s.row_wait_obj#
OBJ_NAME ROW_ID
————————————— ———————————————————
ARUP.TEST1:- AAAdvSAAHAAABGPAAw
セッション39のパフォーマンス低下の根本原因を究明できたので、今度はセッション44に注目してみましょう。リスト1の出力結果を改めて見てみると、セッション44が待機(SESSION_STATEの下にWAITINGと表示)と生産的な処理(ON CPUと表示)の間を行ったり来たりしていることがわかります。SESSION_ID 44でSAMPLE_TIMEが29-SEP-12 04.55.34.419 PMのセッションの先頭行を出力結果で確認します。SESSION_STATE列はWAITINGと表示されています。つまり、このときセッションは待機していました。EVENT列とTIME_WAITED列はそれぞれ、"resmgr:cpu quantum"、"109984"と表示されています。つまり、セッションは"resmgr:cpu quantum"イベントの時点ですでに109,984マイクロ秒(約0.11秒)待機していたことになります。リスト1の次の行は、約1秒後にサンプル取得された状態ですが、ここではSESSION_STATE列の値がON CPUと表示されています。つまり、セッションは待機していたのではなく、生産的な処理を実行していました。セッションがこの待機イベントを断続的に待機し、そのためにパフォーマンスが低下する理由を知る必要があります。
"resmgr:cpu quantum"イベントは、Oracle Databaseのデータベース・リソース管理機能によるものです。データベース・リソース管理はリソース・ガバナーの役割を果たします。つまり、すべてのセッションからのCPU需要の合計が100%を超えると個々のセッションのCPU消費を制限し、重要度の高いセッションが必要なCPUを取得できるようにします。出力結果にはセッションが待機していると表示されているため、SESSION_ID 44のセッションは、データベース・リソース管理にCPU使用率を制限されるほど多くのCPUをこの時点で消費していたと結論づけることができます。しかし、アプリケーション所有者は反論します。このアプリケーションは非常に重要であるのだから、リソース使用率が制約されるはずがないと。
こういったケースの場合は、CPU割当て制限が想定よりも厳しいコンシューマ・グループの下にセッションがあった可能性が考えられます。そのため、次のステップとして、現在ではなくその時点でこのセッションに対してアクティブだったコンシューマ・グループを検索します。幸い、この情報を検索する手順は単純です。サンプリング時点でセッションにアクティブだったコンシューマ・グループはアクティブ・セッション履歴に記録され、この情報はV$ACTIVE_SESSION_HISTORYビューのCONSUMER_GROUP_ID列に表示されます。この情報はリスト4に示す問合せを使用して確認できます。
コード・リスト4:コンシューマ・グループのリスト
select sample_time, session_state, event, consumer_group_id
from v$active_session_history
where user_id = 92
and sample_time between
to_date('29-SEP-12 04.55.02 PM','dd-MON-yy hh:mi:ss PM')
and
to_date('29-SEP-12 05.05.02 PM','dd-MON-yy hh:mi:ss PM')
and session_id = 44
order by 1;
SESSION
SAMPLE_TIME _STATE EVENT CONSUMER_GROUP_ID
————————————————————————— ——————— —————————————————— —————————————————
29-SEP-12 04.55.34.419 PM WAITING resmgr:cpu quantum 12166
29-SEP-12 04.55.35.419 PM ON CPU 12166
29-SEP-12 04.55.36.419 PM WAITING resmgr:cpu quantum 12166
29-SEP-12 04.55.37.419 PM ON CPU 12166
29-SEP-12 04.55.38.419 PM WAITING resmgr:cpu quantum 12166
29-SEP-12 04.55.39.419 PM WAITING resmgr:cpu quantum 12166
29-SEP-12 04.55.40.419 PM ON CPU 12166
… 出力結果は省略されています …
29-SEP-12 04.55.37.419 PM ON CPU 12162
29-SEP-12 04.55.38.419 PM ON CPU 12166
29-SEP-12 04.55.39.419 PM ON CPU 12162
29-SEP-12 04.55.40.419 PM ON CPU 12162
いろいろなコンシューマ・グループの下にセッションがあった可能性もあるため、1つのサンプルだけではなく、アクティブ・セッション履歴にサンプル取得されているそのセッションのすべてのデータのコンシューマ・グループを選択するのが賢明です。このケースでは、2012年9月29日午後04時55分37秒419にコンシューマ・グループが12162に変更されるまで、セッションは12166の下にありました。コンシューマ・グループの名前を検索するには、次の問合せを使用します。
select name
from v$rsrc_consumer_group
where id in (12166,12162);
ID NAME
—————— ————————————
12166 OTHER_GROUPS
12162 APP_GROUP
リスト4の出力結果を見ると、セッションは午後04時55分34秒419以降、consumer_group_id 12166の下にありました。これはOTHER_GROUPSです(上のv$rsrc_consumer_groupに対する問合せに表示されています)。CONSUMER_GROUP_IDは午後04時55分37秒419の時点で12166から12162に変更されました。こうした変更は、もっとも可能性の高い3つの理由のうちの1つが原因で発生したと考えられます。3つの理由とは、1) DBAが別のリソース・プランを手動でアクティブ化した、2) スケジュール・メカニズムにより、別のリソース・プランが自動的にアクティブ化された、3) DBAがセッションのコンシューマ・グループをOTHER_GROUPSからAPP_GROUP(これも上のv$rsrc_consumer_groupに対する問合せで表示されています)にオンラインで変更した、です。理由がどうあれ、APP_GROUPコンシューマ・グループがアクティブのとき、セッションは"resmgr:cpu quantum"イベントを待機するより生産性の高い処理を実行しています(SESSION_STATEの値がON CPU)。この観察からさまざまな結論が導かれる可能性がありますが、もっとも明白なのは、おそらくAPP_GROUPコンシューマ・グループのほうがCPU割当てに関してはOTHER_GROUPSより制限が緩いということです。その場合は、OTHER_GROUPSコンシューマ・グループが初期の段階からアクティブ化された理由を調べる必要があります。また、こちらのほうが重要だと思いますが、この制限が必要だったのか単なるミスだったのかも調べる必要があります。ともかく、これで、待機が発生していた根本原因がわかりました。
次はきっと、セッション44がデータベース・リソース管理の制約を受けなければならないほど大量のCPUを消費した理由を質問されるでしょう。答えはセッション44が(現在ではなく)その時点で実行していたSQL文にあります。リスト1の出力結果のSQL_ID列はfngb4y81xr57xです。このSQL文のテキストは、次の問合せを使用して取得できます。
SQL> select SQL_TEXT from v$sql
where sql_id = 'fngb4y81xr57x';
SQL_TEXT
———————————————————————————————————
SELECT MAX(TEST1.OWNER) FROM TEST1,
TEST2, TEST2, TEST2, TEST2, TEST2,
TEST2, TEST2, TEST2, TEST2, TEST2,
TEST2, TEST2, TEST2, TEST2, TEST2,
TEST2, TEST2, TEST2, TEST2, TEST2,
TEST2, TEST2, TEST2, TEST2
出力結果を見れば、TEST2表に対して何回もデカルト結合(表のすべての行を、結合条件なしで別の表のすべての行と結合する処理)が実行されていたことがすぐにわかります。TEST2表の行数が比較的少ないとしても、デカルト結合を実行すると大量の論理I/Oが発生します。論理I/OではCPUサイクルの実行が必要であるため、データベース・リソース管理によって制限がかけられるほどセッションがCPUを消費したことは意外ではありません。この問題を解決するには、問合せを記述し直し、デカルト結合をなくすか減らす必要があります。
ここまでの項で、過去の特定の時点で発生した問題をアクティブ・セッション履歴で検索する方法を確認しました。アクティブ・セッション履歴がどれほど役立ち、多くの場合にどのように使用できるのか、その概要をつかんでいただけたのではないでしょうか。ここで、アクティブ・セッション履歴の能力と用途を別の例で見てみましょう。9月29日の午後4時55分から午後5時5分までの間、特定のクライアント・マシン(prolaps01)からの処理が遅かったようだと、ユーザーから苦情が来たとします。アクティブ・セッション履歴にはマシン名も記録されているため、リスト5に示す問合せを使用して、prolaps01マシンから接続したすべてのセッションで発生したあらゆるイベントと各イベントの発生回数を表示できます。リスト5の出力結果を見ると、この期間中、prolaps01クライアント・マシンから接続したセッションでは、ロックとリソース・マネージャに関連する待機が何回も発生していたことがわかります。この情報をもとに、V$ACTIVE_SESSION_HISTORYビューをさらに詳しく調査して、具体的なセッションと、これらの待機が発生する前にセッションが実行していたことを特定できます。
コード・リスト5:あるマシンで発生したすべてのイベントの確認
select event, count(1)
from v$active_session_history
where machine = 'prolaps01'
and sample_time between
to_date('29-SEP-12 04.55.00 PM','dd-MON-yy hh:mi:ss PM')
and
to_date('29-SEP-12 05.05.00 PM','dd-MON-yy hh:mi:ss PM')
group by event
order by event;
EVENT COUNT(1)
———————————————————————————— ————————
… 出力は省略されています …
db file scattered read 93
db file parallel write 127
log file parallel write 134
db file sequential read 293
control file parallel write 612
control file sequential read 948
enq:TX - row lock contention 1309
resmgr:cpu quantum 1371
特定のデータをアクティブ・セッション履歴から抽出する方法はスポット分析には最適ですが、ある期間内のアクティブ・セッション履歴データをすべてまとめて確認することが必要になる場合があります。その場合は、特定の期間についてのアクティブ・セッション履歴レポートが適しています。アクティブ・セッション履歴レポートはOracle Enterprise Managerまたはコマンドラインから生成できます。コマンドラインを使用する場合は、DBAユーザーでデータベースに接続し、SQL*Plusプロンプトでスクリプト(@$ORACLE_HOME/rdbms/admin/ashrpt.sql)を実行します。
この手順についての詳細は"次のステップ"を参照してください。
アクティブ・セッション履歴には、データベース・インスタンスのアクティブ・セッションに関する情報が1秒ごとに収集されます。そのため、データベースのアクティビティによっては、大量のデータがASHバッファ内に収集されることになりますが、ASHバッファはメモリ常駐型の構造であるため、バッファの領域サイズには限りがあります。また、インスタンスが停止すると、インスタンスのメモリも一緒に消えてしまいます。そのためOracle Databaseでは、ASHバッファの情報をデータベース表にアーカイブし、情報を永続化します。このアーカイブされた表データはDBA_HIST_ACTIVE_SESS_HISTORYというビューで表示できます。V$ACTIVE_SESSION_HISTORYビューでデータが見つからない場合は、DBA_HIST_ACTIVE_SESS_HISTORYビューで確認してください(リスト6を参照)。出力結果を見ると、セッションでは行ロックの待機が発生していました。ロックおよび行の情報は、リスト7に示す問合せを使用してDBA_HIST_ACTIVE_SESS_HISTORYビューから取得できます。
コード・リスト7:アクティブ・セッション履歴アーカイブからの行ロック情報の取得
記事をお読みください。 "パフォーマンス・チューニング入門" "パフォーマンス・チューニング:過去を診断"
パフォーマンス・チューニングの詳細を参照してください。 Oracle Database 2日でパフォーマンス・チューニング・ガイド11g Release 2 (11.2) アクティブ・セッション履歴レポートの生成と使用
select sample_time, session_state, blocking_session,
owner||'.'||object_name||':'||nvl(subobject_name,'-') obj_name,
dbms_ROWID.ROWID_create (
1,
o.data_object_id,
current_file#,
current_block#,
current_row#
) row_id
from dba_hist_active_sess_history s, dba_objects o
where user_id = 92
and sample_time between
to_date('29-SEP-12 04.55.02 PM','dd-MON-yy hh:mi:ss PM')
and
to_date('29-SEP-12 05.05.02 PM','dd-MON-yy hh:mi:ss PM')
and event = 'enq:TX - row lock contention'
and o.data_object_id = s.current_obj#
order by 1,2;
アクティブ・セッション履歴はOracle Databaseに搭載された非常に強力な機能です。データベース・インスタンスのすべてのアクティブ・セッションに関する情報が1秒ごとにバッファに記録されます。このデータはV$ACTIVE_SESSION_HISTORYというビューで表示でき、その後、DBA_HIST_ACTIVE_SESS_HISTORYビューで表示できる永続表にアーカイブされます。アクティブ・セッション履歴を使用すると、セッション内のアクティビティが1秒ごとに記録されるため、セッションが切断されていても、アクティビティが終了していても、時間をさかのぼって、過去のある時点で特定のセッションを阻害していた事象を突き止めることができます。
Setup.sql
REM This to for setting up the test users, tables, etc.
REM
REM Create the user.If this user exists, use a different name
REM
create user arup identified by arup
/
grant create session, unlimited tablespace, create table to arup
/
connect arup/arup
REM
REM create all test tables
REM
drop table test1
/
drop table test2
/
drop table test3
/
create table test1
as
select * from all_objects
/
create table test2
as
select * from test1
/
create table test3
as
select rownum col1, created col2
from test2
/
スクリプト:test1.sql
declare
l_dummy_1 varchar2(2000);
l_dummy_2 varchar2(2000);
l_stmt varchar2(2000);
begin
for i in 1..71540 loop
l_stmt :=
'select to_char(col2,''mm/dd/yyyy hh24:mi:ss'')'||
' from test3'||
' where col1 = to_char('||i||')';
dbms_output.put_line('l_stmt='||l_stmt);
execute immediate l_stmt into l_dummy_1;
l_stmt :=
'select col1 '||
'from test3 '||
'where col2 = to_date('''||
l_dummy_1||
''',''mm/dd/yyyy hh24:mi:ss'')'||
' and col1 = '''||to_char(i)||'''';
dbms_output.put_line('l_stmt='||l_stmt);
execute immediate l_stmt into l_dummy_2;
end loop;
end;
/
スクリプト:test2.sql
declare
l_dummy varchar2(200);
begin
select max(test1.owner)
into l_dummy
from test1, test2, test2, test2, test2,
test2, test2, test2, test2,
test2, test2, test2, test2,
test2, test2, test2, test2,
test2, test2, test2, test2,
test2, test2, test2, test2;
dbms_lock.sleep(120);
end;
/
スクリプト:upd1.sql
update test1 set status = 'D' where object_id = 2
/
Part 1. パフォーマンス・チューニング入門
Part 2. パフォーマンス・チューニング入門:過去を診断
Part 3. パフォーマンス・チューニング入門:アクティブ・セッション履歴
Arup Nanda(arup@proligence.com)は1993年以来、Oracle DBAとしてパフォーマンス・チューニングからセキュリティやディザスタ・リカバリまで、データベース管理のさまざまな分野に携わってきました。2003年のOracle MagazineでDBA of the Yearに選ばれ、2012年にはOracle Excellence Award for Technologist of the Yearを受賞しました。