私は最近、MOSCフォーラムで、V$SQL_SHARED_CURSORビューのTOP_LEVEL_RPI_CURSOR列について質問した個人と協力していました。このコラムがDBAに伝えようとしていることに関するドキュメントはほとんどありません。
Oracleのドキュメントによると、この列には「(Y | N)Is toplevelRPIcursor」が含まれています。では、それはどういう意味ですか?
この投稿の読者は子カーソルに精通していると思います。それは私に大量の紹介情報を節約するでしょう。 V $ SQL_SHARED_CURSORビューは、子カーソルとその親が共有プールで異なるバージョンを持っている理由をDBAに通知します。このビューで子カーソルのOPTIMIZER_MISMATCH列に「Y」が含まれている場合、カーソルを実行しているセッションには、親カーソルの実行を担当したセッションとは異なるオプティマイザ設定があります。
では、子供に対してTOP_LEVEL_RPI_CURSORがYに設定されているとはどういう意味ですか?ドキュメントが明確ではありません。 MOSはこの問題についてほとんど何もしていません。そして、このコラムでの私のGoogleのヒットはすべて、ドキュメントを逆流させるだけです。理由を知るには、RPIがRecursiveProgramInterfaceの略であることを知っておくと役立ちます。これは、再帰SQLを処理するOracleカーネルの一部です。私たちの場合、SQLステートメントが異なる「深さ」で発行されたという事実を扱います。
再帰SQLとは何ですか?あなたに代わって発行されるのはSQLです。つまり、これから説明するように、別の深さで発行されます。まず、Oracleは常に再帰SQLを実行しています。基本的なレベルでは、「select * from table_name」を発行すると、Oracleはデータディクショナリにクエリを実行して、オブジェクトが存在し、そのテーブルに対する権限があることを確認します。オラクルはそれをどのように行っていますか?他のSQLステートメントを使用します。発行するステートメントは、基本レベルであるレベル0にあります。 OracleがSQLステートメントを発行して、テーブルが存在するかどうかを確認すると、次のレベルであるレベル1になります。場合によっては、他のSQLステートメントが次のレベルであるレベル2で発行されることがあります。
SQLステートメントの深さは、Oracleがユーザーに代わってバックグラウンドで実行していることだけに限定されません。ストアドプロシージャを実行するときを考慮してください。ストアドプロシージャの呼び出しは深さ0です。ストアドプロシージャのSQLステートメントは深さ1です。そのストアドプロシージャが別のプロシージャを呼び出す場合、他のプロシージャのSQLは深さ2になります。
再帰SQLとSQL深度に関するこの情報を使用して、Oracle12.1.0.2データベースに簡単な例を作成しました。まず、ストアドプロシージャを作成しました。
create or replace procedure my_sysdate as v_dt date; begin select sysdate into v_dt from dual; end; /からv_dtに選択し始めます。
次に、SQL * Plusセッションを起動し、トレースを開始しました。同じSQLステートメントを発行してから、プロシージャを呼び出しました。
SQL> alter session set sql_trace=true;
Session altered.
SQL> SELECT SYSDATE FROM DUAL 2 /
SYSDATE --------- 05-APR-16
SQL> exec my_sysdate;
PL/SQL procedure successfully completed.
SQL> exit
生のトレースファイルを調べたところ、DUALからSYSDATEへの2つの呼び出しが次のように見つかりました。
カーソルの解析#140670990815296 len =24 dep =0 uid =9449 oct =3 lid =9449 tim =24905125014484 hv =124468195 ad =’81477be0′ sqlid =’c749bc43qqfz3′ SELECT SYSDATE FROM DUAL
カーソルの解析#140670907623848 len =24 dep =1 uid =9449 oct =3 lid =9449 tim =24905129780963 hv =124468195 ad =’81477be0′ sqlid =’c749bc43qqfz3′ SELECT SYSDATE FROM DUAL
トレースファイルをよく見ると、depth=1の2番目のファイルはストアドプロシージャの直接の結果であることがわかります。ストアドプロシージャがすべて小文字で定義されていても、depth=1で発行されたSQLはすべて大文字であることに注意してください。その結果、SQL * Plusセッションで(depth =0で)同じSQLステートメントを直接発行した場合、同じSQL ID値を持つように、そのステートメントの同じ大文字を使用する必要がありました。
トレースファイルにはSQLIDも表示されます。これで、V $SQL_SHARED_CURSORにそのSQLID値を照会し、TOP_LEVEL_RPI_CURSORが子に設定されていることを示すことができます。
SQL> select sql_id,top_level_rpi_cursor from v$sql_shared_cursor where sql_id='c749bc43qqfz3';
SQL_ID T ------------- - c749bc43qqfz3 N c749bc43qqfz3 Y
だから私たちは私たちの証拠を持っています。これら2つのカーソルの唯一の違いは、1つは実行された深さであるということです。 Oracleが共有プールでこの区別を必要とする理由がわかりません。誰か知っているなら、私に連絡してください。
通常、いくつかの追加バージョン、特定のSQLIDのいくつかの子カーソルは気にしません。 SQLステートメントに多数のバージョンがある場合は、深度レベルが異なることが原因ではない可能性があります。他の理由は、SQLステートメントに多数の子カーソルと多数の異なるバージョンが含まれる理由により関連性があります。しかし、これはそのコラムが私たちに何を伝えているのかという質問に答えます。