我从不质疑以下两个脚本之间的效率差异:
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秒相比) - 这是否符合预期?为什么呢?
答案 0 :(得分:3)
在第一个查询中,它使用变量。这些值在编译时是未知的,因此它根据通用估计产生计划。在第二个,它根据实际参数值编译计划。
通用猜测比计算知道特定值的计划更好的事实表明您的统计数据可能需要更新。
可能最后一次更新时,如果有任何行与WHERE DateKey > = 20130101 AND DateKey < 20130201
谓词匹配,但现在有很多行。
See also this question and answers on the dba site
修改这可以在此处的计划中看到
线条的粗细表示行数。计算标量左侧的细线显示估计的行数(计算标量for the reasons here通常不显示实际行计数)。计算标量中的非常粗的行和排序中的非常粗的行表示实际的行数。这两者显然非常不同。
除了选择不合适的计划(带有嵌套循环连接的串行)之外,这个糟糕的估计还意味着当查询请求内存授予不足时(由警告三角形显示),排序溢出到光盘。