联合选择需要很长时间才能执行

时间:2020-03-24 07:22:00

标签: sql oracle oracle11g

嗨,我有这五个select语句,我使用union来组合它们。 但是我的问题是执行需要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 :(得分:0)

也许。

  • UNION将返回 unique 行;如果可能,请将其更改为UNION ALL
  • 截断例如2020-03-01没有用;您认为您将截断什么?
  • 而不是将字符串转换为日期(使用to_date)和(先前的注释)将其截断,而使用日期文字(始终为yyyy-mm-dd格式),例如

    where date_time >= date '2020-03-01'
    
  • 索引date_time列可能会有所帮助(以及remarks);看看解释计划怎么说

  • 您是否收集了这些表的统计信息?如果没有,那就这么做

答案 1 :(得分:0)

首先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);

remarksdate_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永远不能为null。但是我猜想优化器会看到这一点,而您不会提高速度,只会提高可读性。

两个注意事项:

  1. 日期文字看起来像这样:DATE '2020-03-31'。使用这些代替字符串操作。
  2. "COUNT"是保留的SQL字。我不会将它用作列名。
相关问题