我有一个执行不佳的查询。查询的一个方面是在表值函数上使用交叉联接,老实说,我是在模仿我在函数上使用 CROSS APPLY 以避免使用标量函数调用的 TSQL 行为。这是 Oracle 中的不良行为吗?
我遇到的主要问题是 Oracle Tuning Advisor 不会解析我的查询,因此我还无法研究索引优化。通常我不会发布这么多代码,但我怀疑可能导致问题的是我的查询而不是表优化。
statistics se表确实是唯一一个拥有超过4,000,000条记录的表。任何人都可以建议删除公然不良的 Oracle 行为吗?或者,如果一切看起来都很好,那么它是获得一些索引调整建议的好工具吗? Oracle Enterprise Manager 不会解析此查询以提供任何建议。
从跟踪中捕获并格式化的附加性能信息 通过 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: 1165
Rows 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;
最佳答案
您可以按照 this OTN thread 中的建议调查时间花费在何处以及 Oracle 选择的执行计划。
问候,
罗布。
关于选择与表值函数连接中的 Oracle 标量函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6768388/