1

我从未质疑以下两个脚本之间的效率差异:

DateKey 是类型INT

1.

DECLARE @StartDate  INT = 20130101,
        @EndDate    INT = 20130201

SELECT  UserAccountKey,
        income_LT = SUM(ISNULL(income,0.0)) 
INTO    #x
FROM    WH.dbo.xxx x
WHERE   x.DateKey > = @StartDate
        AND x.DateKey < @EndDate
GROUP BY    UserAccountKey

上面的执行是:

在此处输入图像描述

2.

SELECT  UserAccountKey,
        income_LT = SUM(ISNULL(income,0.0)) 
INTO    #x
FROM    WH.dbo.xxx x
WHERE   x.DateKey > = 20130101
        AND x.DateKey < 20130201
GROUP BY    UserAccountKey

以下是 2 号的执行计划: 在此处输入图像描述

1.快得多(2 秒与 80 秒相比) - 这是预期的吗?为什么?

4

1 回答 1

3

在第一个查询中,它使用变量。这些值在编译时是未知的,因此它会根据通用估计生成一个计划。在第二个中,它根据实际参数值编制计划。

通用猜测比知道特定值的计划效果更好,这一事实表明您的统计数据可能需要更新。

如果有任何行与谓词匹配,则可能上次更新它们很少,WHERE DateKey > = 20130101 AND DateKey < 20130201但现在很多。

这是升序日期列的常见问题

另请参阅 dba 站点上的此问题和答案

编辑这可以在这里的计划中看到

在此处输入图像描述

线条的粗细表示行数。计算标量左侧的非常细的线显示了估计的行数(由于此处的原因,计算标量通常不显示实际行数)。计算标量和排序外的非常粗的线表示实际的行数。两者显然有很大不同。

除了选择不合适的计划(带有嵌套循环连接的串行连接)外,这种糟糕的估计还意味着当查询请求的内存授权不足时排序溢出到磁盘(由警告三角形显示)。

于 2013-02-08T13:06:53.643 回答