加入内部视图非常慢

时间:2019-03-10 05:23:54

标签: sql-server tsql

如果您可以为我的问题找到一个更好的标题,请随时编辑我的帖子。

在开始之前,请记住以下几点:

  1. 我无法实现任何视图

  2. 我无法创建任何索引

  3. select t1.*中的所有列都在继续使用,由于某种原因,这部分速度变慢了。

我有一个看法。该视图过去需要30秒才能完成。

现在,此视图至少需要2个小时(2个小时后我放弃并取消了查询)。

这是我的代码:

查询1耗时30秒:

select 
     t1.*,
     t2.legacysystemid as Servicerateid
from 
     NONWAIVER_RATES as t1
left join 
     v_SERVICERATE as t2 on t1.service = t2.service 
                         and t1.fundingsource = t2.fundingsource 
                         and t1.provider = t2.provider 
                         and t1.businessunit = t2.businessunit 
                         and t1.startdate = t2.startdate 
                         and t1.enddate = t2.enddate    
where 
     t2.service is not null

查询2花费了超过2个小时的时间:

与查询1完全相同,除了 t2.provider and t2.businessunit is NULL根据某些条件。

该如何加快加入速度?加入NULL值会降低性能吗?

编辑:

我发现在v_servicerate视图中,我使用了case语句。

        case
           when lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0 
              then NULL
              else t1.[fprovider]
        end as [provider]

--------------------------------------------

        case
           when lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0 
              then NULL
              else t1.[businessunit]
        end as [businessunit]

-------------------------------------------------------------------------

        case
           when lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0 
              then NULL
              else t1.[providerid_parent]
        end as [providerid_parent]

---------------------------------------------------

        case
           when lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0 
              then NULL
              else t1.[providerid_child]
        end as [providerid_child]
-----------------------------------------------------------------

如果我删除case语句并仅使用列本身(又名[providerid_parent],[providerid_child],[provider]和[businessunit])

一切再次变得超级快。

现在,我只需要弄清楚如何才能拿到我的蛋糕并将其吃掉。 。

2 个答案:

答案 0 :(得分:1)

对于case语句,您可能会检查iif()是否更快,因为它们仅在其他情况下使用一种情况,例如

,case
            when lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0 then NULL
            else t1.[fprovider]
            end as [provider]

-- becomes


,iif(lu_service.[iswaivereligible] = 0 AND lu_service.[isvariablerate] = 0,null,t1.[fprovider]) [provider]

  我发现时差有1000万条记录,收益微乎其微。

     

/ * 1000万条记录的案情声明* /
  SQL Server执行时间:CPU时间= 3407 ms,   经过的时间= 3404毫秒。

     

/ *如果相同的一千万个记录,则立即显示* /
  SQL Server执行   时间:CPU时间= 3297毫秒,经过的时间= 3366毫秒。

关于视图的第一个想法。既然您发现案例陈述有问题,那么其中的某些想法就变得毫无意义了:)但是这里是

--first, updatestats then check execution time 
exec sp_updatestats;
GO

-- next, I'd set "with schemabinding" and see if it's faster
create view blah with schemabinding
as
select 
     t1.*,
     t2.legacysystemid as Servicerateid
from 
     NONWAIVER_RATES as t1
left join 
     v_SERVICERATE as t2 
     on 
     t1.service=t2.service 
     and t1.fundingsource=t2.fundingsource 
     and t1.provider=t2.provider 
     and t1.businessunit=t2.businessunit 
     and t1.startdate=t2.startdate 
     and t1.enddate=t2.enddate    

where 
     t2.service is not null
GO

-- next I'd rework the join a bit, trying, not likely to work. sql should do this or something better "behind the scenes"

create view blah 
as
     t1.*,
     t2a.Servicerateid
from 
     NONWAIVER_RATES as t1
left join 
(select
      t2.fundingsource 
     ,t2.provider 
     ,t2.businessunit 
     ,t2.startdate 
     ,t2.enddate  
     ,t2.legacysystemid as Servicerateid
from 
     NONWAIVER_RATES as t1
inner join 
     v_SERVICERATE as t2 
     on 
     t1.service=t2.service -- if service is null it cannot match any value, even null.
     and t1.fundingsource=t2.fundingsource 
     and t1.provider=t2.provider 
     and t1.businessunit=t2.businessunit 
     and t1.startdate=t2.startdate 
     and t1.enddate=t2.enddate   
where 
     t2.service is not null   ) t2a 
   on 
     t1.service=t2a.service 
     and t1.fundingsource=t2a.fundingsource 
     and t1.provider=t2a.provider 
     and t1.businessunit=t2a.businessunit 
     and t1.startdate=t2a.startdate 
     and t1.enddate=t2a.enddate 

GO

答案 1 :(得分:0)

问题与我的案例陈述有关:

我在某些专栏中有一个案例陈述,但有些选择性(请参阅我的原始帖子)。我的加入条件也有类似的案例陈述。

我解决问题的方法是使用以下格式:

with everything as (

select *
from table
where criteria is not matched

union all

select *
from same_table_as_above
where criteria is matched

)

...其余查询。 。

关于我正在做的事情的主要构想是将符合特定条件的记录和不符合特定条件的记录分开,然后将它们合并在一起。

通过这种方式,我可以返回30秒的查询,同时获得所需的结果。

换句话说,我也把蛋糕也吃了。

问题现已解决。

编辑:

通过这种方式,我更改了执行计划。我不是执行计划方面的专家,但是我知道这就是为什么我的更改更快的原因。