“IF..ElseIf..Else”或“Where子句”用于指导存储过程结果

时间:2010-11-04 09:49:36

标签: sql performance stored-procedures recompile

我有以下两个SQL语句

第一个:

IF(@User_Id IS NULL)  
BEGIN  
      SELECT *
      FROM [UserTable]
END  
ELSE           
BEGIN                  
      SELECT *
   FROM  [UserTable] AS u
   WHERE  u.[Id] = @User_Id                  
END 

第二个:

SELECT  *
FROM [UserTable] AS u
WHERE (@User_Id IS NULL OR u.[Id] = @User_Id)

这两个查询都将包装在自己的存储过程中。我怀疑IF语句对SQL造成了很多重新编译。我面临要么将IF语句的每个部分分成它自己的存储过程,要么用WHERE子句替换整个IF语句(如上面第二个SQL语句所示)

我的问题是:从性能角度看两个语句之间有什么区别,以及SQL如何处理每个语句?

感谢。

1 个答案:

答案 0 :(得分:0)

两种解决方案都会产生相同数量的编辑。

第一个解决方案是查询优化器可以自由地为两个不同的查询中的每一个提出最佳计划。第一个查询(在IF的NULL分支上)并不是很多可以优化的,但如果Id列上的索引存在,则可以优化第二个查询(在ID的NOT NULL分支上)。 / p>

但第二种解决方案是优化灾难。无论@User_Id参数的值如何,优化程序都必须提供适用于参数的任何值的计划。因此,无论@User_Id的值如何,计划都始终使用次优表扫描。没有办法绕过这个问题,这是参数嗅探有些人可能会想到的。只是计划的正确性,即使计划生成时的值为非NULL,即使参数 为NULL,计划也必须工作,因此它不能使用Id上的索引。

始终,始终,始终使用带有显式IF的第一个表单。