У меня есть запрос, который работает плохо. Одним из аспектов запроса является использование перекрестного соединения для табличной функции, и, честно говоря, я имитировал свое поведение TSQL при использовании CROSS APPLY для функции, чтобы избежать использования скалярного вызова функции. Это плохое поведение в Oracle?
Основная проблема, с которой я сталкиваюсь, заключается в том, что Oracle Tuning Advisor не будет анализировать мой запрос, поэтому я пока не могу исследовать оптимизации индекса. Обычно я не публикую такого большого количества кода, но я подозреваю, что проблема может быть вызвана не столько оптимизацией таблиц, сколько моим запросом.
Таблица se статистики на самом деле является единственной таблицей с более чем 4 000 000 записей. Кто-нибудь может порекомендовать устранение вопиющего плохого поведения Oracle? Или, если все выглядит хорошо, хороший инструмент для получения рекомендаций по настройке индекса? Oracle Enterprise Manager не будет анализировать этот запрос для предоставления каких-либо рекомендаций.
Дополнительная информация о производительности, полученная из трассировки и отформатированная
через ТКПРОФ
Parse: Count (1) | Процессор (0,04) | Прошло (0,04) | Диск (0) | Запрос (852) | Текущий (0) | Ряды (0)
Выполнить: Количество (1) | CPU (0,00) | Прошло (0,00) | Диск (0) | Запрос (0) | Текущий (0) | Ряды (0)
Выборка: Количество (1) | CPU (9,64) | Прошло (14.50) | Диск (34578) | Запрос (35610) | Текущий (4) | Ряды (4)
Пропуски в кеше библиотеки при разборе: 1
Режим оптимизатора: ALL_ROWS
Парсинг ID пользователя: 1165
Операция с источником строк Rows
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 ФИЛЬТР (cr = 37972 pr = 34578 pw = 0 раз = 19673947 us)
60650 NESTED LOOPS (cr = 37972 pr = 34578 pw = 0 время = 19431329 us)
60650 HASH JOIN (cr = 37941 pr = 34578 pw = 0 время = 5294908 us)
4 СБОР ИЗБИРАТЕЛЕЙ ИТЕРАТОРА СБОРА REPORT_MACHINEINFO_GETT_UDF (cr = 2331 pr = 0 pw = 0 time = 212033 us)
60650 ТАБЛИЦА ДОСТУПА ПОЛНОГО ELS_STATISTIC_ENTRY (cr = 35610 pr = 34578 pw = 0
время = 4416705 мес)
60650 ПАРАМЕТРЫ СБОРА ИТЕРАТОРА КОЛЛЕКЦИИ REPORT_INTERVAL_GETT_UDF (cr = 31 pr = 0> pw = 0 время = 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;