我有使用以下构造的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的事实应该已经“短路”了那部分查询?
答案 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)您将得到一个好的计划。