繁体   English   中英

如何优化此SQL查询的性能

[英]How to optimize performance of this SQL query

我需要找到每一天的年龄,但是我需要在一个查询中找到所有以前的日期。 因此,我使用了以下查询:

 select trunc(sysdate) - level + 1 **DATE**
 ,trunc(sysdate) - level + 1 - created_date **AGE**   from items
connect by trunc(sysdate) - level + 1 - created_date > 0

我得到的输出(日期和年龄)正确无误:

 DATE               AGE
   --------- ----------
   6-JUL-15          22
   5-JUL-15          21
   4-JUL-15          20
   3-JUL-15          19
   2-JUL-15          18
   1-JUL-15          17
   30-JUN-15         16
   29-JUN-15         15
   28-JUN-15         14
   27-JUN-15         13
   26-JUN-15         12
   25-JUN-15         11
   24-JUN-15         10    

现在,我需要计算每天的平均年龄 ,因此在以下查询中添加了平均年龄

  select trunc(sysdate) - level + 1 **DATE** ,
    **avg**(trunc(sysdate) - level + 1 - created_date )** AVERAGE_AGE**   
    from items
    connect by trunc(sysdate) - level + 1 - created_date > 0
    group by trunc(sysdate) - level + 1

这个查询正确吗? 当我向该查询添加聚合函数(avg)时,它需要1个小时来检索数据。 当我从查询中删除平均值函数时,它会在2秒内给出结果吗? 在不影响性能的情况下计算平均值的可能解决方案是什么?

抱歉,我从未使用过Oracle,因此即使我尝试阅读doc以获得语法详细信息,也可能会出现一些错误:

您说此查询在2秒内完成了工作:

select trunc(sysdate) - level + 1 **DATE**
 ,trunc(sysdate) - level + 1 - created_date **AGE**   from items
connect by trunc(sysdate) - level + 1 - created_date > 0

因此,我们将保留它并从中进行view

CREATE OR REPLACE VIEW my_view AS
(select 
    trunc(sysdate) - level + 1 **DATE** AS "date_col",
    trunc(sysdate) - level + 1 - created_date **AGE** AS "age_col"  
from items
connect by trunc(sysdate) - level + 1 - created_date > 0);

但是通过执行以下操作,可能我们可以获得一些多余的计算:

CREATE OR REPLACE VIEW distinct_dates AS 
(
SELECT DISTINCT trunc(sysdate) - level + 1 AS "date_distinct"
from items
connect by trunc(sysdate) - level + 1 - created_date > 0
);

CREATE OR REPLACE VIEW my_view AS
(select 
    date_distinct AS "date_col",
    date_distinct - created_date AS "age_col"  
from distinct_dates
connect by date_distinct - created_date > 0);

我为什么要这么做? 因为看来问题出在聚合上,所以恐怕视图实际上是在您的代码中多次计算的。 下一步只是在视图上进行计算:

select 
    date_col ,
    AVG(age_col)
from my_view
group by date_col;

最后,最终代码将是:

CREATE OR REPLACE VIEW distinct_dates AS 
(
SELECT DISTINCT trunc(sysdate) - level + 1 AS "date_distinct"
from items
connect by trunc(sysdate) - level + 1 - created_date > 0
);

CREATE OR REPLACE VIEW my_view AS
(select 
    date_distinct AS "date_col",
    date_distinct - created_date AS "age_col"  
from distinct_dates
connect by date_distinct - created_date > 0);

select 
    date_col ,
    AVG(age_col)
from my_view
group by date_col;

或者,如果它不起作用:

CREATE OR REPLACE VIEW my_view AS
(select 
    trunc(sysdate) - level + 1 **DATE** AS "date_col",
    trunc(sysdate) - level + 1 - created_date **AGE** AS "age_col"  
from items
connect by trunc(sysdate) - level + 1 - created_date > 0);


select 
    date_col ,
    AVG(age_col)
from my_view
group by date_col;

修改后的查询:

select tdate, avg(trunc(tdate)-created_date) AVG_AGE
  from (
    select trunc(sysdate) - level + 1 tdate
      from (select min(created_date) dt from items)
      connect by trunc(sysdate) - level + 1 - dt > 0 ) dates
  join items on dates.tdate > items.created_date
  group by tdate order by tdate

SQLFiddle演示

假设您只有两行,日期分别为“ 2015-06-01”和“ 2015-06-20”。 根据我的计算,您的层次查询为它们生成了1376254行,这可能不是您想要的,它应该生成51行(35 + 16)。 这就是为什么要花这么长时间的原因,因为表items更多行输出呈指数增长。

您可以通过添加某种计数器(由rownumrow_number生成),然后添加and prior rn = rn connect by子句来修改查询,但是上面显示的查询使查询更简单。 我在SQLFiddle中添加了第二个查询以比较结果,两者均产生相同的输出。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM