Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Usenet -> c.d.o.misc -> Re: performance question with function returning object type

Re: performance question with function returning object type

From: A Billington <billiauk_at_yahoo.co.uk>
Date: 17 Dec 2004 06:21:47 -0800
Message-ID: <1103293307.852484.239450@z14g2000cwz.googlegroups.com>


This is a really interesting problem. At first I thought this was to do with query merging, but after some tests I can only surmise that I haven't a clue what is going on ;o)

I added a little "execution counter" to the ALLAN_PKG and tried various iterations of the SQL statement to see the effects. The general rule is that there are no rules about how many times a function will be executed in a SQL statement ! As a set-based language, who knows what might be happening under the covers ? Anyway, my examples ( using 9.2.0.5.0 on Solaris ):-

9i> select allan_pkg.get_utilization
2 from dual
3 /

GET_UTILIZATION(PCT_UTIL, MORN_AVAIL, AFTN_AVAIL, EVE_AVAIL)



RES_UTIL_TYP(8148, 8148, 8148, 8148) 1 row selected.

9i> exec allan_pkg.report;
Function executed 1 time(s).

PL/SQL procedure successfully completed.

>> OK. So we see above our starting position. 1 execution returning the
object. Consistent with your OP.

9i>

9i> select ru.u.pct_util
2  ,      ru.u.morn_avail
3  ,      ru.u.aftn_avail
4  ,      ru.u.eve_avail
5  from  (
6         select allan_pkg.get_utilization u
7         from dual
8        ) ru

9 /

U.PCT_UTIL U.MORN_AVAIL U.AFTN_AVAIL U.EVE_AVAIL ---------- ------------ ------------ ----------- 8148 8148 8148 8148

1 row selected.

9i> exec allan_pkg.report
Function executed 4 time(s).

PL/SQL procedure successfully completed.

>> Just to prove to myself that there are 4 executions on my database
as you demonstrated in your OP. So I thought this must be to do with query merging by the CBO, such that it would end up running something along the following lines :-

SELECT allan_pkg.get_utilization.pct_util
,      allan_pkg.get_utilization.morn_avail
,      allan_pkg.get_utilization.aftn_avail
,      allan_pkg.get_utilization.eve_avail
FROM dual;

So to test this, I made sure the query could not be MERGED by adding the /*+ NO_MERGE */ hint into the in-line view. If my above hypothesis were correct, then we'd (hopefully) be back down to 1 function call.

9i>

9i> select ru.u.pct_util
2  ,      ru.u.morn_avail
3  ,      ru.u.aftn_avail
4  ,      ru.u.eve_avail
5  from  (
6         select /*+ no_merge */ allan_pkg.get_utilization u
7         from   dual
8        ) ru

9 /

U.PCT_UTIL U.MORN_AVAIL U.AFTN_AVAIL U.EVE_AVAIL ---------- ------------ ------------ ----------- 8148 8148 8148 8148

1 row selected.

9i> exec allan_pkg.report
Function executed 3 time(s).

PL/SQL procedure successfully completed.

>> NO! Now down to 3 executions. So that means that the first query DID
merge. I conclude this because by explicitly not merging, we got fewer function calls. To test whether the 4 function calls for 4 type attributes was circumstantial or not, I added 4 more elements to the object type ( making 8 ) and ran the merged and unmerged queries again. The merged query gave 8 executions and the merged query gave 3.

So, I continued with the original setup by trying some variations on a theme...

9i>
9i> with subq as (

2     select allan_pkg.get_utilization u
3     from   dual
4     )
5  select ru.u.pct_util
6  ,      ru.u.morn_avail
7  ,      ru.u.aftn_avail
8  ,      ru.u.eve_avail

9 from subq ru
10 /

U.PCT_UTIL U.MORN_AVAIL U.AFTN_AVAIL U.EVE_AVAIL ---------- ------------ ------------ ----------- 8148 8148 8148 8148

1 row selected.

9i> exec allan_pkg.report
Function executed 4 time(s).

PL/SQL procedure successfully completed.

>> Nothing unexpected there. What about if we force a temp table
transformation by forcing a no merge ( using the MATERIALIZE hint gave me a nasty ORA-0600 so I used an alternative ) ?

9i>
9i> with subq as (

2     select /*+ no_merge */
3            allan_pkg.get_utilization u
4     from   dual
5     )
6  select ru.u.pct_util
7  ,      ru.u.morn_avail
8  ,      ru.u.aftn_avail
9  ,      ru.u.eve_avail

10 from subq ru
11 /

U.PCT_UTIL U.MORN_AVAIL U.AFTN_AVAIL U.EVE_AVAIL ---------- ------------ ------------ ----------- 8148 8148 8148 8148

1 row selected.

9i> exec allan_pkg.report
Function executed 3 time(s).

>> Back to 3 executions, which I think is as low as you'll get this
without using a method such as the nested table method in the previous post.

So that's as far as I managed to get. Where's Jonathan Lewis when you need him ? !!!

Regards
Adrian Received on Fri Dec 17 2004 - 08:21:47 CST

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US