Deterministic Functions, Caching, and Worries About Consistent Data

DZone 's Guide to

Deterministic Functions, Caching, and Worries About Consistent Data

Learn about The Rule of deterministic functions: Only add the DETERMINISTIC keyword to truly deterministic functions.

· Database Zone ·
Free Resource

A developer contacted me with the following questions last week:

We have created a function that returns a single row column value form a query. When we call this function with the same input values, it takes to long to return. Example: 

select max (det_function('A2')) from dual connect by rownum <= 1000000

But when we change the function to a deterministic function, the statement returns really fast. The only thing where we are unsure of is what happens when the tables have changed to what the statement of the function selects. Do we need a to commit this table to bring Oracle to re-execute the statement in the function and not use the cache, or what should we do to get a consistent return value? 

   v_ident   NUMBER;
     FROM my_table
    WHERE id = v_in_id;

   RETURN v_ident;

A function is deterministic if the value returned by the function is determined entirely by its input(s).

The following function, for example, is deterministic:

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

You can also quickly see, I hope, that any function that contains SQL (like the first function defined above) cannot possibly be deterministic: it depends on the contents of one or more tables to do its job, and those datasets are not passed as IN parameters.

Does that mean the compiler will complain? No! But it does mean that you could create real problems for yourself if you are not careful about your use of this keyword.

So the rule should be: Only add the DETERMINISTIC keyword to truly deterministic functions.

Why? Why should it matter? Because under certain circumstances (such as the one identified by the developer above), Oracle Database will not execute your function, but instead simply use a previously cached return value.

Within the scope of a single server call (i.e. execution of a PL/SQL block), Oracle Database will keep track of input and return values for your deterministic functions. If in that same server call, you pass the same input values to the function, the database engine may choose to not actually execute the function but instead simply pass back the previously-computed return value (for those same inputs).

That's why this developer saw such a great leap forward in performance.

Once that SELECT statement finishes, though, memory for the cache is released. When and if that same query is run again, the engine will start rebuilding and using that cache.

While that statement executing, though, no matter what sort of changes are made to the table, no matter if a commit is issued or not, those changes will not be visible to the statement that called the function.

That's why I will repeat The Rule again:

Only add the DETERMINISTIC keyword to truly deterministic functions.

If your function contains a SELECT statement and you want to call it from a SELECT statement, the best thing to do is take the SQL out of the function and "merge" it into your SQL - in other words, no user-defined functions. Just SQL.

Rob van Wijk offers lots more details on the behavior and performance of deterministic functions here. You will also be well-served to read Bryn Llewellyn's in-depth exploration of how to write a safe result-cached function.

Rather than repeat all those findings, I will simply conclude with:

  1. Use the DETERMINISTIC function primarily as a way to document to future developers that your function is currently free of side effects, and should stay that way.

  2. If you are looking for ways to improve the performance of functions executed inside SQL, learn more about the UDF pragma (new in Oracle Database 12c Release 1).

  3. See if the function result cache feature (also explored in Bryn's blog post) might be applicable to your situation.

  4. Do not call user-defined functions from SQL statements that in turn contain SQL statements (or at least do so with extreme caution). That SQL inside the function is not part of the same read-consistent image as the data set identified by the "outer" SQL.

database ,deterministic ,plsql ,oracle

Published at DZone with permission of Steven Feuerstein , DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}