Pipe function vs Decode!
Alex, October 16, 2003 - 10:36 am UTC
Hello Tom,
And thank you for the great reply!
We have not followed up earlier is because we have been exploring carefully both alternatives you suggested.
We were a litle surprised by the results!
At first.. we thought the idea of a pipeline function was very elegant so we explored that avenue first. However we soon came to a roadblock - when I first posted our query I possibly over simplified the issue.
In the original post I outlined that there was a number some lookup tables which needed to be joined together with a single table with nuumerous columns to be transposed to rows. There is actually 2 tables...
Looking at our original View:
-- ----------------------------------------------------------------------------------
CREATE OR REPLACE FORCE VIEW EP.EP_V_PERIODMAP_CURVE_R_OLD
(EPCM_CALENDAR_ID, EPCM_SEASON_ID, EPCM_DAY_ID, EPCM_DATE, CURVE_ID,
P_NO, PERIOD_ID, P_VALUE)
AS
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, cm.EPCM_DATE, cd.CURVE_ID, 'P0030' as P_NO, pm.P0030 as PERIOD_ID, cd.P0030 as P_VALUE
from ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails cd
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = cd.curvedetails_date
union all
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, cm.EPCM_DATE, cd.CURVE_ID, 'P0100' as P_NO, pm.P0100 as PERIOD_ID, cd.P0100 as P_VALUE
from ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails cd
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = cd.curvedetails_date
union all
...
union all
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, cm.EPCM_DATE, cd.CURVE_ID, 'P2400' as P_NO, pm.P2400 as PERIOD_ID, cd.P2400 as P_VALUE
from ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails cd
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = cd.curvedetails_date;
-- ----------------------------------------------------------------------------------
For the record... this is has been perform! (7 seconds is too too long!)
ep@EP> select * from EP_V_PERIODMAP_CURVE_READINGS where curve_id = 120403
and EPCM_DATE between '01-Jul-2003' and '10-Jul-2003';
-- ----------------------------------------------------------------------------------
But what I did not tell you as you ca derive from the view structure is that the fields pm.P0030 as PERIOD_ID to pm.P2400 as PERIOD_ID also requires transposition!
So... we we came up with the following interpretation of your sample code... you will note that we have created Type ty_cal_map IS RECORD and we manage both the values (from our UNION query):
pm.P0230 as PERIOD_ID
cd.P0230 as P_VALUE
as
l_rec.p_no := 'P0030';
l_rec.period_id := ty_output_values(i).p0030;
l_rec.p_value := ty_output_values(i).c0030;
as you can see in function EE_PeriodMapCurveReadings...
-- ----------------------------------------------------------------------------------
create or replace type myCurvePeriodMapValues as object
(EPCM_calendar_id number,
EPCM_season_id number,
EPCM_day_id number,
EPCM_date date,
Curve_id number,
p_no varchar2(6),
period_id number(9),
p_value number);
/
/* Source of TYPE BODY MYCURVEPERIODMAPVALUES is not available */
/
create or replace type ty_PeriodMap_Curvedetails as table of myCurvePeriodMapValues;
/
create or replace function EE_PeriodMapCurveReadings(p_cursor in sys_refcursor) return ty_PeriodMap_Curvedetails
PIPELINED IS
l_rec myCurvePeriodMapValues := myCurvePeriodMapValues(null,null,null,null,null,null,null,null);
Type ty_cal_map IS RECORD
(Cal_id NUMBER,
Season_Id NUMBER,
Day_Id NUMBER,
C_Date DATE,
curve_id NUMBER,
p0030 number, p0100 number, p0130 number, p0200 number, p0230 number, p0300 number,
p0330 number, p0400 number, p0430 number, p0500 number, p0530 number, p0600 number,
p0630 number, p0700 number, p0730 number, p0800 number, p0830 number, p0900 number,
p0930 number, p1000 number, p1030 number, p1100 number, p1130 number, p1200 number,
p1230 number, p1300 number, p1330 number, p1400 number, p1430 number, p1500 number,
p1530 number, p1600 number, p1630 number, p1700 number, p1730 number, p1800 number,
p1830 number, p1900 number, p1930 number, p2000 number, p2030 number, p2100 number,
p2130 number, p2200 number, p2230 number, p2300 number, p2330 number, p2400 number,
c0030 number, c0100 number, c0130 number, c0200 number, c0230 number, c0300 number,
c0330 number, c0400 number, c0430 number, c0500 number, c0530 number, c0600 number,
c0630 number, c0700 number, c0730 number, c0800 number, c0830 number, c0900 number,
c0930 number, c1000 number, c1030 number, c1100 number, c1130 number, c1200 number,
c1230 number, c1300 number, c1330 number, c1400 number, c1430 number, c1500 number,
c1530 number, c1600 number, c1630 number, c1700 number, c1730 number, c1800 number,
c1830 number, c1900 number, c1930 number, c2000 number, c2030 number, c2100 number,
c2130 number, c2200 number, c2230 number, c2300 number, c2330 number, c2400 number);
Type ty_RP_CalPer_Map is table of ty_cal_map index by binary_integer;
ty_output_values Ty_Rp_Calper_Map;
begin
loop
fetch p_cursor bulk collect into ty_output_values limit 100; -- _data, qq_data limit 100;
for i in 1 .. ty_output_values.count
loop
l_rec.epcm_calendar_id := ty_output_values(i).Cal_id;
l_rec.epcm_season_id := ty_output_values(i).Season_id;
l_rec.epcm_day_id := ty_output_values(i).Day_id;
l_rec.epcm_date := ty_output_values(i).c_date;
l_rec.curve_id := ty_output_values(i).curve_id;
l_rec.p_no := 'P0030';
l_rec.period_id := ty_output_values(i).p0030;
l_rec.p_value := ty_output_values(i).c0030;
pipe row( l_rec );
l_rec.p_no := 'P0100';
l_rec.period_id := ty_output_values(i).p0100;
l_rec.p_value := ty_output_values(i).c0100;
pipe row( l_rec );
l_rec.p_no := 'P0130';
l_rec.period_id := ty_output_values(i).p0130;
l_rec.p_value := ty_output_values(i).c0130;
pipe row( l_rec );
...
l_rec.p_no := 'P2400';
l_rec.period_id := ty_output_values(i).p2400;
l_rec.p_value := ty_output_values(i).c2400;
end loop;
exit when p_cursor%notfound;
end loop;
close p_cursor;
return;
-- end;
end EE_PeriodMapCurveReadings;
/
-- ----------------------------------------------------------------------------------
This produced the vastly improved results:
timing for: new_RP_functions
Elapsed: 00:00:00.00
ep@EP>
ep@EP> set autotrace traceonly;
ep@EP>
ep@EP>
ep@EP> select * from TABLE(EE_PeriodMapCurveReadings(cursor(
2 select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, CM.EPCM_DATE, cd.curve_id,
3 pm.P0030, pm.P0100,pm.P0130, pm.P0200,pm.P0230, pm.P0300,pm.P0330, pm.P0400,pm.P0430, pm.P0
500,
4 pm.P0530, pm.P0600,pm.P0630, pm.P0700,pm.P0730, pm.P0800,pm.P0830, pm.P0900,pm.P0930, pm.P1
000,
5 pm.P1030, pm.P1100,pm.P1130, pm.P1200,pm.P1230, pm.P1300,pm.P1330, pm.P1400,pm.P1430, pm.P1
500,
6 pm.P1530, pm.P1600,pm.P1630, pm.P1700,pm.P1730, pm.P1800,pm.P1830, pm.P1900,pm.P1930, pm.P2
000,
7 pm.P2030, pm.P2100,pm.P2130, pm.P2200,pm.P2230, pm.P2300,pm.P2330, pm.P2400,
8 cd.P0030, cd.P0100,cd.P0130, cd.P0200,cd.P0230, cd.P0300,cd.P0330, cd.P0400,cd.P0430, cd.P0
500,
9 cd.P0530, cd.P0600,cd.P0630, cd.P0700,cd.P0730, cd.P0800,cd.P0830, cd.P0900,cd.P0930, cd.P1
000,
10 cd.P1030, cd.P1100,cd.P1130, cd.P1200,cd.P1230, cd.P1300,cd.P1330, cd.P1400,cd.P1430, cd.P1
500,
11 cd.P1530, cd.P1600,cd.P1630, cd.P1700,cd.P1730, cd.P1800,cd.P1830, cd.P1900,cd.P1930, cd.P2
000,
12 cd.P2030, cd.P2100,cd.P2130, cd.P2200,cd.P2230, cd.P2300,cd.P2330, cd.P2400
13 from ep_calendar_map cm,
14 ep_period_map pm,
15 ep_curvedetails cd
16 where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
17 and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
18 and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
19 and cm.EPCM_DATE = cd.curvedetails_date
20 and cd.curve_id = 120403
21 and cd.curvedetails_date between '01-Jul-2003' and '10-Jul-2003'
22 )));
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=8168 Bytes=56
19584)
1 0 VIEW (Cost=4 Card=8168 Bytes=5619584)
2 1 COLLECTION ITERATOR (PICKLER FETCH) OF 'EE_PERIODMAPCURV
EREADINGS'
Statistics
----------------------------------------------------------
7 recursive calls
0 db block gets
7309 consistent gets
0 physical reads
0 redo size
204772 bytes sent via SQL*Net to client
7770 bytes received via SQL*Net from client
663 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
9917 rows processed
ep@EP>
ep@EP> timing show
timing for: new_RP_functions
Elapsed: 00:00:01.01
ep@EP> spool off
TKPROF: Release 9.2.0.3.0 - Production on Thu Oct 16 23:50:54 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Trace file: ep_ora_2880.trc
Sort options: fchela exeela
********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
********************************************************************************
select * from TABLE(EE_PeriodMapCurveReadings(cursor(
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, CM.EPCM_DATE, cd.curve_id,
pm.P0030, pm.P0100,pm.P0130, pm.P0200,pm.P0230, pm.P0300,pm.P0330, pm.P0400,pm.P0430, pm.P0500,
pm.P0530, pm.P0600,pm.P0630, pm.P0700,pm.P0730, pm.P0800,pm.P0830, pm.P0900,pm.P0930, pm.P1000,
pm.P1030, pm.P1100,pm.P1130, pm.P1200,pm.P1230, pm.P1300,pm.P1330, pm.P1400,pm.P1430, pm.P1500,
pm.P1530, pm.P1600,pm.P1630, pm.P1700,pm.P1730, pm.P1800,pm.P1830, pm.P1900,pm.P1930, pm.P2000,
pm.P2030, pm.P2100,pm.P2130, pm.P2200,pm.P2230, pm.P2300,pm.P2330, pm.P2400,
cd.P0030, cd.P0100,cd.P0130, cd.P0200,cd.P0230, cd.P0300,cd.P0330, cd.P0400,cd.P0430, cd.P0500,
cd.P0530, cd.P0600,cd.P0630, cd.P0700,cd.P0730, cd.P0800,cd.P0830, cd.P0900,cd.P0930, cd.P1000,
cd.P1030, cd.P1100,cd.P1130, cd.P1200,cd.P1230, cd.P1300,cd.P1330, cd.P1400,cd.P1430, cd.P1500,
cd.P1530, cd.P1600,cd.P1630, cd.P1700,cd.P1730, cd.P1800,cd.P1830, cd.P1900,cd.P1930, cd.P2000,
cd.P2030, cd.P2100,cd.P2130, cd.P2200,cd.P2230, cd.P2300,cd.P2330, cd.P2400
from ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails cd
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = cd.curvedetails_date
and cd.curve_id = 120403
and cd.curvedetails_date between '01-Jul-2003' and '10-Jul-2003'
)))
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.37 0.41 0 125 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 42 1.12 1.24 0 14834 0 19834
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 46 1.50 1.65 0 14959 0 19834
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 57 (EP)
Rows Row Source Operation
------- ---------------------------------------------------
9917 VIEW (cr=7527 r=0 w=0 time=494932 us)
9917 COLLECTION ITERATOR PICKLER FETCH (cr=7527 r=0 w=0 time=431058 us)
Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT GOAL: CHOOSE
9917 VIEW
9917 COLLECTION ITERATOR (PICKLER FETCH) OF
'EE_PERIODMAPCURVEREADINGS'
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 42 0.00 0.00
SQL*Net message from client 42 0.00 0.12
SQL*Net more data to client 118 0.00 0.06
********************************************************************************
SELECT "A4"."EPCM_CALENDAR_ID" "EPCM_CALENDAR_ID","A4"."EPCM_SEASON_ID"
"EPCM_SEASON_ID","A4"."EPCM_DAY_ID" "EPCM_DAY_ID","A4"."EPCM_DATE"
"EPCM_DATE","A2"."CURVE_ID" "CURVE_ID","A3"."P0030" "P0030","A3"."P0100"
"P0100","A3"."P0130" "P0130","A3"."P0200" "P0200","A3"."P0230" "P0230",
"A3"."P0300" "P0300","A3"."P0330" "P0330","A3"."P0400" "P0400","A3"."P0430"
"P0430","A3"."P0500" "P0500","A3"."P0530" "P0530","A3"."P0600" "P0600",
"A3"."P0630" "P0630","A3"."P0700" "P0700","A3"."P0730" "P0730","A3"."P0800"
"P0800","A3"."P0830" "P0830","A3"."P0900" "P0900","A3"."P0930" "P0930",
"A3"."P1000" "P1000","A3"."P1030" "P1030","A3"."P1100" "P1100","A3"."P1130"
"P1130","A3"."P1200" "P1200","A3"."P1230" "P1230","A3"."P1300" "P1300",
"A3"."P1330" "P1330","A3"."P1400" "P1400","A3"."P1430" "P1430","A3"."P1500"
"P1500","A3"."P1530" "P1530","A3"."P1600" "P1600","A3"."P1630" "P1630",
"A3"."P1700" "P1700","A3"."P1730" "P1730","A3"."P1800" "P1800","A3"."P1830"
"P1830","A3"."P1900" "P1900","A3"."P1930" "P1930","A3"."P2000" "P2000",
"A3"."P2030" "P2030","A3"."P2100" "P2100","A3"."P2130" "P2130","A3"."P2200"
"P2200","A3"."P2230" "P2230","A3"."P2300" "P2300","A3"."P2330" "P2330",
"A3"."P2400" "P2400","A2"."P0030" "P0030","A2"."P0100" "P0100","A2"."P0130"
"P0130","A2"."P0200" "P0200","A2"."P0230" "P0230","A2"."P0300" "P0300",
"A2"."P0330" "P0330","A2"."P0400" "P0400","A2"."P0430" "P0430","A2"."P0500"
"P0500","A2"."P0530" "P0530","A2"."P0600" "P0600","A2"."P0630" "P0630",
"A2"."P0700" "P0700","A2"."P0730" "P0730","A2"."P0800" "P0800","A2"."P0830"
"P0830","A2"."P0900" "P0900","A2"."P0930" "P0930","A2"."P1000" "P1000",
"A2"."P1030" "P1030","A2"."P1100" "P1100","A2"."P1130" "P1130","A2"."P1200"
"P1200","A2"."P1230" "P1230","A2"."P1300" "P1300","A2"."P1330" "P1330",
"A2"."P1400" "P1400","A2"."P1430" "P1430","A2"."P1500" "P1500","A2"."P1530"
"P1530","A2"."P1600" "P1600","A2"."P1630" "P1630","A2"."P1700" "P1700",
"A2"."P1730" "P1730","A2"."P1800" "P1800","A2"."P1830" "P1830","A2"."P1900"
"P1900","A2"."P1930" "P1930","A2"."P2000" "P2000","A2"."P2030" "P2030",
"A2"."P2100" "P2100","A2"."P2130" "P2130","A2"."P2200" "P2200","A2"."P2230"
"P2230","A2"."P2300" "P2300","A2"."P2330" "P2330","A2"."P2400" "P2400"
FROM
"EP_CALENDAR_MAP" "A4","EP_PERIOD_MAP" "A3","EP_CURVEDETAILS" "A2" WHERE
"A4"."EPCM_CALENDAR_ID"="A3"."EPPM_CALENDAR_ID" AND "A4"."EPCM_SEASON_ID"=
"A3"."EPPM_SEASON_ID" AND "A4"."EPCM_DAY_ID"="A3"."EPPM_DAY_ID" AND
"A4"."EPCM_DATE"="A2"."CURVEDETAILS_DATE" AND "A2"."CURVE_ID"=120403 AND
"A2"."CURVEDETAILS_DATE">='01-Jul-2003' AND "A2"."CURVEDETAILS_DATE"<=
'10-Jul-2003'
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.00 0.00 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 6 0.31 0.29 0 14594 0 422
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 10 0.31 0.29 0 14594 0 422
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 57 (EP) (recursive depth: 2)
Rows Row Source Operation
------- ---------------------------------------------------
211 NESTED LOOPS (cr=7297 r=0 w=0 time=133946 us)
7250 MERGE JOIN CARTESIAN (cr=43 r=0 w=0 time=54967 us)
10 TABLE ACCESS BY INDEX ROWID EP_CURVEDETAILS (cr=12 r=0 w=0 time=1660 us)
365 INDEX RANGE SCAN EP_CUREVEDETAILS_ID_INDEX (cr=6 r=0 w=0 time=700 us)(object id 37565)
7250 BUFFER SORT (cr=31 r=0 w=0 time=31077 us)
725 TABLE ACCESS FULL EP_PERIOD_MAP (cr=31 r=0 w=0 time=1616 us)
211 INDEX UNIQUE SCAN EP_CALENDAR_MAP_IDX (cr=7254 r=0 w=0 time=41198 us)(object id 38588)
Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT GOAL: CHOOSE
211 NESTED LOOPS
7250 MERGE JOIN (CARTESIAN)
10 TABLE ACCESS GOAL: ANALYZED (BY INDEX ROWID) OF
'EP_CURVEDETAILS'
365 INDEX GOAL: ANALYZED (RANGE SCAN) OF
'EP_CUREVEDETAILS_ID_INDEX' (NON-UNIQUE)
7250 BUFFER (SORT)
725 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'EP_PERIOD_MAP'
211 INDEX GOAL: ANALYZED (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX'
(UNIQUE)
********************************************************************************
My first question is... did we approach this implementation of the pipe function appropriately?
We wonder because... it was NOT as fast as the Decode or Case approach!!!!
Here is the structure and benchmark results:
-- --------------------------------------------------------------
CREATE OR REPLACE FORCE VIEW EP.EP_V_PERIODMAP_CURVE_READINGS
(EPCM_CALENDAR_ID, EPCM_SEASON_ID, EPCM_DAY_ID, EPCM_DATE, CURVE_ID,
P_NO, PERIOD_ID, P_VALUE)
AS
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, cm.EPCM_DATE, EP.CURVE_ID,
decode(x, 1, 'P0030', 2, 'P0100', 3, 'P0130', 4, 'P0200', 5, 'P0230', 6, 'P0300', 7, 'P0330', 8, 'P0400',
9, 'P0430', 10, 'P0500', 11, 'P0530', 12, 'P0600', 13, 'P0630', 14, 'P0700', 15, 'P0730', 16, 'P0800',
17, 'P0830', 18, 'P0900', 19, 'P0930', 20, 'P1000', 21, 'P1030', 22, 'P1100', 23, 'P1130', 24, 'P1200',
25, 'P1230', 26, 'P1300', 27, 'P1330', 28, 'P1400', 29, 'P1430', 30, 'P1500', 31, 'P1530', 32, 'P1600',
33, 'P1630', 34, 'P1700', 35, 'P1730', 36, 'P1800', 37, 'P1830', 38, 'P1900', 39, 'P1930', 40, 'P2000',
41, 'P2030', 42, 'P2100', 43, 'P2130', 44, 'P2200', 45, 'P2230', 46, 'P2300', 47, 'P2330', 48, 'P2400') P_no,
decode(x, 1, pm.P0030, 2, pm.P0100, 3, pm.P0130, 4, pm.P0200, 5, pm.P0230, 6, pm.P0300, 7, pm.P0330, 8, pm.P0400,
9, pm.P0430, 10, pm.P0500, 11, pm.P0530, 12, pm.P0600, 13, pm.P0630, 14, pm.P0700, 15, pm.P0730, 16, pm.P0800,
17, pm.P0830, 18, pm.P0900, 19, pm.P0930, 20, pm.P1000, 21, pm.P1030, 22, pm.P1100, 23, pm.P1130, 24, pm.P1200,
25, pm.P1230, 26, pm.P1300, 27, pm.P1330, 28, pm.P1400, 29, pm.P1430, 30, pm.P1500, 31, pm.P1530, 32, pm.P1600,
33, pm.P1630, 34, pm.P1700, 35, pm.P1730, 36, pm.P1800, 37, pm.P1830, 38, pm.P1900, 39, pm.P1930, 40, pm.P2000,
41, pm.P2030, 42, pm.P2100, 43, pm.P2130, 44, pm.P2200, 45, pm.P2230, 46, pm.P2300, 47, pm.P2330, 48, pm.P2400) Period_ID,
decode(x, 1, ep.P0030, 2, EP.P0100, 3, EP.P0130, 4, EP.P0200, 5, EP.P0230, 6, EP.P0300, 7, EP.P0330, 8, EP.P0400,
9, EP.P0430, 10, EP.P0500, 11, EP.P0530, 12, EP.P0600, 13, EP.P0630, 14, EP.P0700, 15, EP.P0730, 16, EP.P0800,
17, EP.P0830, 18, EP.P0900, 19, EP.P0930, 20, EP.P1000, 21, EP.P1030, 22, EP.P1100, 23, EP.P1130, 24, EP.P1200,
25, EP.P1230, 26, EP.P1300, 27, EP.P1330, 28, EP.P1400, 29, EP.P1430, 30, EP.P1500, 31, EP.P1530, 32, EP.P1600,
33, EP.P1630, 34, EP.P1700, 35, EP.P1730, 36, EP.P1800, 37, EP.P1830, 38, EP.P1900, 39, EP.P1930, 40, EP.P2000,
41, EP.P2030, 42, EP.P2100, 43, EP.P2130, 44, EP.P2200, 45, EP.P2230, 46, EP.P2300, 47, EP.P2330, 48, EP.P2400) P_value
from ( select x from tall_dual where x <= 48) b,
ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails ep
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = ep.curvedetails_date;
timing for: Benchmark
Elapsed: 00:00:00.00
ep@EP>
ep@EP> select * from EP_V_PERIODMAP_CURVE_READINGS where curve_id = 120403 and EPCM_DATE between '01-Jul-2003' and '10-Jul-2003';
10128 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=315 Bytes=83
790)
1 0 MERGE JOIN (CARTESIAN) (Cost=12 Card=315 Bytes=83790)
2 1 NESTED LOOPS (Cost=11 Card=1 Bytes=253)
3 2 MERGE JOIN (CARTESIAN) (Cost=11 Card=594 Bytes=140778)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'EP_CURVEDETAILS' (
Cost=9 Card=1 Bytes=41)
5 4 INDEX (RANGE SCAN) OF 'EP_CUREVEDETAILS_ID_INDEX'
(NON-UNIQUE) (Cost=3 Card=286)
6 3 BUFFER (SORT) (Cost=2 Card=725 Bytes=142100)
7 6 TABLE ACCESS (FULL) OF 'EP_PERIOD_MAP' (Cost=2 Car
d=725 Bytes=142100)
8 2 INDEX (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX' (UNIQUE)
9 1 BUFFER (SORT) (Cost=12 Card=408 Bytes=5304)
10 9 INDEX (RANGE SCAN) OF 'SYS_IOT_TOP_38649' (UNIQUE) (Co
st=1 Card=408 Bytes=5304)
Statistics
----------------------------------------------------------
4073 recursive calls
0 db block gets
8076 consistent gets
0 physical reads
0 redo size
129722 bytes sent via SQL*Net to client
719 bytes received via SQL*Net from client
22 SQL*Net roundtrips to/from client
44 sorts (memory)
0 sorts (disk)
10128 rows processed
ep@EP>
ep@EP> set echo off
10128 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=315 Bytes=83
790)
1 0 MERGE JOIN (CARTESIAN) (Cost=12 Card=315 Bytes=83790)
2 1 NESTED LOOPS (Cost=11 Card=1 Bytes=253)
3 2 MERGE JOIN (CARTESIAN) (Cost=11 Card=594 Bytes=140778)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'EP_CURVEDETAILS' (
Cost=9 Card=1 Bytes=41)
5 4 INDEX (RANGE SCAN) OF 'EP_CUREVEDETAILS_ID_INDEX'
(NON-UNIQUE) (Cost=3 Card=286)
6 3 BUFFER (SORT) (Cost=2 Card=725 Bytes=142100)
7 6 TABLE ACCESS (FULL) OF 'EP_PERIOD_MAP' (Cost=2 Car
d=725 Bytes=142100)
8 2 INDEX (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX' (UNIQUE)
9 1 BUFFER (SORT) (Cost=12 Card=408 Bytes=5304)
10 9 INDEX (RANGE SCAN) OF 'SYS_IOT_TOP_38649' (UNIQUE) (Co
st=1 Card=408 Bytes=5304)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
7333 consistent gets
0 physical reads
0 redo size
129722 bytes sent via SQL*Net to client
719 bytes received via SQL*Net from client
22 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
10128 rows processed
timing for: Benchmark
Elapsed: 00:00:01.05
TKPROF: Release 9.2.0.3.0 - Production on Fri Oct 17 00:18:20 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Trace file: ep_ora_1272.trc
Sort options: fchela exeela
********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
****
October 16, 2003 - 3:08 pm UTC
I don't see anything obviously wrong in your implementation -- but that is why i gave you two methods -- benchmark them and see which works best in your case.
Most of the times, if you can do it in straight sql, thats best. there are cases where plsql can edge it out, but here -- the massive assignments probably killed us.
Pipe function vs Decode (cont'd)
Alex, October 16, 2003 - 10:39 am UTC
Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT GOAL: CHOOSE
211 NESTED LOOPS
7250 MERGE JOIN (CARTESIAN)
10 TABLE ACCESS GOAL: ANALYZED (BY INDEX ROWID) OF
'EP_CURVEDETAILS'
365 INDEX GOAL: ANALYZED (RANGE SCAN) OF
'EP_CUREVEDETAILS_ID_INDEX' (NON-UNIQUE)
7250 BUFFER (SORT)
725 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'EP_PERIOD_MAP'
211 INDEX GOAL: ANALYZED (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX'
(UNIQUE)
********************************************************************************
My first question is... did we approach this implementation of the pipe function appropriately?
We wonder because... it was NOT as fast as the Decode or Case approach!!!!
Here is the structure and benchmark results:
-- --------------------------------------------------------------
CREATE OR REPLACE FORCE VIEW EP.EP_V_PERIODMAP_CURVE_READINGS
(EPCM_CALENDAR_ID, EPCM_SEASON_ID, EPCM_DAY_ID, EPCM_DATE, CURVE_ID,
P_NO, PERIOD_ID, P_VALUE)
AS
select cm.EPCM_CALENDAR_ID, cm.EPCM_SEASON_ID, cm.EPCM_DAY_ID, cm.EPCM_DATE, EP.CURVE_ID,
decode(x, 1, 'P0030', 2, 'P0100', 3, 'P0130', 4, 'P0200', 5, 'P0230', 6, 'P0300', 7, 'P0330', 8, 'P0400',
9, 'P0430', 10, 'P0500', 11, 'P0530', 12, 'P0600', 13, 'P0630', 14, 'P0700', 15, 'P0730', 16, 'P0800',
17, 'P0830', 18, 'P0900', 19, 'P0930', 20, 'P1000', 21, 'P1030', 22, 'P1100', 23, 'P1130', 24, 'P1200',
25, 'P1230', 26, 'P1300', 27, 'P1330', 28, 'P1400', 29, 'P1430', 30, 'P1500', 31, 'P1530', 32, 'P1600',
33, 'P1630', 34, 'P1700', 35, 'P1730', 36, 'P1800', 37, 'P1830', 38, 'P1900', 39, 'P1930', 40, 'P2000',
41, 'P2030', 42, 'P2100', 43, 'P2130', 44, 'P2200', 45, 'P2230', 46, 'P2300', 47, 'P2330', 48, 'P2400') P_no,
decode(x, 1, pm.P0030, 2, pm.P0100, 3, pm.P0130, 4, pm.P0200, 5, pm.P0230, 6, pm.P0300, 7, pm.P0330, 8, pm.P0400,
9, pm.P0430, 10, pm.P0500, 11, pm.P0530, 12, pm.P0600, 13, pm.P0630, 14, pm.P0700, 15, pm.P0730, 16, pm.P0800,
17, pm.P0830, 18, pm.P0900, 19, pm.P0930, 20, pm.P1000, 21, pm.P1030, 22, pm.P1100, 23, pm.P1130, 24, pm.P1200,
25, pm.P1230, 26, pm.P1300, 27, pm.P1330, 28, pm.P1400, 29, pm.P1430, 30, pm.P1500, 31, pm.P1530, 32, pm.P1600,
33, pm.P1630, 34, pm.P1700, 35, pm.P1730, 36, pm.P1800, 37, pm.P1830, 38, pm.P1900, 39, pm.P1930, 40, pm.P2000,
41, pm.P2030, 42, pm.P2100, 43, pm.P2130, 44, pm.P2200, 45, pm.P2230, 46, pm.P2300, 47, pm.P2330, 48, pm.P2400) Period_ID,
decode(x, 1, ep.P0030, 2, EP.P0100, 3, EP.P0130, 4, EP.P0200, 5, EP.P0230, 6, EP.P0300, 7, EP.P0330, 8, EP.P0400,
9, EP.P0430, 10, EP.P0500, 11, EP.P0530, 12, EP.P0600, 13, EP.P0630, 14, EP.P0700, 15, EP.P0730, 16, EP.P0800,
17, EP.P0830, 18, EP.P0900, 19, EP.P0930, 20, EP.P1000, 21, EP.P1030, 22, EP.P1100, 23, EP.P1130, 24, EP.P1200,
25, EP.P1230, 26, EP.P1300, 27, EP.P1330, 28, EP.P1400, 29, EP.P1430, 30, EP.P1500, 31, EP.P1530, 32, EP.P1600,
33, EP.P1630, 34, EP.P1700, 35, EP.P1730, 36, EP.P1800, 37, EP.P1830, 38, EP.P1900, 39, EP.P1930, 40, EP.P2000,
41, EP.P2030, 42, EP.P2100, 43, EP.P2130, 44, EP.P2200, 45, EP.P2230, 46, EP.P2300, 47, EP.P2330, 48, EP.P2400) P_value
from ( select x from tall_dual where x <= 48) b,
ep_calendar_map cm,
ep_period_map pm,
ep_curvedetails ep
where cm.EPCM_CALENDAR_ID = pm.EPPM_CALENDAR_ID
and cm.EPCM_SEASON_ID = pm.EPPM_SEASON_ID
and cm.EPCM_DAY_ID = pm.EPPM_DAY_ID
and cm.EPCM_DATE = ep.curvedetails_date;
timing for: Benchmark
Elapsed: 00:00:00.00
ep@EP>
ep@EP> select * from EP_V_PERIODMAP_CURVE_READINGS where curve_id = 120403 and EPCM_DATE between '01-Jul-2003' and '10-Jul-2003';
10128 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=315 Bytes=83
790)
1 0 MERGE JOIN (CARTESIAN) (Cost=12 Card=315 Bytes=83790)
2 1 NESTED LOOPS (Cost=11 Card=1 Bytes=253)
3 2 MERGE JOIN (CARTESIAN) (Cost=11 Card=594 Bytes=140778)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'EP_CURVEDETAILS' (
Cost=9 Card=1 Bytes=41)
5 4 INDEX (RANGE SCAN) OF 'EP_CUREVEDETAILS_ID_INDEX'
(NON-UNIQUE) (Cost=3 Card=286)
6 3 BUFFER (SORT) (Cost=2 Card=725 Bytes=142100)
7 6 TABLE ACCESS (FULL) OF 'EP_PERIOD_MAP' (Cost=2 Car
d=725 Bytes=142100)
8 2 INDEX (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX' (UNIQUE)
9 1 BUFFER (SORT) (Cost=12 Card=408 Bytes=5304)
10 9 INDEX (RANGE SCAN) OF 'SYS_IOT_TOP_38649' (UNIQUE) (Co
st=1 Card=408 Bytes=5304)
Statistics
----------------------------------------------------------
4073 recursive calls
0 db block gets
8076 consistent gets
0 physical reads
0 redo size
129722 bytes sent via SQL*Net to client
719 bytes received via SQL*Net from client
22 SQL*Net roundtrips to/from client
44 sorts (memory)
0 sorts (disk)
10128 rows processed
ep@EP>
ep@EP> set echo off
10128 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=12 Card=315 Bytes=83
790)
1 0 MERGE JOIN (CARTESIAN) (Cost=12 Card=315 Bytes=83790)
2 1 NESTED LOOPS (Cost=11 Card=1 Bytes=253)
3 2 MERGE JOIN (CARTESIAN) (Cost=11 Card=594 Bytes=140778)
4 3 TABLE ACCESS (BY INDEX ROWID) OF 'EP_CURVEDETAILS' (
Cost=9 Card=1 Bytes=41)
5 4 INDEX (RANGE SCAN) OF 'EP_CUREVEDETAILS_ID_INDEX'
(NON-UNIQUE) (Cost=3 Card=286)
6 3 BUFFER (SORT) (Cost=2 Card=725 Bytes=142100)
7 6 TABLE ACCESS (FULL) OF 'EP_PERIOD_MAP' (Cost=2 Car
d=725 Bytes=142100)
8 2 INDEX (UNIQUE SCAN) OF 'EP_CALENDAR_MAP_IDX' (UNIQUE)
9 1 BUFFER (SORT) (Cost=12 Card=408 Bytes=5304)
10 9 INDEX (RANGE SCAN) OF 'SYS_IOT_TOP_38649' (UNIQUE) (Co
st=1 Card=408 Bytes=5304)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
7333 consistent gets
0 physical reads
0 redo size
129722 bytes sent via SQL*Net to client
719 bytes received via SQL*Net from client
22 SQL*Net roundtrips to/from client
2 sorts (memory)
0 sorts (disk)
10128 rows processed
timing for: Benchmark
Elapsed: 00:00:01.05
TKPROF: Release 9.2.0.3.0 - Production on Fri Oct 17 00:18:20 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Trace file: ep_ora_1272.trc
Sort options: fchela exeela
********************************************************************************
count = number of times OCI procedure was executed
cpu = cpu time in seconds executing
elapsed = elapsed time in seconds executing
disk = number of physical reads of buffers from disk
query = number of buffers gotten for consistent read
current = number of buffers gotten in current mode (usually for update)
rows = number of rows processed by the fetch or execute call
********************************************************************************
select * from EP_V_PERIODMAP_CURVE_READINGS where curve_id = 120403
and EPCM_DATE between '01-Jul-2003' and '10-Jul-2003'
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 2 0.25 0.30 0 743 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 44 0.59 0.55 0 14666 0 20256
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 48 0.84 0.85 0 15409 0 20256
Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 57 (EP)
Rows Row Source Operation
------- ---------------------------------------------------
10128 MERGE JOIN CARTESIAN (cr=7333 r=0 w=0 time=175006 us)
211 NESTED LOOPS (cr=7332 r=0 w=0 time=119713 us)
7250 MERGE JOIN CARTESIAN (cr=59 r=0 w=0 time=54276 us)
10 TABLE ACCESS BY INDEX ROWID EP_CURVEDETAILS (cr=28 r=0 w=0 time=1592 us)
365 INDEX RANGE SCAN EP_CUREVEDETAILS_ID_INDEX (cr=14 r=0 w=0 time=783 us)(object id 37565)
7250 BUFFER SORT (cr=31 r=0 w=0 time=30287 us)
725 TABLE ACCESS FULL EP_PERIOD_MAP (cr=31 r=0 w=0 time=1565 us)
211 INDEX UNIQUE SCAN EP_CALENDAR_MAP_IDX (cr=7273 r=0 w=0 time=34521 us)(object id 38588)
10128 BUFFER SORT (cr=1 r=0 w=0 time=17773 us)
48 INDEX RANGE SCAN SYS_IOT_TOP_38649 (cr=1 r=0 w=0 time=91 us)(object id 38650)
Rows Execution Plan
------- ---------------------------------------------------
0 SELECT STATEMENT GOAL: CHOOSE
10128 MERGE JOIN (CARTESIAN)
211 NESTED LOOPS
7250 MERGE JOIN (CARTESIAN)
10 TABLE ACCESS GOAL: ANALYZED (BY INDEX ROWID) OF
'EP_CURVEDETAILS'
365 INDEX GOAL: ANALYZED (RANGE SCAN) OF
'EP_CUREVEDETAILS_ID_INDEX' (NON-UNIQUE)
7250 BUFFER (SORT)
725 TABLE ACCESS GOAL: ANALYZED (FULL) OF 'EP_PERIOD_MAP'
211 INDEX GOAL: ANALYZED (UNIQUE SCAN) OF
'EP_CALENDAR_MAP_IDX' (UNIQUE)
10128 BUFFER (SORT)
48 INDEX (RANGE SCAN) OF 'SYS_IOT_TOP_38649' (UNIQUE)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 44 0.00 0.00
SQL*Net message from client 44 0.00 0.11
SQL*Net more data to client 120 0.00 0.05
********************************************************************************
-- ----------------------------------------------------------------------
So Decode was a bit slower.. but not by much! And in other tests it was actually faster - when returning larger date ranges!
Ultimately we have achieved outstanding results but I was hoping you might provide some more effective analysis of our pipe function...
Thank you so very much!
PS.. any plans to support HTML on your site.. so we can provide some colour formatting to make posts easier to read?