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

时间:2013-08-28 09:09:20

标签: sql tsql

我定义了以下视图:

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子句中的比较运算符会产生这样的差异吗?为什么&lt; 似乎非常有效地对结果集进行切片,而&gt; = 会使查询无法响应?


其他一些信息:

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

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秒)

与合作伙伴只有'&gt; ='查询需要〜30秒 ;使用dsplit_US只花了大约60秒

这是后者EXEC PLAN

的实际执行计划

最后两张表比其他表大得多,但有几十万条记录不应该花这么长时间。什么原因导致执行时间的差异依赖于'&lt;'或'&gt;'在where子句中使用的运算符?

1 个答案:

答案 0 :(得分:0)

据我所知&lt; &gt; = 不同 例如 如果x <4,则X的值小于4或3,2,1 ...... 同时 X的值,如果x> = 4则为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它会导致错误而且不会产生预期的结果

希望这有助于谢谢:)