Oracle: diferença entre determinístico e result_cache

Do tradutor: Decidi começar minha jornada para Habr não com uma tentativa de escrever algum texto exclusivo do zero, mas com a tradução de um artigo relativamente novo (de 17/08/2020) do clássico desenvolvimento PL / SQL Stephen Feuerstein , no qual ele discute a diferença em detalhes suficientes entre as duas variantes principais do cache de resultados de função PL / SQL. Espero que esta tradução seja útil para muitos desenvolvedores que estão começando com as tecnologias Oracle.





Introdução

Cedo ou tarde, qualquer desenvolvedor Oracle experiente recebe uma pergunta como:





Eu não entendo qual é exatamente a diferença entre determinístico e result_cache. Eles têm casos de uso diferentes? Eu uso determinística em muitas funções que obtêm dados de tabelas de pesquisa. Preciso usar a palavra-chave result_cache em vez de determinística?





Achei que valeria a pena escrever sobre as diferenças entre essas duas possibilidades. Primeiro, vamos ter certeza de que todos nós temos o mesmo entendimento de quando uma função é determinística.





A Wikipedia fornece a seguinte definição de algoritmo determinístico:





Um algoritmo determinístico é um algoritmo que retorna o mesmo conjunto de saídas para o mesmo conjunto de entradas, enquanto executa a mesma sequência de ações.





Em outras palavras, uma sub-rotina determinística (procedimento ou função) não tem efeitos colaterais. Ao passar um conjunto específico de valores como parâmetros de entrada, você sempre obterá o mesmo resultado na saída, independentemente de quando, onde ou com que freqüência você chama esta sub-rotina.





Uma pergunta razoável é: qual é o efeito colateral de uma função PL / SQL? No mínimo (a lista não é exaustiva):





  • qualquer (ou seja, qualquer) operador DML





  • Usando uma variável declarada fora desta função (ou seja, global, fora do escopo, também conhecido como "global")





  • chame qualquer sub-rotina não determinística





, deterministic result_cache , . . ( result_cache), , , .





FUNCTION betwnstr (
   string_in   IN   VARCHAR2
 , start_in    IN   INTEGER
 , end_in      IN   INTEGER
)
   RETURN VARCHAR2 DETERMINISTIC 
IS
BEGIN
   RETURN (SUBSTR (string_in, start_in, end_in - start_in + 1));
END;
      
      



- substr



, , . , , .





, Oracle Database , DETERMINISTIC



( ).





?





  • ,





  • ( )





, :





CREATE OR REPLACE FUNCTION pass_number (i NUMBER)
   RETURN NUMBER
   DETERMINISTIC
IS
BEGIN
   DBMS_OUTPUT.put_line ('pass_number executed');
   RETURN 0;
END;
/

DECLARE
   n   NUMBER := 0;
BEGIN
   FOR rec IN (SELECT pass_number (1)
                 FROM all_objects
                WHERE ROWNUM < 6)
   LOOP
      n := n + 1;
   END LOOP;

   DBMS_OUTPUT.put_line (n + 1);
END;
/

pass_number executed
6
      
      



, , 5 , . Oracle Database , ( PL/SQL SQL-, ).





.





, result_cache

betwnstr



, result_cache:





FUNCTION betwnstr (
   string_in   IN   VARCHAR2
 , start_in    IN   INTEGER
 , end_in      IN   INTEGER
)
   RETURN VARCHAR2 
   RESULT_CACHE
IS
BEGIN
   RETURN (SUBSTR (string_in, start_in, end_in - start_in + 1));
END;
      
      



- RESULT_CACHE



. , DETERMINISTIC



, . , result_cache.





result_cache? :





  • Oracle Database, SGA (Shared Global Area)





  • , ,





  • ( "" )





  • ( Oracle - , references) , commit





, . RESULT_CACHE



- "" DETERMINISTIC



( , ) . RESULT_CACHE



, . RESULT_CACHE



Oracle Live SQL.





, , RESULT_CACHE



:





CREATE OR REPLACE FUNCTION pass_number (i NUMBER)
   RETURN NUMBER
   RESULT_CACHE
IS
BEGIN
   DBMS_OUTPUT.put_line ('pass_number executed for ' || i);
   RETURN 0;
END;
/

DECLARE
   n   NUMBER := 0;
BEGIN
   FOR rec IN (SELECT pass_number (100)
                 FROM all_objects
                WHERE ROWNUM &lt; 6)
   LOOP
      n := n + 1;
   END LOOP;

   DBMS_OUTPUT.put_line ('All done ' || TO_CHAR (n + 1));
END;
/

pass_number executed for 100
All done 6


BEGIN
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (100));
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (200));
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (300));
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (100));
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (200));
   DBMS_OUTPUT.PUT_LINE ('Returned ' || pass_number (300));
END;
/

Returned 0
pass_number executed for 200
Returned 0
pass_number executed for 300
Returned 0
Returned 0
Returned 0
Returned 0
      
      



100 ( ), , , .





200 300 - , .





! ( ) PL/SQL , :





All done 6
Returned 0
Returned 0
Returned 0
Returned 0
Returned 0
Returned 0
      
      



, RESULT_CACHE



, , . , - - .





: , result_cache, , .





deterministic result_cache?

DETERMINISTIC



RESULT_CACHE



.





?

, , DETERMINISTIC



, ( ) ( SQL-, ). , , .





, , , RESULT_CACHE



, (instance) , ( , ) . , .





?

: DETERMINISTIC



, .





PL/SQL SQL, , (, ).





, . , , .





DETERMINISTIC



, . Oracle , , .





, result_cache?

. RESULT_CACHE



. DBA, , . , SGA , (latch contention).





, result_cache. :





  • ?





  • , ? ,





  • , , , ? , ,





  • - , NLS? , , , , TO_CHAR



      .





: RESULT_CACHE



, , , .








All Articles