выбор объединения занимает много времени для выполнения - PullRequest
0 голосов
/ 24 марта 2020

Привет, у меня есть пять операторов выбора, и я использую объединение, чтобы объединить их. Но моя проблема в том, что выполнение занимает 25 секунд. Есть ли способ сделать это выполнение более быстрым?

Select Case when sum(COUNT)is null then 0 end as count,'Exeed45' as tittle from VW_BREAK_TIME_EXCEEDING45
where date_time >=  trunc(To_date('2020-03-01','YYYY-MM-DD')) and date_time <= trunc(to_date('2020-03-31','YYYY-MM-DD'))
union
Select Case when sum(CNT) is null then 0 end as count,'Double' as tittle from VW_BREAK_TIME_DOUBLEBREAK
where date_time >=  trunc(To_date('2020-03-01','YYYY-MM-DD')) and date_time <= trunc(to_date('2020-03-31','YYYY-MM-DD'))
union
Select sum(COUNT)as count,'Frequent' as tittle from VW_BREAK_TIME_FREQUENTBREAK
where date_time >=  trunc(To_date('2020-03-01','YYYY-MM-DD')) and date_time < =trunc(to_date('2020-03-31','YYYY-MM-DD'))
union
Select Count(REMARKS)as count,'LateProd' as tittle from VW_BREAK_TIME_PROD_TIMEIN
where date_time >=  trunc(To_date('2020-03-01','YYYY-MM-DD')) and date_time <= trunc(to_date('2020-03-31','YYYY-MM-DD'))
and REMARKS = 'LATE'
union
Select Count(REMARKS)as count,'EarlyOut' as tittle from VW_BREAK_TIME_PROD_TIMEOUT
where date_time >=  trunc(To_date('2020-03-01','YYYY-MM-DD')) and date_time <= trunc(to_date('2020-03-31','YYYY-MM-DD'))
and REMARKS = 'Early Out';

Надеюсь, я скажу это ясно. Заранее благодарю.

Ответы [ 2 ]

0 голосов
/ 24 марта 2020

Прежде всего UNION - это дорогостоящая операция, которая не только склеивает два результата вместе, но и ищет дубликаты для удаления. Вместо этого вы хотите UNION ALL, который выполняет только склеивание, потому что ваши запросы не дают дубликатов (поскольку tittle отличается).

Тогда в столбце date_time должны быть индексы плюс сумма столбец для каждой таблицы:

create index idx1 on vw_break_time_exceeding45 (date_time, "COUNT");
create index idx2 on VW_BREAK_TIME_DOUBLEBREAK (date_time, cnt);
create index idx3 on VW_BREAK_TIME_FREQUENTBREAK (date_time, "COUNT");
create index idx4 on VW_BREAK_TIME_PROD_TIMEIN (date_time, remarks);
create index idx5 on VW_BREAK_TIME_PROD_TIMEOUT (date_time, remarks);

Я бы также добавил следующие индексы для случая remarks более избирательно, чем date_time. (Вы всегда можете проверить план объяснения запроса и удалить индексы, которые не используются.)

create index idx6 on VW_BREAK_TIME_PROD_TIMEIN (remarks, date_time);
create index idx7 on VW_BREAK_TIME_PROD_TIMEOUT (remarks, date_time);

Вы должны не Count(REMARKS), а COUNT(*), поскольку вы хотите только считать строки; REMARKS никогда не может быть нулевым из-за вашего условия WHERE. Но я предполагаю, что оптимизатор видит это, и вы не получаете скорость, только удобочитаемость.

Два примечания:

  1. Литерал даты выглядит так: DATE '2020-03-31'. Используйте их вместо манипуляции со строками.
  2. "COUNT" - зарезервированное SQL слово. Я бы не использовал его для названия столбца.
0 голосов
/ 24 марта 2020

Возможно.

  • UNION вернет уникальных строк; если возможно, измените значение на UNION ALL
  • , например, 2020-03-01 бесполезно; что именно вы думаете, вы будете усекать?
  • вместо преобразования строки в дату (с использованием to_date) и (предыдущего замечания) ее усечения, используйте литерал даты (который всегда в формате yyyy-mm-dd), например,

    where date_time >= date '2020-03-01'
    
  • может помочь индексирование столбца date_time (а также remarks); посмотрите, что объясняет план объяснения

  • вы собирали статистику по этим таблицам? Если нет, сделайте это
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...