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不考虑索引 但为什么在第一个查询执行计划显示索引寻求? 感谢
答案 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”的值。根据您的需要,您可能需要考虑全文搜索(即,此查询中使用的参数值是因为它是作为应用程序用户的输入提供的。)