Oracle
 sql >> Database >  >> RDS >> Oracle

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR

Recentemente stavo lavorando con un individuo su una domanda nei forum MOSC in cui hanno chiesto informazioni sulla colonna TOP_LEVEL_RPI_CURSOR della vista V$SQL_SHARED_CURSOR. C'è poca documentazione su ciò che questa colonna sta cercando di dire al DBA.

Tutto ciò che dicono i documenti Oracle è che questa colonna contiene "(Y|N) Is cursore RPI di livello superiore". Allora cosa significa?

Presumo che il lettore di questo post abbia familiarità con i cursori figlio. Ciò mi farà risparmiare una grande quantità di informazioni introduttive. La vista V$SQL_SHARED_CURSOR indicherà al DBA perché un cursore figlio e il relativo genitore hanno versioni diverse nel pool condiviso. Se la colonna OPTIMIZER_MISMATCH del cursore figlio contiene una "Y" in questa vista, la sessione che esegue il cursore aveva impostazioni di ottimizzazione diverse rispetto alla sessione responsabile dell'esecuzione del cursore padre.

Quindi cosa significa quando TOP_LEVEL_RPI_CURSOR è impostato su Y per un bambino? La documentazione non è chiara. MOS ha ben poco sull'argomento. E tutti i miei risultati di Google su questa colonna praticamente rigurgitano la documentazione. Per sapere perché, è utile sapere che RPI sta per Recursive Program Interface. Questo fa parte del kernel Oracle che si occupa di SQL ricorsivo. Nel nostro caso, si tratta del fatto che l'istruzione SQL è stata emessa a una "profondità" diversa.

Che cos'è l'SQL ricorsivo? È SQL che viene emesso per tuo conto, il che significa a una profondità diversa, come illustrerò. Prima di tutto, Oracle esegue sempre SQL ricorsivo. A livello di base, quando si emette "select * from table_name", Oracle interroga il dizionario dei dati per assicurarsi che l'oggetto esista e che si disponga delle autorizzazioni su quella tabella. Come fa Oracle a farlo? Utilizza altre istruzioni SQL. La dichiarazione che emetti è al livello 0, il livello base. Quando Oracle emette un'istruzione SQL per verificare se la tabella esiste, questa sarà al livello successivo, livello 1. A volte, ciò causerà l'emissione di altre istruzioni SQL al livello successivo, livello 2.

La profondità di un'istruzione SQL non si limita solo a ciò che Oracle sta facendo in background, per tuo conto. Considera quando esegui una stored procedure. La tua chiamata alla procedura memorizzata è alla profondità 0. Qualsiasi istruzione SQL nella procedura memorizzata è alla profondità 1. Se quella procedura memorizzata chiama un'altra procedura, l'SQL nell'altra procedura sarà alla profondità 2.

Ho usato queste informazioni su SQL ricorsivo e sulla profondità SQL per costruire un semplice esempio nel mio database Oracle 12.1.0.2. Innanzitutto, ho creato una procedura memorizzata.

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

Ho quindi avviato una sessione SQL*Plus e avviato una traccia. Ho emesso la stessa istruzione SQL e poi ho chiamato la mia procedura.

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

Quando ho esaminato il file di traccia non elaborato, ho trovato le due chiamate a SYSDATE da DUAL come segue:

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

Se osservi il file di traccia da vicino, vedrai che il secondo a depth=1 era un risultato diretto della procedura memorizzata. Si noti che anche se la mia procedura memorizzata è stata definita in lettere minuscole, l'SQL emesso a depth=1 era in lettere maiuscole. Di conseguenza, quando ho emesso la stessa istruzione SQL direttamente nella mia sessione SQL*Plus (a profondità =0), ho dovuto utilizzare la stessa forma maiuscola di tale istruzione in modo che avesse lo stesso valore ID SQL.

Il file di traccia mostra anche l'ID SQL. Ora posso interrogare V$SQL_SHARED_CURSOR per quel valore ID SQL e mostrare che TOP_LEVEL_RPI_CURSOR è impostato per il bambino.

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

Quindi ecco la nostra prova. L'unica differenza tra questi due cursori è che uno era la profondità da cui venivano eseguiti. Non sono sicuro del motivo per cui Oracle abbia bisogno di questa distinzione nel pool condiviso. Se qualcuno lo sa, mi mandi un messaggio.

Normalmente, non ci interessano alcune versioni extra, alcuni cursori figlio per un determinato ID SQL. Se la tua istruzione SQL ha un numero elevato di versioni, probabilmente non è dovuto ai diversi livelli di profondità. Altri motivi sarebbero più rilevanti per il motivo per cui un'istruzione SQL avrebbe un numero elevato di cursori figlio, un numero elevato di versioni diverse. Ma questo risponde alla domanda su cosa ci dice quella colonna.