比较运算符对查询执行持续时间的巨大影响令人可笑



我定义了以下视图:

dsplit_base-4个查询的联合,每个查询是事实表和映射表之间的简单联接(包含调用统计信息);它由201列组成

calls_check-从dsplit_base派生的视图,用于数据一致性检查。以下是定义:

SELECT a.Brand,
       a.[Call Center] ,
       c.date,
       c.weekday,
       COUNT(*) vol,
       cast((COUNT(*)-g.vol) AS real)/g.vol*100 vol_diff ,
       SUM(abncalls+acdcalls) calls ,
       CASE
           WHEN g.calls<>0 THEN cast((SUM(abncalls+acdcalls)-g.calls) AS real)/g.calls*100
           ELSE CASE
                    WHEN SUM(abncalls+acdcalls)<>0 THEN 100
                    ELSE 0
                END
       END calls_diff
FROM dsplit_base a
JOIN calendar c ON a.ROW_DATE=c.date
JOIN
  ( SELECT t.Brand,
           t.[Call Center],
           c.weekday,
           avg(cast(vol AS bigint)) vol,
           AVG(cast(calls AS bigint)) calls
   FROM
     ( SELECT Brand,
              [Call Center], row_date, COUNT(*) vol, SUM(abncalls+acdcalls) calls from dsplit_base group by ROW_DATE, [Call Center],
              Brand ) t
   JOIN calendar c ON t.row_date=c.date
   GROUP BY c.weekday,
            t.[Call Center],
            t.Brand) g ON c.weekday=g.weekday
AND a.Brand=g.Brand
AND a.[Call Center]=g.[Call Center]
GROUP BY c.date,
         c.weekday,
         g.vol,
         g.calls,
         a.[Call Center],
         a.Brand

以下查询在1-3秒内生成约16000行:

    select * from calls_check
Brand   Call Center date    weekday     vol vol_diff    calls   calls_diff
LMN Munich      2008-01-24  Thursday    3   -25     470 8.796296
LMN Munich      2008-04-26  Saturday    3   0       352 51.72414
...

现在,我遇到的实际问题是,当我试图在有限的时间内得出结果时。通过添加如下where子句,查询将不会完成(肯定不会在大约10分钟内完成):

    select * from calls_check
    where date >= DATEADD(d, -8, sysdatetime())

更奇怪的是,这个查询在一秒钟内成功执行!

    select * from calls_check
    where date < DATEADD(d, -8, sysdatetime())

有人能说出为什么where子句中的比较运算符会产生这样的差异吗?为什么<似乎非常有效地对结果集进行切片,而=会使查询无响应?


一些附加信息:

dsplit_base视图由4个表联合(带联接)组成。以下是他们的行计数:

dsplit_DE-2521

dsplit_WNS-7243

dsplit_US-121451

合作伙伴-377841(166043)

实际的"partners"表行数为166043,因为在视图中,它在以下条件下取行:

from partners p join splitdim s 
ON p.[Skill Name]=s.SPLITNAME and (p.Date>=s.[start_date] or s.[start_date] is null) and (p.DATE<=s.[end_date] or s.[end_date] is null)
where s.[Call center] IN ('Sitel', 'TRX', 'Sellbytel') 
OR (s.[Call center]='WNS' and p.Date<(select MIN(row_Date) from dsplit_WNS))
OR (s.[Call Center]='Munich' and (p.Date<'2012-06-29' or p.Date between '2012-08-01' and '2012-08-27'))

我对修改后的视图定义进行了实验,发现:

只有dsplit_DE和/或dsplit_WNS的视图,两个查询的工作速度都很快(1-2秒)

对于合作伙伴,仅'>='查询耗时约30秒;使用dsplit_US只需要大约60秒的

这是后一个执行计划的实际执行计划

最后两张表比其他表大得多,但有几十万条记录,应该不会花这么长时间。是什么导致执行时间的差异取决于'<'或where子句中使用的">"运算符?

据我所知<>=不同例如如果X<4,它将小于4或3,2,1…同时如果X>=4,X的值是多少,它将是4,5,6…

     select * from calls_check
where date < DATEADD(d, -8, sysdatetime())

仅检索最小数据

 select * from calls_check
    where date >= DATEADD(d, -8, sysdatetime())

检索大量数据,这就是为什么它需要大量时间来检索

此外,在比较日期时也需要非常小心,两者都应该在datetime中,而不是在string中,这将导致错误,并且不会产生预期的结果

希望这能有所帮助,谢谢:)

最新更新