2016-08-23 48 views
0

所以这是场景:sp_execute选择不同的查询计划

表中有许多字段。 Field2是聚簇索引中唯一的字段。 存在不包含任何其他字段的Field1,Field2唯一索引。

表中有500000行,其中499900个字段为空值。

查询1:

SELECT TOP (1) * 
FROM Table WITH(UPDLOCK) 
WHERE (Field1='XXX') ORDER BY Field1 DESC, Field2 DESC OPTION(OPTIMIZE FOR UNKNOWN) 

可生产索引查找唯一索引字段1,字段2,然后键查找到聚集索引,并且是非常快的。

然而,

Declare @P1 int; 
Exec sp_prepare @P1 output, 
N'@0 nvarchar(20)', 
N'SELECT TOP (1) * 
FROM Table WITH(UPDLOCK) 
WHERE ([email protected]) ORDER BY Field1 DESC, Field2 DESC OPTION(OPTIMIZE FOR UNKNOWN)'; 
Exec sp_execute @P1, N'XXX' 
EXEC sp_unprepare @P1; 

产生一个簇索引扫描,这是缓慢的。

DBCC FREEPROCCACHE没有帮助,所以它不是问题与兑现查询计划。

问题是,为什么区别?

谢谢。

编辑:意外地将同样的事情放入第二个查询中,更新以正确反映它。

+0

我想知道如果将@ P1参数硬编码到命令字符串中会发生什么情况。那么执行时间是多少? – PacoDePaco

+0

对参数进行硬编码使计划保持一致。 – mrQQ

回答

0

这是由于参数是可变的,如果你硬编码它将返回到相同的计划,或者如果你把参数放在正常执行中,它将生成计划来扫描。

+0

很明显,这是唯一的区别,但为什么?这在哪里记录? – mrQQ

+0

您可以在[this](https://msdn.microsoft.com/en-us/library/ee343986(SQL.100).aspx)文章中获得一些信息。在我看来,Itzik Ben-Gan'查询Microsoft SQL Server 2012'第17章第2课:'使用参数化查询和批处理操作'的书很好地解释了它。 – PacoDePaco

+0

您认为文章的哪一部分与此有关? – mrQQ