Escolar Documentos
Profissional Documentos
Cultura Documentos
Patrick Wolf
Inside Oracle APEX a blog that helps to get more
out of Oracle Application Express (APEX) for your
daily development work!
Search
Search
Main menu
Skip to primary content
Home
Overview
About
Post navigation
Previous Next
WHY?
Because the function is probably called more often than you think it is! If you dont want to
read the hole article, scroll down and check the APEX impact.
AN EXAMPLE
And now look at the following SQL Statement where we call our new function with a
constant value.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = getValue(1)
;
How often to you think it is called? You have the same choice as before.
Check the DBMS_Output.
Its just called one time! What is the difference? In our second example the optimizer is
using the EMP_EMP_ID_PK index and in that case as Tom Kyte explained me
The optimizer gets the start/stop range (the function might be called twice
actually) and then it range scans with the constants.
Keep in mind the performance issue when you have a function which is selecting against
other tables and you use such a function in a where-clause, where 1.000s of records are
processed!
POSSIBLE SOLUTIONS?
You can change the query in the following way. The optimizer then knows that is ok when
he executes the query just one time. So called scalar subquery caching, which works with
all DB versions. Checkout AskTom about that term.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = (SELECT getValue(1) FROM DUAL)
;
Or you take a look at the DETERMINISTIC clause which can specified when creating a
function or a package functions. What does it do? Its a hint for the optimizer to indicate that
the function returns the same result value whenever it is called with the same values for its
arguments. But, as noted by Tom Kyte
10gr2 supports deterministic as an optimization in SQL for the first time.
Prior to 10gr2 deterministic was all about function based indexes only
the SQL engine ignored it.
So only if you have a 10.2.x database, using DETERMINISTIC will give you a speed up of
your query. Use the above solution instead.
But lets change our function and see what we get now.
CREATE OR REPLACE FUNCTION getValue
( pValue IN NUMBER
)
RETURN NUMBER DETERMINISTIC
IS
BEGIN
DBMS_Output.put_line
( 'called getValue with '||pValue||' at '||
TO_CHAR(SYSDATE, 'HH24:MI:SS')
);
RETURN pValue;
END getValue;
Run the first query again and you will see that the function is called just once!
Try the following SQL statement.
SELECT COUNT(*)
FROM EMPLOYEES
WHERE SALARY = getValue(SALARY)
;
How often do you think it is called? Its just called as often as there are different salaries in
the table. With the old version of the function is called for each row again.
I know that the Oracle documentation about DETERMINISTIC says
Do not specify this clause to define a function that uses package variables or
that accesses the database in any way that might affect the return result of
the function.
Which I think is basically to see in relation to the function based index for which this hint
has been introduced. From my observation, if you have such a function call in several SQL
statements which are called after each other (eg in a anonymous pl/sql block), the function
is executed again for each SQL statement. Its just a hint for the optimizer during execution
of the current statement.
DONT USE DETERMINISTIC if your function is changing some global variables (eg
increase a counter) or doing DML and you expect that the function is called for each row!
Are you using the V or NV function in your SQL statements? In APEX 2.0 the V function
isnt wrapped (in 2.2 it is) and I dont see that the DETERMINISTIC is used in the code
Its just memory processing they do in there, but if you call it for 1.000s of records
Always use bind variables instead! Only use the V function in your packages, but never
use them in your report SQL statements.
I have done a posting on OTN about speeding up the V function. Stay tuned.
UPDATE: See my posting Drop in replacement for V and NV function which contains a
wrapper for the existing functions.
RELATED POSTS
This entry was posted in Caution, Performance, SQL by Patrick Wolf. Bookmark the
permalink.
1.
2.
would assume that the SYS_CONTEXT is defined deterministic and just called once by the
optimizer/query engine.
3.
In second example the f() function calls every time in RANGE SCAN with index for query.
As I said trivial.
4.
5.
6.
WBR, Yuri
7.
8.