避免在 SQL Server 2008 R2 中进行索引扫描
Avoid index scan in SQL Server 2008 R2
我需要一些帮助。
我目前正在对一些 SQL 的动态问题进行故障排除,这需要一段时间才能 return 结果。我正在使用 SQL Server 2008 R2,内部版本 10.50.4305
我已经执行了 SQL 跟踪,所以我现在可以看到发生了什么,基本上罪魁祸首是聚簇索引扫描。
select 包含:
WHERE
Name LIKE @Query + '%' ESCAPE '\'
ORDER BY
这会导致聚簇索引扫描。
如果我将 select 更改为
WHERE
Name LIKE 'value' + '%' ESCAPE '\'
ORDER BY
我得到一个索引查找和一个键查找。
我看起来好像在使用 forceseek 查询提示,但我收到了错误....
Msg 8622, Level 16, State 1, Line 6
Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN.
任何有关如何在查询中保留参数并避免聚簇索引扫描的帮助或建议,我们将不胜感激。
更新(摘自 Shnugo 的评论)
I've added the query to the original question and the value of @Query is the same everytime whether the result is fast or slow
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
正如我在评论中指出的那样,我假设您的动态 SQL 中的某些字符被解释为模式。 ESCAPE
的用法可能是一个提示,您知道这一点并且插入了替换字符以将这些特殊字符标记为 normal...
看起来,好像您只是在寻找相同的开始...试试这个
WHERE LEFT(Name,LEN(@Query))=@Query
这应该从 Name
的左侧剪切相同数量的字符,并将其与您的 @Query
变量进行比较。
这种方法不会那么快,因为它不可搜索并且也不能使用索引,但是 - 如果我的假设是正确的 - 它应该比 LIKE
更快它正在对每一行进行复杂的模式检查...
更新(摘自以下评论)
难道是其他重动作盗用了服务器资源?你试过没有 ORDER BY
吗?
我刚刚试过了,我可以重现这个。搜索文字意味着优化器可以提前了解所有内容:最佳预测、统计信息和索引的最佳使用。此外,您的结果可能具有误导性。如果您一遍又一遍地执行此操作,结果将被缓存。使用相同的查询,您可能会很快得到答案 - 但它们来自缓存...
参数嗅探也可能是个问题。
将语句创建为字符串(带有文字)并使用 EXEC
到 运行。
可能会有所帮助
我需要一些帮助。
我目前正在对一些 SQL 的动态问题进行故障排除,这需要一段时间才能 return 结果。我正在使用 SQL Server 2008 R2,内部版本 10.50.4305
我已经执行了 SQL 跟踪,所以我现在可以看到发生了什么,基本上罪魁祸首是聚簇索引扫描。
select 包含:
WHERE
Name LIKE @Query + '%' ESCAPE '\'
ORDER BY
这会导致聚簇索引扫描。
如果我将 select 更改为
WHERE
Name LIKE 'value' + '%' ESCAPE '\'
ORDER BY
我得到一个索引查找和一个键查找。
我看起来好像在使用 forceseek 查询提示,但我收到了错误....
Msg 8622, Level 16, State 1, Line 6
Query processor could not produce a query plan because of the hints defined in this query. Resubmit the query without specifying any hints and without using SET FORCEPLAN.
任何有关如何在查询中保留参数并避免聚簇索引扫描的帮助或建议,我们将不胜感激。
更新(摘自 Shnugo 的评论)
I've added the query to the original question and the value of @Query is the same everytime whether the result is fast or slow
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
正如我在评论中指出的那样,我假设您的动态 SQL 中的某些字符被解释为模式。 ESCAPE
的用法可能是一个提示,您知道这一点并且插入了替换字符以将这些特殊字符标记为 normal...
看起来,好像您只是在寻找相同的开始...试试这个
WHERE LEFT(Name,LEN(@Query))=@Query
这应该从 Name
的左侧剪切相同数量的字符,并将其与您的 @Query
变量进行比较。
这种方法不会那么快,因为它不可搜索并且也不能使用索引,但是 - 如果我的假设是正确的 - 它应该比 LIKE
更快它正在对每一行进行复杂的模式检查...
更新(摘自以下评论)
难道是其他重动作盗用了服务器资源?你试过没有 ORDER BY
吗?
我刚刚试过了,我可以重现这个。搜索文字意味着优化器可以提前了解所有内容:最佳预测、统计信息和索引的最佳使用。此外,您的结果可能具有误导性。如果您一遍又一遍地执行此操作,结果将被缓存。使用相同的查询,您可能会很快得到答案 - 但它们来自缓存...
参数嗅探也可能是个问题。
将语句创建为字符串(带有文字)并使用 EXEC
到 运行。