2013-02-26 31 views
1

我遇到一個相當奇怪的問題:SqlCommand的顯示性能不良傳遞文本參數時像

我形成動態SQL服務器命令及其部分之一,是一批像測試,被用來作爲文本搜索在幾個列和表上。它看起來像:

SET @text = '%' + REPLACE(REPLACE(REPLACE(@text, '!', '!!'), '%', '!%'), '_', '!_') + '%' 

INSERT INTO 
    @textFiltered 
FROM 
    @documents d 
    LEFT JOIN docData t1 WITH (NOLOCK) 
    ON t1.ID = d.ID AND 
     (t1.Topic like @text escape '!' 
     OR t1.Subject like @text escape '!') 
    LEFT JOIN docData2 t2 WITH (NOLOCK) 
    ON t2.ID = d.ID AND 
     t2.Name like @text escape '!' 
WHERE 
    t1.ID IS NOT NULL 
    OR t2.ID IS NOT NULL 

(當然,這不是做文本搜索的最好辦法,還是這不是點)

現在,當我在C#創建SqlCommand的,就像這樣:

using (var cmd = new SqlCommand()) 
{ 
    cmd.CommandText = cmdText; 
    cmd.CommandType = CommandType.Text; 
    cmd.Connection = connection; 
    cmd.Parameters.Add("text", NVarChar, 4000).Value = searchText; 
    var reader = cmd.ExecuteReader(); 
    .... 
} 

在SQL Management Studio中執行相同查詢的速度要快得多(比如500毫秒),執行的執行效率很差(如8秒)。 然而,如果不是通過文本作爲參數,我將其嵌入到與SQL文本:

DECLARE @text nvarchar(max) 
SET @text = '<embedded-text>' 

然後SqlCommand的也跑得快。 更奇怪的是,這種行爲似乎與LIKE子句中使用的一組列相關(沒有說明如何)。這些列的類型可以是nvarchar(size),nvarchar(max),ntext。

我懷疑問題是與參數 - 也許它的類型是不正確的或別的什麼別的。

P.S.試圖創建參數大小=搜索文本的長度+ 1 - 沒有幫助。

+0

你的'%'標籤在哪裏? – MethodMan 2013-02-26 05:11:16

+0

%標記附加在SQL中。在sql文本中添加了一行代碼,在輸入中添加了它們並掩蓋了'%','_'符號。 – Quercus 2013-02-26 05:54:01

+0

我有類似的問題(http://stackoverflow.com/q/2041484/87698)。顯然,SQL Server優化器有時會選擇錯誤的查詢計劃。 :-( – Heinzi 2013-02-26 06:06:29

回答

0

我最好的猜測是它與SQL Server爲您選擇的查詢計劃相關。 使用SQL服務器可以評估的常量varchar與現有統計信息之間存在很大差異,並且使用服務器一無所知的任意變量。

你可以嘗試OPTION(RECOMPILE)提示。儘管此提示將導致在每次調用時編譯的存儲過程爲,但它也將允許SQL Server搜索給定值的最佳計劃,也許在您的情況下它會很好的折衷。

你也可以爲存儲過程的兩個選項添加查詢計劃,也許有人能夠看到差異,並指出確切的問題。