Oracle FAQ | Your Portal to the Oracle Knowledge Grid |
Home -> Community -> Usenet -> c.d.o.server -> Re: table constraint
Here is the same package again, but with a corrected lck procedure and
including a procedure implementing Charles Hooper's idea.
create table mytable
as
select 1 colour, 1 direction,
to_date('25062007120000','ddmmyyyyhh24miss') mydate from dual
/
alter table mytable add constraint mytable_pk primary key
(colour,direction,mydate)
/
exec dbms_stats.gather_table_stats(user,'mytable',cascade=>true)
create package mytable_api
as
procedure ins
( p_colour in mytable.colour%type
( p_colour in mytable.colour%type
( name => 'mytable_api.ins' || to_char(p_colour) || '|' || to_char(p_direction)
, base => 1 , hash_size => power(2,30) )
( p_colour in mytable.colour%type
into l_dummy from mytable where colour = p_colour and direction = p_direction and mydate between p_mydate - 3/24/60 and p_mydate + 3/24/60;
( p_colour , p_direction , p_mydate
( p_colour in mytable.colour%type
d.colour, d.direction, nvl(min(t1.mydate),d.mydate) mydate from (select p_colour colour, p_direction direction, p_mydate mydate from dual) d, mytable t1 where d.colour=t1.colour(+) and d.direction=t1.direction(+) and (d.mydate-0.002083333)<=t1.mydate(+) and (d.mydate+0.002083333)>=t1.mydate(+) group by d.colour, d.direction, d.mydate
I ran the following test:
remark Warming up
alter session set sql_trace true
/
exec mytable_api.ins(1,1,sysdate);
exec mytable_api.charles_hooper_ins(1,2,sysdate)
declare
l_start_time number := dbms_utility.get_time;
begin
for i in 1..1000
loop
mytable_api.ins
( trunc(dbms_random.value(0,2))
, trunc(dbms_random.value(0,2))
, sysdate - dbms_random.value(-.2,.2)
);
end loop;
dbms_output.put_line(to_char(dbms_utility.get_time - l_start_time)
|| ' hsecs');
rollback;
l_start_time := dbms_utility.get_time;
for i in 1..1000
loop
mytable_api.charles_hooper_ins
( trunc(dbms_random.value(0,2))
, trunc(dbms_random.value(0,2))
, sysdate - dbms_random.value(-.2,.2)
);
end loop;
dbms_output.put_line(to_char(dbms_utility.get_time - l_start_time)
|| ' hsecs');
rollback;
end;
/
disconnect
The output was:
67 hsecs
1186 hsecs
And tkprof was showing this as most costly statement (apart from the PL/SQL block itself):
INSERT INTO MYTABLE SELECT /*+ ordered */ D.COLOUR, D.DIRECTION,
NVL(MIN(T1.MYDATE),D.MYDATE) MYDATE FROM (SELECT 1 COLOUR, 1
DIRECTION,
TO_DATE('25-jun-2007 11:59:00','dd-mon-yyyy hh24:mi:ss') MYDATE FROM
DUAL D)
D, MYTABLE T1 WHERE D.COLOUR=T1.COLOUR(+) AND
D.DIRECTION=T1.DIRECTION(+)
AND (D.MYDATE-0.002083333)<=T1.MYDATE(+) AND (D.MYDATE
+0.002083333)>=
T1.MYDATE(+) GROUP BY D.COLOUR, D.DIRECTION, D.MYDATE
call count cpu elapsed disk query current rows
Parse 1 0.00 0.00 0 0 0 0 Execute 1001 6.42 6.48 0 2008 5053 0 Fetch 0 0.00 0.00 0 0 0 0
total 1002 6.42 6.48 0 2008 5053 0
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 61 (recursive depth: 1)
Rows Row Source Operation
------- ---------------------------------------------------
1001 SORT GROUP BY NOSORT (cr=2001 pr=0 pw=0 time=108523 us) 1001 NESTED LOOPS OUTER (cr=2001 pr=0 pw=0 time=74805 us) 1001 FAST DUAL (cr=0 pr=0 pw=0 time=12952 us) 1001 INDEX RANGE SCAN MYTABLE_PK (cr=2001 pr=0 pw=0 time=36076 us)(object id 58226)
There are two things I cannot explain right now, and it's too late at
night for me to explore further:
- 1186 hsecs and 648 hsecs elapsed time, what is the procedure doing
in the other 5 seconds? Maybe it is running the PL/SQL block and
calculating all the dbms_random.value's ?
- Why 648 hsecs elapsed time where the row source operation looks much
more efficient?
Regards,
Rob.
Received on Wed Jun 27 2007 - 18:15:57 CDT