sp_execute 选择不同的查询计划
Posted
技术标签:
【中文标题】sp_execute 选择不同的查询计划【英文标题】:sp_execute chooses different query plan 【发布时间】:2016-08-23 08:35:33 【问题描述】:所以这就是场景:
表格有很多字段。 Field2 是聚集索引中的唯一字段。 存在Field1、Field2唯一索引,不包含任何其他字段。
表有 500000 行,其中 499900 为 Field1 有空值。
查询 1:
SELECT TOP (1) *
FROM Table WITH(UPDLOCK)
WHERE (Field1='XXX') ORDER BY Field1 DESC, Field2 DESC OPTION(OPTIMIZE FOR UNKNOWN)
产生Index Seek到唯一索引Field1,Field2,然后key查找到聚集索引,速度非常快。
然而,
Declare @P1 int;
Exec sp_prepare @P1 output,
N'@0 nvarchar(20)',
N'SELECT TOP (1) *
FROM Table WITH(UPDLOCK)
WHERE (Field1=@0) ORDER BY Field1 DESC, Field2 DESC OPTION(OPTIMIZE FOR UNKNOWN)';
Exec sp_execute @P1, N'XXX'
EXEC sp_unprepare @P1;
产生聚集索引扫描,速度很慢。
DBCC FREEPROCCACHE 没有帮助,所以这不是现金查询计划的问题。
问题是,为什么会有差异?
谢谢。
已编辑:不小心将相同的内容放入第二个查询中,已更新以正确反映它。
【问题讨论】:
我想知道如果@P1 参数被硬编码到命令字符串中会发生什么。那么执行时间是多少呢? 硬编码参数使计划相同。 【参考方案1】:这是由于参数是可变的,如果你硬编码它会返回相同的计划,或者如果你将参数放入正常执行中,它会生成要扫描的计划。
【讨论】:
显然这是唯一的区别,但为什么呢?这是在哪里记录的? 您可以在this 文章中获得一些信息。在我看来,Itzik Ben-Gan 的一本书“查询 Microsoft SQL Server 2012”第 17 章第 2 课:“使用参数化查询和批处理操作”对此进行了很好的解释。 您认为文章的哪一部分与此有关?以上是关于sp_execute 选择不同的查询计划的主要内容,如果未能解决你的问题,请参考以下文章
如何让 MS-Access 为我的查询选择不同/正确的执行计划