避免在SQL Server 2008 R2中进行索引扫描

时间:2017-04-12 08:17:03

标签: sql-server tsql sql-server-2008-r2 clustered-index

我在这里需要一些帮助。

我目前正在对一些动态SQL进行故障排除,这需要一个年龄来返回结果。我正在使用SQL Server 2008 R2,构建10.50.4305

我已经执行了SQL跟踪,所以我现在可以看到发生了什么,基本上罪魁祸首是聚簇索引扫描。

选择包含:

WHERE 
    Name LIKE 'value' + '%' ESCAPE '\' 
ORDER BY

这会导致聚簇索引扫描。

如果我将选择更改为

DECLARE @Query nvarchar(50)

SET @Query = 'EIKO'

SET NOCOUNT ON
SELECT TOP 5 pex.Ric.Name AS Id, pex.Ric.Name + '|' + pex.Ric.DisplayName AS Name FROM pex.Ric WITH (nolock) WHERE pex.Ric.Name LIKE @Query + '%' ESCAPE '\' ORDER BY PeId, Name

我得到索引搜索和键查找。

我看起来像使用forceseek查询提示但我收到错误....

  

Msg 8622,Level 16,State 1,Line 6
  由于此查询中定义的提示,查询处理器无法生成查询计划。重新提交查询而不指定任何提示,也不使用SET FORCEPLAN。

非常感谢有关如何在查询中保留参数以及避免聚簇索引扫描的任何帮助或建议。

更新(取自Shnugo的评论)

  

我已经将查询添加到原始问题中,无论结果是快还是慢,@ Query的值都是相同的

    User.findOneAndUpdate(
    { id: req.params.userid },
    { $pull: { 'posts': { 'posts._id': { $eq: req.body.postID } } } },
    { new: true }
 )

1 个答案:

答案 0 :(得分:2)

正如我的评论中所指出的,我假设,动态SQL中的一些字符被解释为模式。 ESCAPE的用法可以是一个提示,您知道这一点,并且您插入替换字符以将这些特殊字符标记为 normal ...

看起来好像你只是在寻找同样的开始......试试这个

WHERE LEFT(Name,LEN(@Query))=@Query

这应该从Name的左侧剪切相同的字符数,并将其与@Query变量进行比较。

这种方法不会那么快,因为它不是可以攻击的,也不能使用索引,但是 - 如果我的假设是正确的 - 它应该比LIKE更快,而不是ORDER BY对每一行进行复杂的模式检查...

更新(取自以下评论)

可能是,其他沉重的行为窃取了服务器的资源?你试过没有EXEC吗?

我刚尝试过,我可以重现这一点。搜索文字意味着优化器事先知道所有内容:最佳预测,统计和索引的最佳使用。此外,您的结果可能会产生误导。如果反复执行此操作,结果将被缓存。使用相同的查询,您可能会获得非常快速的答案 - 但它们来自缓存......

参数嗅探也可能是一个问题。

将语句创建为字符串(使用文字)并使用echo来运行可能会有所帮助。