SQL Server:" boolean"中的子查询WHERE子句

时间:2014-09-11 02:28:43

标签: sql sql-server tsql subquery where-in

我有使用以下构造的T-SQL查询(SQL Server 2008/2012):

WHERE (@param1 IS NULL OR column1 = @param1)
AND (@param2 IS NULL OR column2 = @param2)
AND (@param3 IS NULL OR column3 = @param3)

这样可以正常工作,并使用NULL参数自动优化WHERE子句的任何AND部分。

但是当我使用子查询执行同样的操作时,即使param为NULL,优化器仍然会执行子查询:

WHERE 
    (@param1 IS NULL OR column1 IN (SELECT column 
                                    FROM table 
                                    WHERE column = @param1))
    AND (@param2 IS NULL OR column2 IN (SELECT column 
                                        FROM table 
                                        WHERE column = @param2))
    AND (@param3 IS NULL OR column3 IN (SELECT column 
                                        FROM table 
                                        WHERE column = @param3))

我的问题是为什么优化器甚至会考虑“IN”SELECT,因为param为NULL的事实应该已经“短路”了那部分查询?

1 个答案:

答案 0 :(得分:0)

@ user640466:我认为如果添加OPTION(RECOMPILE)查询提示错误计划将消失,原因是查询优化器必须评估IN子句以获取ProductID值,而在OPTION(重新编译)的情况下,它可以嗅探运行时间值。请参阅以下Adventure工作的工作副本:

CREATE PROC MyTest
@ProductID INT ,
@Name NVARCHAR(50),
@ProductNumber NVARCHAR(50)
AS
SELECT * 
FROM Production.Product 
WHERE 
(ProductID IN (SELECT ProductID FROM Production.Product WHERE ProductID = @ProductID ) OR @ProductID IS NULL)
AND 
(Name IN (SELECT Name FROm Production.Product WHERE Name = @Name) OR @Name IS NULL)
AND 
(ProductNumber IN (SELECT ProductNumber FROM Production.Product WHERE ProductNumber = @ProductNumber)  OR @ProductNumber IS NULL)
--OPTION (RECOMPILE)
GO 

如果您执行Proc:EXEC Mytest 1,NULL,NULL,您将获得一个冗长的计划,但是更改sp并取消注释OPTION(RECOMPILE)您将得到一个好的计划。