Oracle
 sql >> Base de données >  >> RDS >> Oracle

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR

Je travaillais récemment avec une personne sur une question dans les forums MOSC où elle posait des questions sur la colonne TOP_LEVEL_RPI_CURSOR de la vue V$SQL_SHARED_CURSOR. Il y a peu de documentation sur ce que cette colonne essaie de dire au DBA.

Tout ce que disent les documents Oracle, c'est que cette colonne contient "(Y | N) est le curseur RPI de niveau supérieur". Alors qu'est-ce que cela signifie ?

Je vais supposer que le lecteur de cet article est familier avec les curseurs enfants. Cela me fera économiser une grande quantité d'informations d'introduction. La vue V$SQL_SHARED_CURSOR indiquera au DBA pourquoi un curseur enfant et son parent ont des versions différentes dans le pool partagé. Si la colonne OPTIMIZER_MISMATCH du curseur enfant contient un "Y" dans cette vue, cela signifie que la session exécutant le curseur avait des paramètres d'optimisation différents de ceux de la session responsable de l'exécution du curseur parent.

Alors qu'est-ce que cela signifie lorsque TOP_LEVEL_RPI_CURSOR est défini sur Y pour un enfant ? La documentation n'est pas claire. MOS a très peu sur le sujet. Et tous mes résultats Google sur cette colonne ne font que régurgiter la documentation. Pour savoir pourquoi, il est utile de savoir que RPI signifie Recursive Program Interface. Cela fait partie du noyau Oracle qui traite du SQL récursif. Dans notre cas, il s'agit du fait que l'instruction SQL a été émise à une "profondeur" différente.

Qu'est-ce que le SQL récursif ? C'est SQL qui est émis en votre nom, ce qui signifie à une profondeur différente comme je vais l'illustrer. Tout d'abord, Oracle exécute tout le temps du SQL récursif. Au niveau de base, lorsque vous émettez "select * from table_name", Oracle interroge le dictionnaire de données pour s'assurer que l'objet existe et que vous disposez des autorisations sur cette table. Comment Oracle fait-il cela ? Il utilise d'autres instructions SQL. L'instruction que vous émettez est au niveau 0, le niveau de base. Lorsqu'Oracle émet une instruction SQL pour vérifier si la table existe, ce sera au niveau suivant, le niveau 1. Parfois, cela entraînera l'émission d'autres instructions SQL au niveau suivant, le niveau 2.

La profondeur d'une instruction SQL ne se limite pas à ce qu'Oracle fait en arrière-plan, en votre nom. Tenez-en compte lorsque vous exécutez une procédure stockée. Votre appel à la procédure stockée est à la profondeur 0. Toute instruction SQL dans la procédure stockée est à la profondeur 1. Si cette procédure stockée appelle une autre procédure, le SQL de l'autre procédure sera à la profondeur 2.

J'ai utilisé ces informations sur le SQL récursif et la profondeur SQL pour construire un exemple simple dans ma base de données Oracle 12.1.0.2. Tout d'abord, j'ai créé une procédure stockée.

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

J'ai ensuite lancé une session SQL*Plus et lancé une trace. J'ai émis la même instruction SQL, puis j'ai appelé ma procédure.

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

Lorsque j'ai examiné le fichier de trace brut, j'ai trouvé les deux appels à SYSDATE de DUAL comme suit :

ANALYSE AU CURSEUR #140670990815296 len=24 dep=0 uid=9449 oct=3 lid=9449 tim=24905125014484 hv=124468195 ad='81477be0′ sqlid='c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

ANALYSE AU CURSEUR #140670907623848 len=24 dep=1 uid=9449 oct=3 lid=9449 tim=24905129780963 hv=124468195 ad='81477be0′ sqlid='c749bc43qqfz3′ SELECT SYSDATE FROM DUAL

Si vous regardez attentivement le fichier de trace, vous verrez que le second à profondeur =1 était un résultat direct de la procédure stockée. Notez que même si ma procédure stockée a été définie en minuscules, le SQL émis à profondeur =1 était en majuscules. Par conséquent, lorsque j'ai émis la même instruction SQL directement dans ma session SQL*Plus (à profondeur =0), j'ai dû utiliser la même forme majuscule de cette instruction afin qu'elle ait la même valeur d'ID SQL.

Le fichier de trace affiche également l'ID SQL. Je peux maintenant interroger V$SQL_SHARED_CURSOR pour cette valeur d'ID SQL et montrer que TOP_LEVEL_RPI_CURSOR est défini pour l'enfant.

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

Nous avons donc notre preuve. La seule différence entre ces deux curseurs est que l'un était la profondeur à partir de laquelle ils ont été exécutés. Je ne sais pas pourquoi Oracle a besoin de cette distinction dans le pool partagé. Si quelqu'un sait, envoyez-moi un message.

Normalement, nous ne nous soucions pas de quelques versions supplémentaires, de quelques curseurs enfants pour un ID SQL donné. Si votre instruction SQL a un grand nombre de versions, cela n'est probablement pas dû aux différents niveaux de profondeur. D'autres raisons seraient plus pertinentes pour expliquer pourquoi une instruction SQL aurait un nombre élevé de curseurs enfants, un nombre élevé de versions différentes. Mais cela répond à la question de savoir ce que cette colonne nous dit.