sql >> Databasteknik >  >> RDS >> Oracle

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR

Jag arbetade med en person på en fråga i MOSC-forumen nyligen där de frågade om TOP_LEVEL_RPI_CURSOR-kolumnen i vyn V$SQL_SHARED_CURSOR. Det finns lite dokumentation om vad den här kolumnen försöker berätta för DBA.

Allt som Oracle-dokumenten säger är att den här kolumnen innehåller "(Y|N) Is top level RPI cursor". Så vad betyder det?

Jag kommer att anta att läsaren av det här inlägget är bekant med underordnade markörer. Det kommer att spara mig en stor mängd introduktionsinformation. V$SQL_SHARED_CURSOR-vyn kommer att berätta för DBA varför en underordnad markör och dess förälder har olika versioner i den delade poolen. Om den underordnade markörens OPTIMIZER_MISMATCH-kolumn innehåller ett "Y" i den här vyn, hade sessionen som kör markören andra optimeringsinställningar än den session som var ansvarig för den överordnade markörkörningen.

Så vad betyder det när TOP_LEVEL_RPI_CURSOR är inställd på Y för ett barn? Dokumentationen är inte tydlig. MOS har väldigt lite om ämnet. Och alla mina Google-träffar på den här kolumnen förgyller nästan bara dokumentationen. För att veta varför, hjälper det att veta att RPI står för Rekursivt programgränssnitt. Detta är en del av Oracle-kärnan som hanterar rekursiv SQL. I vårt fall handlar det om det faktum att SQL-satsen utfärdades på ett annat "djup".

Vad är rekursiv SQL? Det är SQL som utfärdas för din räkning, vilket betyder på ett annat djup som jag ska illustrera. För det första, Oracle utför rekursiv SQL hela tiden. På en grundläggande nivå, när du utfärdar "välj * från tabellnamn", frågar Oracle Data Dictionary för att säkerställa att objektet finns och att du har behörigheter för den tabellen. Hur gör Oracle det? Den använder andra SQL-satser. Påståendet du utfärdar är på nivå 0, basnivån. När Oracle utfärdar en SQL-sats för att kontrollera om tabellen finns, kommer det att vara på nästa nivå, nivå 1. Ibland kommer det att leda till att andra SQL-satser utfärdas på nästa nivå, nivå 2.

Djupet av en SQL-sats är inte begränsad till bara vad Oracle gör i bakgrunden, för din räkning. Tänk på när du kör en lagrad procedur. Ditt anrop till den lagrade proceduren är på djup 0. Alla SQL-satser i den lagrade proceduren är på djup 1. Om den lagrade proceduren anropar en annan procedur, kommer SQL i den andra proceduren att vara på djup 2.

Jag använde denna information om rekursiv SQL och SQL-djup för att konstruera ett enkelt exempel i min Oracle 12.1.0.2-databas. Först skapade jag en lagrad procedur.

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

Jag startade sedan upp en SQL*Plus-session och startade en spårning. Jag utfärdade samma SQL-sats och sedan anropade jag min procedur.

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

När jag undersökte den råa spårningsfilen hittade jag de två anropen till SYSDATE från DUAL enligt följande:

PARSERING I MARKör #140670990815296 len=24 dep=0 uid=9449 oct=3 lid=9449 tim=24905125014484 hv=124468195 ad=’81477be0′ sqlid=9449 oct=3DATUM SqlidbDUc4c4c3DATUM SqlidbDUc4c4c3DATUM SqlidbVz3c4c3P

PARSERING I MARKÖR #140670907623848 len=24 dep=1 uid=9449 oct=3 lid=9449 tim=24905129780963 hv=124468195 ad=’81477be0′ sqlidbDUc4c3DATUM sqlidbDUc4c4c3DATUM SqlidbDUc4c4c3DATUM FROM

Om du tittar på spårningsfilen noga, kommer du att se att den andra på djup=1 var ett direkt resultat av den lagrade proceduren. Observera att även om min lagrade procedur definierades med små bokstäver, så var SQL-koden som utfärdades på depth=1 i alla versaler. Som ett resultat av detta, när jag utfärdade samma SQL-sats direkt i min SQL*Plus-session (vid depth=0), var jag tvungen att använda samma versaler som den satsen så att den skulle ha samma SQL ID-värde.

Spårningsfilen visar också SQL ID. Jag kan nu fråga V$SQL_SHARED_CURSOR för det SQL ID-värdet och visa att TOP_LEVEL_RPI_CURSOR är inställt för barnet.

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

Så där har vi vårt bevis. Den enda skillnaden mellan dessa två markörer är att den ena var djupet från vilket de utfördes. Jag är inte säker på varför Oracle behöver denna distinktion i den delade poolen. Om någon vet, skriv till mig.

Normalt bryr vi oss inte om några extra versioner, några underordnade markörer för ett givet SQL ID. Om din SQL-sats har ett stort antal versioner, beror det förmodligen inte på de olika djupnivåerna. Andra skäl skulle vara mer relevanta för varför en SQL-sats skulle ha ett stort antal underordnade markörer, ett stort antal olika versioner. Men detta svarar på frågan om vad den kolumnen säger oss.


  1. Hur man lägger till linjenummer i SQL Server Management Studio ( SSMS) - SQL Server / TSQL självstudie del 11

  2. Hur skriver man ut VARCHAR(MAX) med Print Statement?

  3. Hur djupkopierar jag en uppsättning data och ändrar FK-referenser till att peka på alla kopior?

  4. Oracle infoga från välj i tabell med fler kolumner