Professional Documents
Culture Documents
Functions
It is common for any programming languages to abstract similar contents/code blocks into reusable functions, to make applications easy to maintain. Functions are also used extensively in Oracle, for example, built in functions like to_date, substr, etc. Some Oracle functions are deterministic: the same inputs always result in the same output. Some Oracle functions may depend on other factors, for example, a random number generator, or a table with content constantly updated. The results from a deterministic function will be cached, but the results from a non-deterministic function will not be cached, meaning Oracle has to evaluate the function every time it is used. A not well-written function in a large query could have significant performance impact.
Example
hlpat: hotlist-sp1.corp.sp1.yahoo.com SQL_ID: 4mjnbvjjsjy61
select SPACEID, get_apt_attrs_as_varchar2_q(spaceid) as APT_ATTR_STR from yan_resolved_class_node_query
function get_apt_attrs_as_varchar2_q (p_spaceid in number) return varchar2 IS l_data varchar2(32767); BEGIN select apt_attr_str into l_data from yan_resolved_class_node_query where spaceid = p_spaceid; return substr (l_data, 1, 32767); END get_apt_attrs_as_varchar2_q;
SQL Stats
4 executions, started at 2012-11-01 13:15:52, ended at 2012-11-05 09:04:23. Three aborted, one succeeded. Elapsed time: 325,260 seconds. CPU time: 317,488 seconds. IO Wait Time: 160,440 seconds. DISK_READS (PIO): 3,449,182,357 blocks. BUFFER_GETS (LIO): 3,534,546,432 blocks Rows: 493,657
1. A very simple plan. FTS to read every block and row. 2. Dynamic sampling level 2 is used, since the table has no statistics. 3. Since no additional predicate, so the Rows in the plan should be the accurate estimate of the table row count: 521K (note the query SQL stats returned 493,657 rows). 4. The table size is 50,897 blocks as of 2012-11-02, found from v$session_longops, not statistics. dba_segments can be used for estimation.
The SQL_ID of the recursive SQL related to the function is visible from v$session. V$sql_monitor for the given session has a huge number of entries for this recursive SQL based on the SID of the main query and it is hard to find the main query v$sql_monitor info because of the long list.
The Alternatives
Without rewriting the main query: add index on column spaceid to reduce IO (PIO and LIO) for the function. Rewriting the main query by using join (a lot of function usages can be eliminated using join). In some cases, if the function input has few distinct values (say less than subquery cache slot size), replace the function with a subquery.