У меня есть запрос, который производит 529 032 строки, которые я сохраняю в таблицу с именем EFOT_DISTINCT_COMBOS
.
(Раньше это было материализованное представление, но наши администраторы сервера рекомендовали вместо этого использовать простые таблицы, и вручную "refre sh" данных из запросов, используя хранимые процедуры.)
Что мне нужно сделать с этим дальше, это CROSS JOIN
, который сталкивается с серьезной проблемой ... сервер блокируется и просто зависает, не выполняя никакой работы ... (блокировка кэша библиотеки?)
Похоже, мне нужно заменить CROSS JOIN
в моем запросе и найти лучший способ написать этот запрос.
Этот запрос выглядит как кошмар, но на самом деле он НАМНОГО проще, чем кажется - он просто вычисляет некоторые простые условные итоги.
(Месяц go Я пытался использовать для этого оконные функции, но оконные функции что-то сломалось (я не помню, что именно), поэтому мне пришлось по какой-то причине вернуться к простым агрегатам.)
Таблица, которую мы CROSS JOIN
используем, называется SNAPSHOTS
, и это очень короткая таблица, содержащая только 44 строки (в конечном итоге она не будет намного больше, возможно, максимум 80-100 строк).
529 032 x 44 = 23 277 408 строк, созданных этим CROSS JOIN
.
I попытался уменьшить этот след, добавив HAVING COUNT(ef.TIMESTAMP) > 0
внизу, который удаляет, вероятно, 75% результатов (которые мне не обязательно нужны).
Это определенно помогает, но запрос все равно не выполняется на сервере .
SELECT
ss.TIMESTAMP,
ss.TIMESTAMP_DATE,
fc.FISCAL_QUARTER,
fc.LOB,
fc.FREQUENCY,
fc.EDGE_VP,
fc.EDGE_RM,
fc.EDGE_ASM,
NVL(SUM(ef.PIPELINE),0) AS PIPELINE,
NVL(SUM(ef.BEST),0) AS BEST,
NVL(SUM(ef.FORECAST),0) AS FORECAST,
NVL(SUM(ef.CLOSED),0) AS CLOSED,
CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PIPELINE_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_PIPELINE_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_PIPELINE_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_PIPELINE_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_PIPELINE_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_PIPELINE_DIFF),0) END AS PIPELINE_CHANGE,
CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.BEST_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_BEST_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_BEST_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_BEST_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_BEST_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_BEST_DIFF),0) END AS BEST_CHANGE,
CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.FORECAST_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_FORECAST_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_FORECAST_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_FORECAST_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_FORECAST_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_FORECAST_DIFF),0) END AS FORECAST_CHANGE,
CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.CLOSED_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_CLOSED_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_CLOSED_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_CLOSED_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_CLOSED_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_CLOSED_DIFF),0) END AS CLOSED_CHANGE,
CASE WHEN CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_PIPELINE),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_PIPELINE),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_PIPELINE),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_PIPELINE),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_PIPELINE),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_PIPELINE),0) END = 0 THEN 0
ELSE 100 * CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PIPELINE_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_PIPELINE_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_PIPELINE_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_PIPELINE_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_PIPELINE_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_PIPELINE_DIFF),0) END
/ CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_PIPELINE),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_PIPELINE),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_PIPELINE),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_PIPELINE),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_PIPELINE),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_PIPELINE),0) END END AS PIPELINE_PERCENT_CHANGE,
CASE WHEN CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_BEST),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_BEST),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_BEST),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_BEST),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_BEST),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_BEST),0) END = 0 THEN 0
ELSE 100 * CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.BEST_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_BEST_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_BEST_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_BEST_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_BEST_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_BEST_DIFF),0) END
/ CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_BEST),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_BEST),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_BEST),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_BEST),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_BEST),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_BEST),0) END END AS BEST_PERCENT_CHANGE,
CASE WHEN CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_FORECAST),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_FORECAST),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_FORECAST),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_FORECAST),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_FORECAST),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_FORECAST),0) END = 0 THEN 0
ELSE 100 * CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.FORECAST_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_FORECAST_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_FORECAST_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_FORECAST_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_FORECAST_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_FORECAST_DIFF),0) END
/ CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_FORECAST),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_FORECAST),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_FORECAST),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_FORECAST),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_FORECAST),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_FORECAST),0) END END AS FORECAST_PERCENT_CHANGE,
CASE WHEN CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_CLOSED),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_CLOSED),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_CLOSED),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_CLOSED),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_CLOSED),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_CLOSED),0) END = 0 THEN 0
ELSE 100 * CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.CLOSED_DIFF),0)
WHEN 'D' THEN NVL(SUM(ef.D_CLOSED_DIFF),0)
WHEN 'W' THEN NVL(SUM(ef.W_CLOSED_DIFF),0)
WHEN 'M' THEN NVL(SUM(ef.M_CLOSED_DIFF),0)
WHEN 'Q' THEN NVL(SUM(ef.Q_CLOSED_DIFF),0)
WHEN 'Y' THEN NVL(SUM(ef.Y_CLOSED_DIFF),0) END
/ CASE fc.FREQUENCY WHEN '%' THEN NVL(SUM(ef.PREV_CLOSED),0)
WHEN 'D' THEN NVL(SUM(ef.PREV_D_CLOSED),0)
WHEN 'W' THEN NVL(SUM(ef.PREV_W_CLOSED),0)
WHEN 'M' THEN NVL(SUM(ef.PREV_M_CLOSED),0)
WHEN 'Q' THEN NVL(SUM(ef.PREV_Q_CLOSED),0)
WHEN 'Y' THEN NVL(SUM(ef.PREV_Y_CLOSED),0) END END AS CLOSED_PERCENT_CHANGE -- ,
-- COUNT(ef.TIMESTAMP) AS DEAL_SS_COUNT
FROM EFOT_DISTINCT_COMBOS fc
CROSS JOIN SNAPSHOTS ss
LEFT JOIN EDGE_FORECAST_OVER_TIME ef
ON ef.TIMESTAMP = ss.TIMESTAMP
AND ef.fq_selection = NVL(fc.FISCAL_QUARTER,'%')
AND ef.lob_selection = NVL(fc.LOB,'%')
AND ((fc.FREQUENCY = 'D' AND ef.FREQUENCY in('D', 'W', 'M', 'Q', 'Y') AND ef.TIMESTAMP_DATE >= TRUNC(LOCALTIMESTAMP) - INTERVAL '1' MONTH)
OR (fc.FREQUENCY = 'W' AND TO_CHAR(ef.TIMESTAMP, 'fmDAY') = 'MONDAY' AND ef.TIMESTAMP_DATE >= TRUNC(LOCALTIMESTAMP) - INTERVAL '3' MONTH)
OR (fc.FREQUENCY = 'M' AND ef.FREQUENCY in('M', 'Q', 'Y') AND ef.TIMESTAMP_DATE >= TRUNC(LOCALTIMESTAMP) - INTERVAL '1' YEAR)
OR (fc.FREQUENCY = 'Q' AND ef.FREQUENCY in('Q', 'Y'))
OR ef.FREQUENCY LIKE NVL(fc.FREQUENCY,'%'))
AND ef.EDGE_VP LIKE NVL(fc.EDGE_VP,'%')
AND ef.EDGE_RM LIKE NVL(fc.EDGE_RM,'%')
AND ef.EDGE_ASM LIKE NVL(fc.EDGE_ASM,'%')
WHERE ss.TABLE_NAME = 'EDGE_FORECAST'
GROUP BY ss.TIMESTAMP ,
ss.TIMESTAMP_DATE ,
fc.FISCAL_QUARTER ,
fc.LOB ,
fc.FREQUENCY ,
fc.EDGE_VP ,
fc.EDGE_RM ,
fc.EDGE_ASM
HAVING COUNT(ef.TIMESTAMP) > 0;
Затем попытался разделить этот запрос на два запроса.
- Первый запрос для выполнения
CROSS JOIN
и создания 23 277 408 строк с 0 для общего числа столбцов. - 2-й запрос к
UPDATE
всем 23 277 408 строкам и вычислению значений для итоговых столбцов.
1-й запрос работал отлично, выполнялся примерно за 12 минут.
Но 2-й запрос стал еще более сложным, он выполнялся почти 6 часов и в конце концов завершился ошибкой:
ORA-01555: snapshot too old
.
Есть ли лучший способ написать это, чтобы сервер действительно мог получить работа делает ne?
Этот запрос раньше работал до того, как мы добавили все фильтры LOB
(я предполагаю, что один дополнительный фильтр переместил его через край, с точки зрения сложности плана выполнения).
(PasteBin потому что эти запросы слишком длинные для StackOverflow.)
1-й запрос:
2-й запрос