2012-02-15 43 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

相關問題