SQL查询变量与硬编码值

SQL查询变量与硬编码值,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我需要一些解释,因为我自己找不到(可能是因为我不知道如何搜索它) 我有一个SQL Server查询,其中包含一些常见的表表达式,其中一个CTE是根据日期和用户不为空来选择数据,例如 WHERE "dummy"."UsageEnd" >= '20161001' AND "dummy"."UsageEnd" < '20161101' AND "Users"."Login" IS NOT NULL 此子查询执行时间为23-24秒,整个查询(作为提醒,此子查询

我需要一些解释,因为我自己找不到(可能是因为我不知道如何搜索它)

我有一个SQL Server查询,其中包含一些常见的表表达式,其中一个CTE是根据日期和用户不为空来选择数据,例如

WHERE 
    "dummy"."UsageEnd" >= '20161001' 
    AND "dummy"."UsageEnd" < '20161101' 
    AND "Users"."Login" IS NOT NULL
此子查询执行时间为23-24秒,整个查询(作为提醒,此子查询在CTE中)需要7-8分钟,而之前需要12-15秒


有人能给我解释一下为什么将日期与变量进行比较会显著增加执行时间吗?还有可能,整个查询花费的时间太长,因为当in-CTE是一个变量时,它会每次重新计算它,而不仅仅是一个?

问题很可能是由所有人的评论组合而成的:

如果UsageEnd列不是datetime数据类型,而是varchar,那么优化器首先需要将所有值转换为datetime类型,以便与变量进行比较

第一个带有“硬编码常量”的查询已经在varchar中,因此优化器能够更快地执行比较


这两个计划看起来都不同,并明确指出在哪里可以找到问题。

当运算符组合两个不同数据类型的表达式时,数据类型优先级规则指定将优先级较低的数据类型转换为优先级较高的数据类型。如果转换不是受支持的隐式转换,则返回错误

你比较过执行计划吗?可能与参数嗅探有关。如果你搜索它,你会找到比我能给出的更好的描述和解决方案。不过,您可以尝试使用“重新编译”提示进行
。当您提供一个固定值作为日期文字时,SQL Server可以针对这个确切的日期值优化查询。如果您提供了一个参数,SQL Server必须为您可能提供的任何可能的日期值提供一个尽可能优化的执行计划—因此,这很可能是一次不同的执行plan@marc_s我想你应该把它作为一个答案。重要的是USAGEE的数据类型是什么,并显示很少的日期样本。第二件事是参数的数据类型将是相同的。假设你的参数名是[@start],然后声明名为[@start1]=[@start]的本地变量。类似于[@end]。将@start1和[@end1]放在where子句中。usagend列是一个日期时间类型,这就是为什么我觉得奇怪,将它与“硬编码”varchar进行比较要快得多。关于执行计划,不幸的是,我无法比较它们,因为目前我只有对该数据库的读取权限(SHOWPLAN权限被拒绝)。知道我的公司没有人会给我更高级别的访问权限,所以我无法对此进行分析。然而,HoneyBadger提出的解决方案(选项(重新编译))非常有效很高兴知道你找到了解决办法!另外,根据我自己的经验,有时查询优化器在使用CTE时需要一些帮助,太多或太复杂的CTE可能会生成次优查询计划。将其中一些转换为临时表(@或#),然后在下面的CTE中使用这些表,也给了我一些令人印象深刻的速度提升。谢谢你的提示,我一定会研究它,因为整个查询是。。。在优化方面“不是最好的”。
WHERE  
    "dummy"."UsageEnd" >= @start 
    AND "dummy"."UsageEnd" < @end 
    AND "Users"."Login" IS NOT NULL
declare @datestart datetime
set @datestart = '20161001';

declare @dateend datetime
set @dateend = '20161101';