Oracle: difference between deterministic and result_cache

From the translator: I decided to start my journey to Habr not with an attempt to write some unique text from scratch, but with the translation of a relatively fresh (from 08/17/2020) article by the classic PL / SQL development Stephen Feuerstein, in which he discusses the difference in sufficient detail between the two main variants of the PL / SQL function result cache. I hope this translation will be helpful for many developers getting started with Oracle technologies.





Introduction

Sooner or later, any seasoned Oracle developer is asked a question like:





I don't understand what exactly is the difference between deterministic and result_cache. Do they have different use cases? I use deterministic in many functions that get data from lookup tables. Do I need to use the result_cache keyword instead of deterministic?





I thought it would be worth writing about the differences between these two possibilities. First of all, let's make sure we all have the same understanding of when a function is deterministic.





The Wikipedia provides the following definition of a deterministic algorithm:





A deterministic algorithm is an algorithm that returns the same set of outputs for the same set of inputs, while performing the same sequence of actions.





In other words, a deterministic subroutine (procedure or function) has no side effects. By passing a specific set of values ​​as input parameters, you will always get the same result at the output, regardless of when, where, or how often you call this subroutine.





A reasonable question is, what is a side effect of a PL / SQL function? At a minimum (the list is not exhaustive):





  • any (that is, any) DML operator





  • Using a variable declared outside of this function (that is, global, out-of-scope aka "global")





  • call any non-deterministic subroutine





, 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