Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> Tuning a SQL statement with expensive function calls
(Version 8.1.7, Solaris)
I have this SQL statement
select g.group_id, g.group_name,
nvl(cr.group_id,0) as parent_id,
decode(acs_permission.permission_p(g.group_id, :user_id, 'admin'), 'f',0,1)
as admin_p,
decode(acs_permission.permission_p(g.group_id, :user_id, 'group_read_name'),
'f',0,1) as visible_p
from groups g, orga_group_ext og, composition_rels cr
where og.group_id = g.group_id
and cr.component_id(+) = g.group_id
order by lower(g.group_name)
The call to acs_permission.permission_p is pretty, pretty expensive. The relation between groups and orga_group_ext is 1:n.
The Execution Plan looks like this:
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=120 Bytes=504 0) 1 0 SORT (ORDER BY) (Cost=6 Card=120 Bytes=5040) 2 1 HASH JOIN (OUTER) (Cost=4 Card=120 Bytes=5040) 3 2 NESTED LOOPS (Cost=2 Card=74 Bytes=2516) 4 3 TABLE ACCESS (FULL) OF 'GROUPS' (Cost=1 Card=514 Byt es=15420) 5 3 INDEX (UNIQUE SCAN) OF 'ORGA_GROUP_EXT_GROUP_ID_PK' (UNIQUE) 6 2 INDEX (FULL SCAN) OF 'COMPOSITION_RELS_COMP_GR_IDX' (U NIQUE) (Cost=3 Card=605 Bytes=4840)
I have been trying to push the acs_permission.permission_p call further down. Something like this:
select nvl(cr.group_id,0) as parent_id, g.group_id, g.group_name,
g.admin_p, g.visible_p from
(select * from (select g.group_id, g.group_name,
decode(acs_permission.permission_p(g.group_id, :user_id, 'admin'), 'f',0,1)
as admin_p,
decode(acs_permission.permission_p(g.group_id, :user_id, 'group_read_name'),
'f',0,1) as visible_p
from groups g, orga_group_ext og where og.group_id = g.group_id order by lower(g.group_name)) ) g, composition_rels crwhere cr.component_id(+) = g.group_id;
Execution Plan
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=133 Bytes=105 07) 1 0 HASH JOIN (OUTER) (Cost=6 Card=133 Bytes=10507) 2 1 VIEW (Cost=4 Card=63 Bytes=4473) 3 2 SORT (ORDER BY) (Cost=4 Card=63 Bytes=2142) 4 3 NESTED LOOPS (Cost=2 Card=63 Bytes=2142) 5 4 TABLE ACCESS (FULL) OF 'GROUPS' (Cost=1 Card=514 B ytes=15420) 6 4 INDEX (UNIQUE SCAN) OF 'ORGA_GROUP_EXT_GROUP_ID_PK ' (UNIQUE) 7 1 INDEX (FULL SCAN) OF 'COMPOSITION_RELS_COMP_GR_IDX' (UNI QUE) (Cost=3 Card=605 Bytes=4840)
Consistent gets go down from ~29.300 to ~5.600. Is there a way to squeeze out more?
The function permission_p looks like this:
function permission_p (
object_id acs_objects.object_id%TYPE,
party_id parties.party_id%TYPE,
privilege acs_privileges.privilege%TYPE
) return char
as
exists_p char(1);
begin
--
So basically it's a chain of 5 if statements and the only thing I'm interested in is whether there's at least one permissioning record. Hence the explicit FIRST_ROWS hint.
regards Dirk Received on Wed Jan 23 2002 - 09:52:17 CST