Sql执行计划显示相同输入的不同结果

时间:2010-07-12 12:04:55

标签: sql database sql-server-2005

declare @name varchar(156)
set @name ='sara'
--Query 1:
SELECT [PNAME]  FROM [tbltest] where  [PNAME]  like '%'+@name+'%'

--Query 2:
SELECT [PNAME]  FROM [tbltest] where  [PNAME]  like '%sara%'

假设[tbltest]的[PNAME]列上有NoneClustered Index。 运行查询时,执行计划显示索引查找查询1和索引扫描查询2。 我预计Excution Paln显示索引扫描对于两个查询,但由于在第一个查询中使用参数,它显示索引查找。 那么我的主人呢? 在两个查询中我们在其他方面使用'%',并且知道在这种状态下,sql不考虑索引 但为什么在第一个查询执行计划显示索引寻求? 感谢

3 个答案:

答案 0 :(得分:1)

查询一个使用参数,查询2一个常量。

如果更改常量值,则不会重复使用查询2的计划。

计划1的查询可以是。在这种情况下,SQL Server(简单地)将其选项保留为重用计划。

AKA:查询相同。

如果你force parameterisation,那么你应该让两个查询像查询1一样运行。但我还没有尝试过......

答案 1 :(得分:0)

如果对表执行DBCC SHOW_STATISTICS以及正在使用的索引,请在输出的第一行中查找“String Index = YES”。 SQL Server维护某些额外的统计信息以满足'%x'

之类的查询

在第一个查询中,您可能会看到计算的标量值 - 在查询计划中查找LikeRangeStart('%'+ @ name +'%')。 Index Seek是针对这些值而不是针对%sara%的索引扫描。

这是如何工作的我不知道。为什么SQL Server不够聪明,不能将'sara'转换为常量,并以我不知道的方式执行查询。但我认为这是正在发生的事情。

对于%sara%,它执行索引扫描,读取整个索引。对于%+ @ name +%,它创建RangeStart / RangeEnd / RangeInfo计算值,并使用它们以某种方式利用附加字符串统计信息进行索引查找。

答案 2 :(得分:0)

我认为迈克正在走上正确的轨道,关于你是否正在击中指数。您对成本的跟进可能需要更多地了解您的数据在表格中的分布情况。我已经看到,由于需要两个磁盘读取,因此命中索引的成本更高。要了解原因,您必须知道数据在索引中的分布情况,页面中适合的记录数以及缓存方案的内容。

我会说使用前导%调整查询可能很困难。数据库需要完全遍历您的索引(或表)并命中每个节点以查找包含“sara”的值。根据您的需要,您可能需要考虑全文搜索(即,此查询中使用的参数值是因为它是作为应用程序用户的输入提供的。)