Oracle
 sql >> Datenbank >  >> RDS >> Oracle

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR

Ich habe kürzlich mit einer Person in den MOSC-Foren an einer Frage gearbeitet, in der nach der TOP_LEVEL_RPI_CURSOR-Spalte der V$SQL_SHARED_CURSOR-Ansicht gefragt wurde. Es gibt wenig Dokumentation darüber, was diese Kolumne dem DBA mitzuteilen versucht.

Alles, was die Oracle-Dokumente sagen, ist, dass diese Spalte „(Y|N) Is Top-Level-RPI-Cursor“ enthält. Was bedeutet das also?

Ich gehe davon aus, dass der Leser dieses Beitrags mit untergeordneten Cursorn vertraut ist. Das erspart mir eine Menge an einleitenden Informationen. Die Ansicht V$SQL_SHARED_CURSOR teilt dem DBA mit, warum ein untergeordneter Cursor und sein übergeordneter Cursor unterschiedliche Versionen im gemeinsam genutzten Pool haben. Wenn die OPTIMIZER_MISMATCH-Spalte des untergeordneten Cursors in dieser Ansicht ein „Y“ enthält, hatte die Sitzung, in der der Cursor ausgeführt wurde, andere Optimierungseinstellungen als die Sitzung, die für die Ausführung des übergeordneten Cursors verantwortlich war.

Was bedeutet es also, wenn TOP_LEVEL_RPI_CURSOR für ein Kind auf Y gesetzt ist? Die Dokumentation ist nicht eindeutig. MOS hat sehr wenig zu diesem Thema. Und alle meine Google-Treffer in dieser Kolumne geben so ziemlich nur die Dokumentation wieder. Um zu wissen, warum, ist es hilfreich zu wissen, dass RPI für Recursive Program Interface steht. Dies ist Teil des Oracle-Kernels, der sich mit rekursivem SQL befasst. In unserem Fall geht es darum, dass das SQL-Statement in einer anderen „Tiefe“ abgesetzt wurde.

Was ist rekursives SQL? Es ist SQL, das in Ihrem Namen ausgegeben wird, was bedeutet, dass es sich um eine andere Tiefe handelt, wie ich veranschaulichen werde. Zunächst einmal führt Oracle ständig rekursives SQL aus. Wenn Sie „select * from table_name“ eingeben, fragt Oracle auf einer grundlegenden Ebene das Data Dictionary ab, um sicherzustellen, dass das Objekt vorhanden ist und dass Sie Berechtigungen für diese Tabelle haben. Wie macht Oracle das? Es verwendet andere SQL-Anweisungen. Die Anweisung, die Sie ausgeben, befindet sich auf Ebene 0, der Basisebene. Wenn Oracle eine SQL-Anweisung ausgibt, um zu prüfen, ob die Tabelle existiert, befindet sich dies auf der nächsten Ebene, Ebene 1. Manchmal führt dies dazu, dass andere SQL-Anweisungen auf der nächsten Ebene, Ebene 2, ausgegeben werden.

Die Tiefe einer SQL-Anweisung ist nicht darauf beschränkt, was Oracle für Sie im Hintergrund tut. Überlegen Sie, wann Sie eine gespeicherte Prozedur ausführen. Ihr Aufruf der gespeicherten Prozedur befindet sich auf Tiefe 0. Alle SQL-Anweisungen in der gespeicherten Prozedur befinden sich auf Tiefe 1. Wenn diese gespeicherte Prozedur eine andere Prozedur aufruft, befindet sich die SQL in der anderen Prozedur auf Tiefe 2.

Ich habe diese Informationen zu rekursivem SQL und SQL-Tiefe verwendet, um ein einfaches Beispiel in meiner Oracle 12.1.0.2-Datenbank zu erstellen. Zuerst habe ich eine gespeicherte Prozedur erstellt.

create or replace procedure my_sysdate 
as 
 v_dt date;
begin
 select sysdate into v_dt from dual;
end;
/

Ich habe dann eine SQL*Plus-Sitzung gestartet und eine Ablaufverfolgung gestartet. Ich habe dieselbe SQL-Anweisung ausgegeben und dann meine Prozedur aufgerufen.

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

Als ich die rohe Ablaufverfolgungsdatei untersuchte, fand ich die beiden Aufrufe von SYSDATE von DUAL wie folgt:

PARSING IN CURSOR #140670990815296 len=24 dep=0 uid=9449 oct=3 lid=9449 tim=24905125014484 hv=124468195 ad=’81477be0′ sqlid=’c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

PARSING IN CURSOR #140670907623848 len=24 dep=1 uid=9449 oct=3 lid=9449 tim=24905129780963 hv=124468195 ad=’81477be0′ sqlid=’c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

Wenn Sie sich die Ablaufverfolgungsdatei genau ansehen, werden Sie feststellen, dass die zweite bei der Tiefe =1 ein direktes Ergebnis der gespeicherten Prozedur war. Beachten Sie, dass, obwohl meine gespeicherte Prozedur ausschließlich in Kleinbuchstaben definiert wurde, die bei der Tiefe =1 ausgegebene SQL ausschließlich in Großbuchstaben war. Als ich dieselbe SQL-Anweisung direkt in meiner SQL*Plus-Sitzung (bei Tiefe =0) abgesetzt habe, musste ich daher dieselbe Großbuchstabenform dieser Anweisung verwenden, damit sie denselben SQL-ID-Wert hatte.

Die Trace-Datei zeigt auch die SQL-ID. Ich kann jetzt V$SQL_SHARED_CURSOR nach diesem SQL-ID-Wert abfragen und zeigen, dass TOP_LEVEL_RPI_CURSOR für das untergeordnete Element festgelegt ist.

SQL> select sql_id,top_level_rpi_cursor from v$sql_shared_cursor where sql_id='c749bc43qqfz3';
SQL_ID T
------------- -
c749bc43qqfz3 N
c749bc43qqfz3 Y

Da haben wir also unseren Beweis. Der einzige Unterschied zwischen diesen beiden Cursorn besteht darin, dass einer die Tiefe war, aus der sie ausgeführt wurden. Ich bin mir nicht sicher, warum Oracle diese Unterscheidung im Shared Pool benötigt. Wenn es jemand weiß, schreibt mir.

Normalerweise kümmern wir uns nicht um ein paar zusätzliche Versionen, ein paar untergeordnete Cursor für eine bestimmte SQL-ID. Wenn Ihre SQL-Anweisung eine hohe Anzahl von Versionen hat, dann liegt es wahrscheinlich nicht an den unterschiedlichen Tiefenstufen. Andere Gründe wären relevanter dafür, warum eine SQL-Anweisung eine große Anzahl von untergeordneten Cursorn und eine große Anzahl unterschiedlicher Versionen haben würde. Aber das beantwortet die Frage, was uns diese Kolumne sagt.