我试图理解在谓词中引入变量的影响。我有这个查询
declare @CommentedOnly nvarchar(max)=null
select top 5 * from journalemail je
where @CommentedOnly IS NULL OR je.ID IN (SELECT EmailID FROM EmailComments)
这是实际的计划
我希望过滤器会被优化和删除,因为它始终为null。但是,当我看到计划时,过滤器会增加查询的成本。
有些人可以指导我这是如何工作的吗?
答案 0 :(得分:2)
存储并重用SQL Server中的查询计划。没有进行分析以确定变量的值确实是常量,因此SQL Server必须生成一个可以重用于变量的所有可能值的计划。
您的示例中的查询计划实际上不会触及表EmailComments
,因为Left Semi Join仅检查是否存在至少一行,而该行来自Constant Scan,当{返回一行时{1}}为空。
您可以要求SQL Server使用@CommentedOnly
为每次执行生成新计划。您将获得每次执行的编译开销,但变量值保证是它的原因并且优化器使用该知识,因此在您的示例中,它将构建仅包含Clustered Index Scan和Top运算符的计划
option recompile
答案 1 :(得分:0)
如果查看查询计划,它根本没有声称知道空声明 - 它似乎只查看查询。也许存储过程中的类似代码(其保证将设置值与查询耦合)实际上将被优化。在没有设置此类空值的其他上下文中,此分析器可能会打开空间以供查询使用。