Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

V$SQL_SHARED_CURSOR TOP_LEVEL_RPI_CURSOR


Eu estava trabalhando com um indivíduo em uma pergunta nos fóruns do MOSC recentemente, onde eles perguntaram sobre a coluna TOP_LEVEL_RPI_CURSOR da visualização V$SQL_SHARED_CURSOR. Há pouca documentação sobre o que esta coluna está tentando dizer ao DBA.

Todos os documentos da Oracle dizem que esta coluna contém “(Y|N) Is top level RPI cursor”. Então, o que isso significa?

Vou assumir que o leitor deste post está familiarizado com cursores filhos. Isso vai me poupar uma grande quantidade de informações introdutórias. A visualização V$SQL_SHARED_CURSOR informará ao DBA por que um cursor filho e seu pai têm versões diferentes no pool compartilhado. Se a coluna OPTIMIZER_MISMATCH do cursor filho contiver um 'Y' nesta exibição, a sessão que está executando o cursor terá configurações de otimizador diferentes da sessão responsável pela execução do cursor pai.

Então, o que significa quando TOP_LEVEL_RPI_CURSOR é definido como Y para um filho? A documentação não é clara. MOS tem muito pouco sobre o assunto. E todos os meus acessos do Google nesta coluna apenas regurgitam a documentação. Para saber o porquê, ajuda saber que RPI significa Recursive Program Interface. Isso faz parte do kernel do Oracle que lida com SQL recursivo. No nosso caso, trata-se do fato de que a instrução SQL foi emitida em uma “profundidade” diferente.

O que é SQL recursivo? É o SQL que é emitido em seu nome, o que significa uma profundidade diferente, como ilustrarei. Primeiro, a Oracle está executando SQL recursiva o tempo todo. Em um nível básico, quando você emite “select * from table_name”, o Oracle consulta o Dicionário de Dados para garantir que o objeto exista e que você tenha permissões nessa tabela. Como a Oracle faz isso? Ele usa outras instruções SQL. A declaração que você emite está no nível 0, o nível base. Quando o Oracle emite uma instrução SQL para verificar se a tabela existe, ela estará no próximo nível, nível 1. Às vezes, isso fará com que outras instruções SQL sejam emitidas no próximo nível, nível 2.

A profundidade de uma instrução SQL não se limita apenas ao que a Oracle está fazendo em segundo plano, em seu nome. Considere quando você executa um procedimento armazenado. Sua chamada para o procedimento armazenado está na profundidade 0. Qualquer instrução SQL no procedimento armazenado está na profundidade 1. Se esse procedimento armazenado chamar outro procedimento, o SQL no outro procedimento estará na profundidade 2.

Usei essas informações sobre SQL recursiva e profundidade de SQL para construir um exemplo simples em meu banco de dados Oracle 12.1.0.2. Primeiro, criei um procedimento armazenado.
create or replace procedure my_sysdate 
as 
 v_dt date;
begin
 select sysdate into v_dt from dual;
end;
/

Em seguida, iniciei uma sessão do SQL*Plus e iniciei um rastreamento. Eu emiti a mesma instrução SQL e então chamei meu procedimento.


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 examinei o arquivo de rastreamento bruto, encontrei as duas chamadas para SYSDATE do DUAL da seguinte forma:



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

ANALISANDO NO 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 você observar atentamente o arquivo de rastreamento, verá que o segundo em profundidade=1 foi um resultado direto do procedimento armazenado. Observe que, embora meu procedimento armazenado tenha sido definido em letras minúsculas, o SQL emitido em depth=1 estava em letras maiúsculas. Como resultado, quando emiti a mesma instrução SQL diretamente em minha sessão SQL*Plus (em profundidade=0), tive que usar a mesma forma maiúscula dessa instrução para que ela tivesse o mesmo valor de ID SQL.

O arquivo de rastreamento também mostra o ID SQL. Agora posso consultar V$SQL_SHARED_CURSOR para esse valor de ID SQL e mostrar que TOP_LEVEL_RPI_CURSOR está definido para o filho.
SQL> select sql_id,top_level_rpi_cursor from v$sql_shared_cursor where sql_id='c749bc43qqfz3';
SQL_ID T
------------- -
c749bc43qqfz3 N
c749bc43qqfz3 Y

Então aí temos nossa prova. A única diferença entre esses dois cursores é que um deles era a profundidade a partir da qual eles foram executados. Não sei por que a Oracle precisa dessa distinção no Shared Pool. Se alguém souber, me dê um toque.

Normalmente, não nos importamos com algumas versões extras, alguns cursores filhos para um determinado SQL ID. Se sua instrução SQL tiver um número alto de versões, provavelmente não é devido aos diferentes níveis de profundidade. Outros motivos seriam mais relevantes para o motivo pelo qual uma instrução SQL teria um número alto de cursores filho, um número alto de versões diferentes. Mas isso responde à pergunta sobre o que essa coluna está nos dizendo.