(问题移至SO)
我有一个表(虚拟数据),其中聚集索引包含2列:
现在,我运行这两个查询:
declare
@productid int =1 ,
@priceid int = 1
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid OR @productid IS NULL)
AND (priceid = @priceid OR @priceid IS NULL)
SELECT productid,
t.priceID
FROM Transactions AS t
WHERE (productID = @productid)
AND (priceid = @priceid)
这两个查询的实际执行计划是:
如您所见,第一个使用SCAN,第二个使用SEEK。
但是-添加OPTION (RECOMPILE)
到第一个查询中,还制定了执行计划以使用SEEK:
DBA聊天的朋友告诉我:
在您的查询中,@ productid = 1,这意味着可以将(productID = @ productID或@productID IS NULL)简化为(productID = @ productID)。前者需要扫描才能使用@productID的任何值,后者可以使用查找。因此,当您使用RECOMPILE时,SQL Server将查看您在@productID中实际具有的值,并为其制定最佳计划。如果@productID中的值为非null,则搜索是最好的。如果@productID的值未知,则该计划必须适合@productID中的任何可能的值,这需要进行扫描。警告:OPTION(RECOMPILE)将在每次运行时强制重新计划,这将使每次执行增加几毫秒的时间。虽然这只是查询运行非常频繁的问题。
另外:
如果@productID为null,您将寻求什么价值?答:没有什么可寻求的。所有值均合格。
我知道这会OPTION (RECOMPILE)
强制SQL Server查看参数具有的实际值,并查看它是否可以对其进行搜索。
但是现在我失去了提前编译的好处。
题
仅当参数为null时,才会发生IMHO-SCAN。
很好-让SQL SERVER为SCAN创建执行计划。
但是,如果SQL Server看到我使用值多次运行此查询:1,1
,那为什么不创建另一个执行计划并为此使用SEEK呢?
AFAIK-SQL为最热门的查询创建执行计划。
为什么SQL SERVER不保存以下执行计划:
@productid int =1 , @priceid int = 1
(我用这些值运行了很多次)
- 是否可以强制SQL保留该执行计划(使用SEEK)以供将来调用?