改善严重依赖于日期的视图的性能

时间:2012-10-30 17:26:48

标签: sql sql-server sql-server-2008 tsql

此视图需要我执行HOURS:

USE [SalesDWH]
GO

/****** Object:  View [dbo].[FirstLastEstablished]    Script Date: 10/29/2012 15:12:47 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

ALTER view [dbo].[FirstLastEstablished] as


with cte_min as(

select 
      a.client_id
      ,a.specimen_source
      ,a.received_date
from
      millennium_dw_dev..F_ACCESSION_DAILY a
join
            (select distinct
                  f.client_id
                  ,f.received_date
                  ,f.accession_daily_key
            from 
                  millennium_dw_dev..F_ACCESSION_DAILY f
            join 
                  (select CLIENT_ID, MIN(received_date) MinRecDate
                  from millennium_dw_dev..F_ACCESSION_DAILY
                  group by CLIENT_ID) i
            on f.CLIENT_ID=i.CLIENT_ID
            and f.RECEIVED_DATE=i.MinRecDate) b
on    
      a.ACCESSION_DAILY_KEY=b.ACCESSION_DAILY_KEY 

)

,
cte_max as 
(

select 
      a.client_id
      ,a.specimen_source
      ,a.received_date
from
      millennium_dw_dev..F_ACCESSION_DAILY a
join
            (select distinct
                  f.client_id
                  ,f.received_date
                  ,f.accession_daily_key
            from 
                  millennium_dw_dev..F_ACCESSION_DAILY f
            join 
                  (select CLIENT_ID, max(received_date) MaxRecDate
                  from millennium_dw_dev..F_ACCESSION_DAILY
                  group by CLIENT_ID) i
            on f.CLIENT_ID=i.CLIENT_ID
            and f.RECEIVED_DATE=i.MaxRecDate) b
on    
      a.ACCESSION_DAILY_KEY=b.ACCESSION_DAILY_KEY 

)
,


cte_est as

(

select distinct client_id, MLIS_DATE_ESTABLISHED
from millennium_dw_dev..D_CLIENT
where REC_ACTIVE_FLG=1
and MLIS_DATE_ESTABLISHED is not null
)

,

mainQuery as(
select distinct
      f.client_id
      ,cmin.specimen_source first_specimen_source
      ,cmin.received_date first_received
      ,cmax.specimen_source last_specimen_source
      ,cmax.received_date last_received
      ,cest.MLIS_DATE_ESTABLISHED MLIS_DATE_ESTABLISHED
from millennium_dw_dev..F_ACCESSION_DAILY f
left join cte_max cmax
on cmax.CLIENT_ID=f.CLIENT_ID
left join cte_min cmin
on cmin.CLIENT_ID=f.CLIENT_ID
left join cte_est cest
on cest.CLIENT_ID=f.CLIENT_ID
)
,
DateDifferences
as

(
SELECT
client_id,
   (DATEDIFF(dd, MLIS_DATE_ESTABLISHED,first_received) + 1)
  -(DATEDIFF(wk, MLIS_DATE_ESTABLISHED,first_received) * 2)
  -(CASE WHEN DATENAME(dw, first_received) = 'Sunday' THEN 1 ELSE 0 END)
  -(CASE WHEN DATENAME(dw, MLIS_DATE_ESTABLISHED) = 'Saturday' THEN 1 ELSE 0 END)
 -(case when cast('01/01/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('05/26/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('07/04/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('09/01/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('11/27/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('12/25/2008 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('01/01/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('05/25/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('07/03/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('09/07/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('11/26/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('12/25/2009 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('01/01/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('05/31/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('07/05/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('09/06/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('11/25/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('12/24/2010 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('01/03/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('05/30/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('07/04/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('09/05/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('11/24/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('12/26/2011 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('01/02/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('05/28/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('07/04/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('09/03/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('11/22/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)
-(case when cast('12/25/2012 ' as date) between MLIS_DATE_ESTABLISHED and first_received then 1 else 0 end)


   DifferenceExcludingWeekends
  from
  mainQuery
)
,
Territory 
as
(
select distinct c.client_id,c.MLIS_TERRITORY,s.REGION_NAME
from millennium_dw_dev..D_CLIENT c
left join millennium_dw_dev..D_SALES_HIERARCHY s
on s.TERRITORY_NAME=c.MLIS_TERRITORY
where c.REC_ACTIVE_FLG=1
and s.REC_ACTIVE_FLG=1

)

select mainQuery.*,d.DifferenceExcludingWeekends,Territory.MLIS_TERRITORY,Territory.REGION_NAME
from mainQuery
left join DateDifferences d
on mainQuery.CLIENT_ID=d.CLIENT_ID
left join Territory
on mainQuery.CLIENT_ID=Territory.CLIENT_ID

GO

我对此进行了sql server数据库调优,并创建了所有推荐的索引。再次执行视图15分钟后,我停了下来。

您是否可以向我提出有关我的查询的更明显的事情,以便更多地优化它并缩短执行时间?

1 个答案:

答案 0 :(得分:1)

我认为你没有利用CTE的“共同”方面。首先尝试将表:millennium_dw_dev..F_ACCESSION_DAILY放入CTE中(如果可能,仅包含必要的字段和记录)。你的代码从这个表中选择了8次(这个表是本地的吗?)。

你的其他一些CTE被引用一次,但我可以看到一个是如何构建另一个。是的,他们可以帮助将复杂的查询分解为更多可管理的部分,但它可能对性能没有帮助。

此处的性能可能不是问题,但将这些硬编码的日期纳入某种假日/休息日表也会有所帮助。拥有date table可能是比所有这些计算更好的路线。

根据数据的大小,将其放入存储过程将允许使用索引临时表。