查询包括子查询和分组慢于预期

时间:2015-05-14 11:48:12

标签: sql sql-server tsql sql-server-2005 subquery

下面的整个查询运行速度非常慢。

子查询查询[别名Stage_1]只需1.37分钟就可以返回9514条记录,但整个查询需要20分钟,返回2606条记录。

我可以使用#temp表来保存子查询以提高性能,但我不愿意。

查询概述是表WeeklySpace内部连接到SpaceblockName_SID上的Spaceblock_Name_to_PG表,这会在WeeklySpace中减少结果并包含PG_Code,其结果在WeeklySpace中。然后,WeeklySpace在3个字段中全部加入Sales_PG_Wk。 where子句聚焦结果,可以更改。然后将子查询的结果相加。由于使用了group by和sum over,你不能在子查询中进行最后的求和。

我认为这个问题是由于在最后一次总结期间在小组中重复计算子查询。 SpaceblockName_SID字段似乎也与导致问题有关,因为没有它,子查询中的group by的运行时间不受影响。

我已阅读大量建议,尝试全部解决问题。

这些包括;

  • 使用Order by添加TOP 2147483647以强制中间 在子查询和使用CTE中实现。
  • 在stage_1之后添加联接。
  • 将一个int中的SpaceblockName_SID转换为varchar然后再转发

子查询和整个查询的执行计划(分为两部分,如代码所示)看起来类似。成本是在我期望的全外加入(哈希匹配)附近。

查询正在T-SQL 2005上运行。

任何帮助都非常感谢!

select 
    Cost_centre
    , Fin_week
    , SpaceblockName_SID
    , sum(Propor_rep_SRV) as Total_SpaceblockName_SID_SRV
from
(
        select  
            coalesce(space_side.fin_week , sales_side.fin_week) as Fin_week 
           ,coalesce(space_side.cost_centre , sales_side.cost_Centre) as Cost_centre 
           ,space_side.SpaceblockName_SID
           ,case
                when  space_side.SpaceblockName_SID is null
                    then sales_side.SalesExVAT
                else  sum(space_side.TLM)
                                /nullif(sum (sum(space_side.TLM) ) over (partition by coalesce(space_side.fin_week , sales_side.fin_week)
                                                                                            , coalesce(space_side.cost_centre , sales_side.cost_Centre)  
                                                                                            , coalesce( Spaceblock_Name_to_PG.PG_Code, sales_side.PG_Code)) ,0)*sales_side.SalesExVAT 
            end as Propor_rep_SRV
        from
            WeeklySpace as space_side
        INNER JOIN
            Spaceblock_Name_to_PG 
                ON space_side.SpaceblockName_SID = Spaceblock_Name_to_PG.SpaceblockName_SID 
                    and Spaceblock_Name_to_PG.PG_Code < 10000
        full outer join
            sales_pg_wk as sales_side
                on  space_side.fin_week = sales_side.fin_week 
                    and space_side.Cost_Centre = sales_side.Cost_Centre 
                    and Spaceblock_Name_to_PG.PG_code = sales_side.pg_code
        where 
            coalesce(space_side.fin_week, sales_side.fin_week) between 201538 and 201550
                and
            coalesce(space_side.cost_centre, sales_side.cost_Centre) in (3, 2800)
        group by  
            coalesce(space_side.fin_week, sales_side.fin_week)  
           ,coalesce(space_side.cost_centre, sales_side.cost_Centre)  
           ,coalesce( Spaceblock_Name_to_PG.PG_Code, sales_side.PG_Code)  
           ,sales_side.SalesExVAT
           ,space_side.SpaceblockName_SID
) as stage_1
group by 
    Cost_centre
    , Fin_week
    , SpaceblockName_SID

执行计划左手边 Execution plan left hand side

执行计划右侧 Execution plan left hand side

2 个答案:

答案 0 :(得分:0)

您没有提到在您在查询中使用的那些列上创建或不创建索引。如果没有,则创建并检查查询的性能

答案 1 :(得分:0)

在看着你的逻辑时,我认为你用一个UNION分成两个 一个是Spaceblock_Name_to_PG.PG_Code&lt; 10000和另一个与Spaceblock_Name_to_PG.PG_Code&gt; = 10000

考虑这种变化 如果可能正在做一堆你将要抛出的联接

window.addEventListener