I have have a query that is performing poorly. One aspect of the query is the use of a cross join on a table-valued function, in all honestly I was mimicking my TSQL behaviors of using CROSS APPLY on a function to avoid using a scalar function call. Is this a bad behavior in Oracle?
The main issue I’m running into is that Oracle Tuning Advisor will not parse my query so I’m unable to research index optimizations yet. Normally I wouldn’t post this much code but I suspect it is my query more than table optimization that may be causing an issue.
The statistics se table is really the only table with volumn more than 4,000,000 records. Can anyone recommend the removal of blatant bad Oracle behaviors? Or if all looks well a good tool to get some index tuning advisory? The Oracle Enterprise Manager won’t parse this query to provide any recommendations.
Additional Performance Information captured from trace and formatted
through TKPROF
Parse: Count(1) | CPU(0.04) | Elapsed(0.04) | Disk(0) | Query(852) | Current(0) | Rows(0)
Execute: Count(1) | CPU(0.00) | Elapsed(0.00) | Disk(0) | Query(0) | Current(0) | Rows(0)
Fetch: Count(1) | CPU(9.64) | Elapsed(14.50) | Disk(34578) | Query(35610) | Current(4) | Rows(4)
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 1165Rows Row Source Operation
4 HASH JOIN OUTER (cr=38069 pr=34578 pw=0 time=19208475 us) 2 COLLECTION ITERATOR PICKLER FETCH REPORT_INTERVAL_SEQUENCE_UDF (cr=97 pr=0 > pw=0 time=13766 us) 4 VIEW (cr=37972 pr=34578 pw=0 time=19194353 us) 4 HASH GROUP BY (cr=37972 pr=34578 pw=0 time=19194329 us)60650 FILTER (cr=37972 pr=34578 pw=0 time=19673947 us)
60650 NESTED LOOPS (cr=37972 pr=34578 pw=0 time=19431329 us)
60650 HASH JOIN (cr=37941 pr=34578 pw=0 time=5294908 us)
4 COLLECTION ITERATOR PICKLER FETCH REPORT_MACHINEINFO_GETT_UDF (cr=2331 pr=0 pw=0 time=212033 us)
60650 TABLE ACCESS FULL ELS_STATISTIC_ENTRY (cr=35610 pr=34578 pw=0
time=4416705 us)
60650 COLLECTION ITERATOR PICKLER FETCH REPORT_INTERVAL_GETT_UDF (cr=31 pr=0 > pw=0 time=13372794 us)
SELECT
TimeInterval,
stats.During,
stats.Name,
stats.cnt
FROM
TABLE (GET_INTERVAL_SEQUENCE_UDF(
TO_TIMESTAMP ('07/15/2011','mm/dd/yyyy')
,TO_TIMESTAMP ('07/20/2011','mm/dd/yyyy')
,2)) dtRange
LEFT JOIN
(
SELECT
i.During
, mi.Name
, SUM (CAST (VALUE_NUMERIC AS INT)) cnt
FROM
statistics se
JOIN TABLE (Get_Context_Info_udf ()) mi
ON (se.Context_ID = mi.Context_ID)
CROSS JOIN TABLE (Interval_GetT (se.EntryDate, 2)) i
WHERE
StatisticTypeID = HEXTORAW ('6CF933B091AE46FEA7F56BE96308190F')
AND EntryDate < TO_TIMESTAMP ('07/20/2011','mm/dd/yyyy')
AND EntryDate > TO_TIMESTAMP ('07/15/2011', 'mm/dd/yyyy')
GROUP BY
i.During
, mi.Name
) stats ON dtRange.TimeInterval = stats.TimeInterval
The following are for reference in the aforementioned query.
CREATE OR REPLACE FUNCTION Interval_GetT(datestamp IN timestamp, timeInterval IN int)
RETURN TReportIntervalList AS vResult TReportIntervalList;
BEGIN
SELECT TReportInterval(
CASE timeInterval
WHEN 1 THEN TO_CHAR(datestamp, 'YYYY-MM-DD HH24')
WHEN 2 THEN TO_CHAR(datestamp, 'YYYY-MM-DD')
WHEN 3 THEN TO_CHAR(datestamp, 'YYYY-WW')
END
)
BULK COLLECT INTO vResult
FROM Dual WHERE ROWNUM = 1;
RETURN vResult;
END;
CREATE OR REPLACE FUNCTION GET_INTERVAL_SEQUENCE_UDF(
startTime IN timestamp,
endTime IN timestamp,
inputInterval IN int)
RETURN t_interval_list_table AS intervalList t_interval_list_table := t_interval_list_table();
BEGIN
SELECT
CASE inputInterval
WHEN 1 THEN (t_interval(REPORT_Interval_Get_udf((startTime + ((ROWNUM-1) * 1/24)), inputInterval))) --Hour
WHEN 2 THEN (t_interval(REPORT_Interval_Get_udf((startTime + (ROWNUM-1)), inputInterval))) --Day
WHEN 3 THEN (t_interval(REPORT_Interval_Get_udf((startTime + ((ROWNUM-1)*7)), inputInterval))) --Week
END
BULK COLLECT INTO intervalList
FROM dual CONNECT BY LEVEL <= (CASE inputInterval
WHEN 1 THEN CAST(CEIL(((TRUNC(endTime, 'HH') - TRUNC(startTime, 'HH')) * 24)) AS INT)
WHEN 2 THEN CAST(TRUNC(endTime, 'DD') - TRUNC(startTime, 'DD') AS INT)
WHEN 3 THEN CAST(CEIL(((TRUNC(endTime, 'DD') - TRUNC(startTime, 'DD')) )/7) AS INT)
END);
RETURN intervalList;
END GET_INTERVAL_SEQUENCE_UDF;
CREATE OR REPLACE FUNCTION Get_Context_Info_udf
RETURN TTRFRMENGMACHINEINFOLIST AS vResult TTRFRMENGMACHINEINFOLIST;
BEGIN
SELECT TTrfrmEngMachineInfo(ch.Context_ID, mac.Name)
BULK COLLECT INTO vResult
FROM
a ch
INNER JOIN
b cxm ON ch.CONTX_MACHINE_ID = cxm.CONTX_MACHINE_ID
INNER JOIN
c mac ON cxm.MACHINE_ID = mac.MACHINE_ID
INNER JOIN
d ic ON mac.MACHINE_ID = ic.MACHINE_ID
WHERE
ic.ONFIGURABLE_ENTITY_ID = HEXTORAW(Format_Guid_udf('11111111-FAE9-47A1-91A9-60A53E9660FE'))
AND mac.IS_DELETED = 'N'
AND ic.IS_DELETED = 'N';
RETURN vResult;
END;
You can investigate where time is being spent and the execution plan Oracle chooses by following the advice in this OTN thread
Regards,
Rob.