SELECT查询速度因不同输入而有很大差异?

时间:2012-02-15 16:35:27

标签: sql sql-server-2005

我在我的数据库中有这个存储过程:

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

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

1 个答案:

答案 0 :(得分:3)

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

那么,为什么差异呢?由于还有更多accountants然后soup s,并且您只搜索TOP N行,第一个查询将倾向于比第二个查找更早的N行,即通过扫描较小的部分该表。

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