2012-02-15 45 views
1

我在我的数据库这个存储过程:SELECT不同的输入对查询速度有很大的影响?

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)。一般来说,当有大量可能的结果可供选择时,查询运行得最快,而当返回的结果非常少时,查询运行速度最慢。

如何加快此查询?减慢写入速度并不重要,但应用更多索引似乎没有帮助。你能提出什么建议吗?

+0

您是否尝试更新统计信息?我使用类似的问题就像你的问题后,我把大量的记录表table.I认为统计碎片不会更新不正确,可能是SQL的原因得到错误的执行计划。只是一个猜测 – 2012-02-15 16:44:00

+1

它被称为参数嗅探 - 本质上,SQL Server根据您传递的第一个参数编译计划,但它可能会根据不同的参数做出不同的决定。你是否比较了好的和坏的执行的执行计划?请参阅http:// stackoverflow。com/questions/1007397/sql-poor-stored-procedure-execution-plan-performance-parameter-sniffing and also get our free Plan Explorer tool which highlight these issues more better http://sqlsentry.net/plan-explorer/ sql-server-query-view.asp – 2012-02-15 16:44:28

+0

@AaronBertrand谢谢,我会得到你的软件,它看起来很有用。实际的存储过程有很多额外的参数(全部可能为空),所以它有'选项(重新编译)'集合,我认为这意味着每次重新编译一个计划。我编辑了我的问题来表明这一点。 – Oliver 2012-02-15 16:54:32

回答

3

LIKE %something上搜索将而不是受益于B-树索引。事实上,只有4000行需要秒(而不是毫秒)来搜索是一个额外的提示,这是事实。不要被查询计划中的ClusteredIndexScan弄糊涂 - 这只是一个完整表扫描的集群等价物。

那么,为什么不同?由于还有更多的accountants,因此soup s,并且您只搜索TOP N行,第一个查询将倾向于先于第二个查找N行,即通过扫描表的较小部分。

您需要重写查询以使用LIKE something%或(如果可能)使用全文索引。

+0

我之前没有使用全文索引,并且我无法避免使用产生结果为'LIKE%query%'的东西。对于这些查询,全文索引工作是否快速? – Oliver 2012-02-15 17:01:48

+0

@Oliver全文索引可以处理单词,而不是任意的子字符串。所以不行 - 这不会加速一般子字符串搜索,其中子字符串不一定落在字边界上。但**如果**你知道它总是会(落在字边界上),你应该能够使用它来加快你的搜索速度(这就是为什么我说“如果可能”)。 – 2012-02-15 17:08:48

+0

@Oliver然后,**如果**你可以将数据整齐地组织到“关键字”中,则可以通过将关键字提取到单独的表中来标准化表,然后您将能够搜索'= something'并使用正常的B树索引。 – 2012-02-15 17:11:50

相关问题