【发布时间】:2012-02-15 16:35:27
【问题描述】:
我的数据库中有这个存储过程:
ALTER PROCEDURE [dbo].[sp_FTSearchLocation]
@SearchFor nvarchar(200) = null
,@StartRow int
,@EndRow int
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM (
SELECT TOP (@EndRow)
*, ROW_NUMBER() OVER (ORDER BY Recommendations DESC, CompanyName) AS num
FROM
dbo.cachedSearchTable
WHERE
(
(@SearchFor IS NULL)
OR (CompanyName like '%' + @SearchFor + '%')
OR (Handle like '%' + @SearchFor + '%')
OR (Activity like '%' + @SearchFor + '%')
)
) As a
WHERE num > @StartRow
OPTION (RECOMPILE)
END
dbo.cachedSearchTable 具有包含 Recommendations DESC, CompanyName 列的聚集索引。没有其他索引。我认为使用* 是安全的,因为表cachedSearchTable 被构造为仅包含与此查询相关的列。
对于某些搜索字符串,此过程运行得非常快。例如,搜索accountants 会在不到一秒的时间内返回。但是,其他的运行速度很慢:当@SearchFor 设置为soup 时,大约需要 6 秒才能返回。
每一个的执行计划看起来都一样:
对于Accountants:
ClusteredIndexScan (85%) ->
Segment (15%) ->
ComputeScalar (0%) ->
SequenceProject (0%) ->
Top (0%) ->
Filter (0%) ->
Select (0%).
对于Soup:
ClusteredIndexScan (95%) ->
Parallelism (Gather Streams) (5%) ->
Segment (0%) ->
ComputeScalar (0%) ->
SequenceProject (0%) ->
Top (0%) ->
Filter (0%) ->
Select (0%).
但是,对于 accountants,ClusteredIndexScan 的估计运算符成本为 0.57,而对于 soup,它的成本为 25.34。
我尝试在表上放置 3 个非聚集索引 - 每个搜索列一个 - 但这没有帮助。
我的数据库中有很多会计师(约 4000 人),但名字中带有“汤”的会计师很少(约 50 人)。一般来说,当有很多可能的结果可供选择时,查询似乎运行得最快,而当要返回的结果很少时,查询运行得最慢。
如何加快查询速度?减慢对表的写入速度并不重要,但应用更多索引似乎无济于事。你有什么建议吗?
【问题讨论】:
-
您是否尝试更新统计信息?在我将大量记录放入表后,我曾经遇到过与您的问题类似的问题。我认为统计信息的碎片不会正确更新,并且可能是 SQL 执行计划错误的原因。只是猜测
-
这称为参数嗅探——本质上,SQL Server 会根据您传递的第一个参数来编译计划,虽然它可能会使用不同的参数做出不同的决定。您是否比较了执行计划的好坏?请参阅stackoverflow.com/questions/1007397/… 并获得我们的免费计划浏览器工具,它可以更好地突出这些问题sqlsentry.net/plan-explorer/sql-server-query-view.asp
-
@AaronBertrand 谢谢,我会得到你的软件,它看起来很有用。实际的存储过程有很多额外的参数(所有这些参数都可能为空),所以它设置了
option(recompiled),我认为这意味着每次都重新编译一个计划。我已经编辑了我的问题以表明这一点。 -
@Pongsathon.keng 这就是小费,我将对此进行调查。表格的全部内容经常变化。
标签: sql sql-server-2005