-1

我有一个针对特定参数运行非常缓慢的存储过程。

存储过程返回一个数据集。

我将存储过程转换为视图。我声明了相同的参数和值,它会在几秒钟内返回数据集。

存储过程需要五分钟。

我将问题缩小到存储过程中的特定子查询。删除子查询使存储过程能够立即返回数据。我将子查询转换为临时表并加入临时表而不是子查询,现在存储过程在几秒钟内返回数据。

初始视图与存储过程测试中的操作相同。视图的执行方式有什么不同吗?

这是使用新临时表的存储过程。原来的子查询被注释掉了:

 (@JCCo bCompany,  
  @BegContract bContract ='', 
  @EndContract bContract ='zzzzzzzzzz', 
  @ThruMth bDate,
  @PM int = 0,
  @LabCTs varchar(10)=null,
  @MatCTs varchar(10)=null,
  @BegDept varchar(10) ='', 
  @EndDept varchar(10) ='zzzzzzzzzz')


With Recompile
as
--move the dates into a temp table
Select JCJM.JCCo, JCJM.Contract, JCCD.Job,
                        LastLaborDate=max(Case when JCTransType='PR' and (CostType between 2 and 3) then ActualDate else null end),
                        LastProjCostDate=max(Case when JCTransType='PF' then ActualDate else null end)
                    INTO #DATES
                   From JCCD JCCD with(NoLock)
                   Join JCJM JCJM with(nolock) on JCJM.JCCo=JCCD.JCCo and JCJM.Job=JCCD.Job
                    where (JCTransType='PR' or JCTransType='PF') and JCCD.JCCo=@JCCo and JCCD.Mth<=@ThruMth 
                            and JCJM.Contract Between @BegContract and @EndContract
                    group by JCJM.JCCo,JCJM.Contract,JCCD.Job
      -- ) as Dates on j.JCCo=Dates.JCCo and j.Contract=Dates.Contract and j.Job=Dates.Job




Select  JCCD.JCCo, JCCD.Job, JobDesc=j.Description, b.Contract, ContrDesc=b.Description, 

    --  MAX(Dates.LastLaborDate) as maxLastLaborDate, MAX(Dates.LastProjCostDate) as maxLastProjCostDate, 
    TD.LastLaborDate, TD.LastProjCostDate, 
--      '01/01/2013' AS LastLaborDate, '01/01/2015' AS LastProjCostDate,

        JCCD.Mth, JCCD.Phase, PhsDesc=JCJP.Description, 
        JCCD.CostType, CTDesc=JCCT.Description, JCCT.JBCostTypeCategory, 
        FieldPctCompl=isnull(u.PctCompl,0), FieldDate=Max(u.Date),  PMName=p.Name, 
        EstHours=sum(EstHours), EstCost=sum(EstCost), JTDHrs=sum(ActualHours), JTDCost=sum(ActualCost),
        ProjHours=sum(JCCD.ProjHours), ProjCost=sum(JCCD.ProjCost),
        MTDHrs=sum(case when JCCD.Mth=@ThruMth then ActualHours else 0 end), 
        MTDCost=sum(case when JCCD.Mth=@ThruMth then ActualCost else 0 end),
        FActCost=SUM(Case when JCCO.ProjMethod=2 then JCCD.ActualCost+JCCD.RemainCmtdCost else JCCD.ActualCost end),
        b.Department, DeptDesc=d.Description, HQName=HQCO.Name,ContrStat=b.ContractStatus,UIAmt=0,UITaxAmt=0,UIMiscAmt=0,ToBeInvd=0,sumTotalCmtdCost=0

from JCCD JCCD with(NoLock)
Left Outer Join JCJM j with(NoLock) on JCCD.JCCo=j.JCCo and JCCD.Job=j.Job
Left Outer Join JCCM b with(NoLock) on j.JCCo=b.JCCo and j.Contract=b.Contract
Left Outer Join JCDM d with(noLock) on b.JCCo=d.JCCo and b.Department=d.Department
Left Outer Join JCMP p with(NoLock) on j.JCCo=p.JCCo and j.ProjectMgr=p.ProjectMgr
Left Outer Join JCJP JCJP with(NoLock) on JCCD.JCCo=JCJP.JCCo and JCCD.Job=JCJP.Job and JCCD.Phase=JCJP.Phase
Left Outer Join JCCT JCCT with(NoLock) on JCCD.PhaseGroup=JCCT.PhaseGroup and JCCD.CostType=JCCT.CostType

Left Outer Join (Select u.Co, Job=u.Contract/*Prints Job# 9/13 per Tina - - VU9148*/, JCJM.Contract,
                        u.Phase, u.CostType, a.Mth, 
                        Date=Max(isnull(Date,'1950-01-01')),PctCompl=isnull(PctCompl,0)
                  from udVPPctComplete u
                  Join JCJM on u.Co=JCJM.JCCo and u.Contract=JCJM.Job
                  Join (select Co, Job=a.Contract,Contract=JCJM.Contract, Phase, CostType, Mth=Max(isnull(Mth,'1950-01-01')) 
                          from udVPPctComplete a 
                          Join JCJM on a.Co=JCJM.JCCo and a.Contract=JCJM.Job
                          where Mth<=@ThruMth and Co=@JCCo and JCJM.Contract between @BegContract and @EndContract
                          group by Co, a.Contract,JCJM.Contract, Phase, CostType
                     )a on a.Co=u.Co and a.Job=u.Contract and a.Phase=u.Phase and  a.CostType=u.CostType and a.Mth=u.Mth and a.Contract=JCJM.Contract
                group by u.Co, u.Contract,JCJM.Contract, u.Phase, u.CostType, a.Mth, isnull(PctCompl,0)
    ) u on JCCD.JCCo=u.Co and b.Contract=u.Contract and JCCD.Phase=u.Phase and JCCD.CostType=u.CostType and u.Job=JCCD.Job

    LEFT OUTER JOIN #DATES TD ON  j.JCCo=TD.JCCo and j.Contract=TD.Contract and j.Job=TD.Job
--Left Outer Join (Select JCJM.JCCo, JCJM.Contract, JCCD.Job,
--                      LastLaborDate=max(Case when JCTransType='PR' and (CostType between 2 and 3) then ActualDate else null end),
--                      LastProjCostDate=max(Case when JCTransType='PF' then ActualDate else null end)
--                 From JCCD JCCD with(NoLock)
--                 Join JCJM JCJM with(nolock) on JCJM.JCCo=JCCD.JCCo and JCJM.Job=JCCD.Job
--                  where (JCTransType='PR' or JCTransType='PF') and JCCD.JCCo=@JCCo and JCCD.Mth<=@ThruMth 
--                          and JCJM.Contract Between @BegContract and @EndContract
--                  group by JCJM.JCCo,JCJM.Contract,JCCD.Job
--     ) as Dates on j.JCCo=Dates.JCCo and j.Contract=Dates.Contract and j.Job=Dates.Job

Join JCCO JCCO with(NoLock) on JCCD.JCCo=JCCO.JCCo
Join HQCO HQCO with(NoLock) on JCCD.JCCo=HQCO.HQCo

where  JCCD.JCCo=@JCCo and b.Contract/*=' 51431.'--*/ between @BegContract and @EndContract and JCCD.Mth<=@ThruMth 
        and b.Department>=@BegDept and b.Department<=@EndDept 
        and j.ProjectMgr=(case when @PM<>0 then @PM else j.ProjectMgr end)

        and (charindex(','+left(cast(JCCD.CostType as char(5))+'     ', len(convert(varchar, JCCD.CostType)))+',', ','+@LabCTs+',')<>0 
                or charindex(','+left(cast(JCCD.CostType as char(5))+'     ', len(convert(varchar, JCCD.CostType)))+',', ','+@MatCTs+',')<>0 )
Group by JCCD.JCCo, JCCD.Job,j.Description, b.Contract, b.Description, JCCD.Mth, JCCD.Phase, JCJP.Description, JCCD.CostType,
            u.PctCompl,JCCT.Description, p.Name,JCCT.JBCostTypeCategory,
                    TD.LastLaborDate, TD.LastProjCostDate, 

            --Dates.LastLaborDate, Dates.LastProjCostDate,
            b.Department, 
            d.Description,HQCO.Name,b.ContractStatus
4

1 回答 1

1

如果两个查询实际上是相同的,那么您的存储过程中可能缓存了一个损坏的查询计划。

您可以通过添加到过程中来强制过程每次重新编译计划OPTION(RECOMPILE)

Kim Tripp 谈 OPTION(重新编译)

如果我知道一个特定的语句在不同的执行之间有很大的不同并且最佳计划也不同(同样,我应该通过测试多个示例执行知道这一点),那么我将正常创建存储过程并使用 OPTION (RECOMPILE)确保语句的计划没有被缓存或与存储过程一起保存。在每次执行时,存储过程将获得不同的参数,特别讨厌的语句将在每次执行时获得新的计划。

编辑我现在看到您正在调用重新编译。我将把这个答案留在这里,但对于其他搜索者来说,因为它可能与他们相关。

于 2013-11-06T16:43:12.217 回答