变量与字符串文字速度差异

时间:2016-06-29 21:59:34

标签: sql sql-server performance sql-server-2014

当我在WHERE子句中使用字符串文字时,我有一个非常快速(大约1秒)运行的简单查询,例如:

select *
from table
where theDate >= '6/5/2016'

然而,这个查询(没有实质性的不同)在2分钟内运行:

declare @thisDate as date
set @thisDate = '6/5/2016'

select *
from table
where theDate >= @thisDate

我尝试使用OPTION(RECOMPILE)建议here,但它没有改善性能。列theDate是日期时间,此数据库最近从SQL Server 2005迁移。

我的theDate列上没有索引,该表的行数超过10亿。它是一个共享资源,我不想在没有保证它会有所帮助的情况下开始编制索引。

我发现使用逻辑而不是变量提供与字符串文字相同的性能:

select *
from table
where theDate >= dateadd(dd, -23, getdate())

但是,如果我用变量整数替换日期整数,性能再次受到阻碍。

如何包含变量并保持性能?

修改

请求包含的实际查询:

DECLARE @days INT

Set @days = 7

select c.DEBT_KEY
       , c.new_value
       , c.CHANGE_DATE
from changes c with (nolock)
where c.C_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, -@days, getdate())

没有加入。

查询计划

使用变量(xml explain plan):

enter image description here

使用字符串文字(xml explain plan):

enter image description here

所以我可以看到区别在于变量调用聚簇索引扫描(聚集),而字符串文字调用密钥查找(聚集)...我需要引用谷歌,因为我真的不知道任何东西关于这些的表现利弊。

编辑编辑

这有效(xml explain plan):

DECLARE @days INT

Set @days = 7

select c.DEBT_KEY
       , c.new_value
       , c.CHANGE_DATE
from changes c with (nolock)
where c.CHANGE_CODE = 3
and c.old_value = 4
and c.CHANGE_DATE >= dateadd(dd, -@days, getdate())
OPTION(OPTIMIZE FOR (@days = 7))

enter image description here

......我不知道为什么。此外,我不喜欢这个解决方案,因为它否定了我使用变量的目的,即将所有变量放在proc的顶部,以减少在不可避免的维护期间在代码中徘徊的需要。

1 个答案:

答案 0 :(得分:0)

快速版本执行群集密钥查找(可以直接到表中找到该值的部分)。

慢速版本执行非群集搜索,然后将其与聚集索引扫描合并(它必须扫描整个表格)。

我看到@thisDate变量定义为Date类型。该列是否可以定义为DateTime?如果这是真的,@thisDate中的任何值都不会与您的聚簇索引完全对齐,这意味着数据库将必须检查整个表,如我们在此处所示。另一方面,字面值将被解释为DateTime值, 匹配您的表列类型,并将与索引一起使用。

如果这是正确的,你可以通过一个非常简单的改变来解决问题:

declare @thisDate as datetime
set @thisDate = '6/5/2016'

只有4个字符的差异。

您也可以与OPTION(RECOMPILE)一起试用,也可以查看OPTIMIZE FOR UNKNOWN