2015-10-08 207 views
0

我正試圖優化一個存儲過程,此時此刻很慢。它需要幾個參數來搜索哪些可以爲空。 SP中的查詢看起來像這樣。SQL查詢優化(搜索)

SELECT 
    *some fields from the table* 
FROM 
    [hrmCase] 
WHERE 
    BrkId = @BrkId 
AND 
    (ChannelId IN ('TO','TD')) 
AND 
    case 
     when @PsId is null then 1 
     when (@PsId is not null) and ((SELECT SUBSTRING(UPPER(DATENAME(MONTH, Created)),1,3) + CAST(PSId AS varchar) PSId) like ('%' + @PsId + '%')) then 1 else 0 
    end = 1 
AND 
    case 
     when @ACaseId is null then 1 
     when (@ACaseId is not null) and (AId like ('%' + @ACaseId + '%')) then 1 else 0 
    end = 1 
AND    
    case 
     when @DateCreated is null then 1 
     when (@DateCreated is not null) and (dbo.StripTime(Created) = dbo.StripTime(@DateCreated)) then 1 else 0 
    end = 1 
AND 
    case 
     when @Clients is null then 1 
     when (@Clients is not null) and (Client like ('%' + @Clients + '%')) then 1 else 0 
    end = 1 

這是做的最好的方式還是應該建立一個基於輸入參數動態查詢像下面

Declare @SQLQuery AS NVarchar(4000) 
Declare @ParamDefinition AS NVarchar(2000) 

Set @SQLQuery = 'SELECT *some fields from the table* FROM [hrmCase] WHERE (1=1)' 

If @PsId Is Not Null 
    Set @SQLQuery = @SQLQuery + ' And (SELECT SUBSTRING(UPPER(DATENAME(MONTH, Created)),1,3) + CAST(PSId AS varchar) PSId) like (''%''' + @PsId + '''%'')' 

etc.. 

這被認爲更加專業和上述兩個查詢的速度會更快。請建議是否有更好的方法來做同樣的事情。

乾杯, DS

+0

在每種情況下,您都使用函數或'LIKE%短語%',以便您的查詢不是SARGable,並且查詢優化器不會在任何存在的情況下使用idexes。沒有使用索引=糟糕的表現。 – lad2025

+0

當條件可以使用索引時,動態查詢幾乎總是更好。在你的情況下,條件不能。所以,動態版本會稍微快一點,因爲查詢的複雜比較會少一些。但它可能不會有很大的不同。 –

+0

不能幫助它。大多數列是文本列,我們允許部分搜索。 – SkoolCodeian

回答

0

SQL Server是非常糟糕時,使用參數處理這樣的 - 我們已經有很多情況下,我們得到它可接受,然後工作4個月後,有新的變化,並將其變成表掃描(或者更糟 - 我看到性能遠遠低於簡單表掃描)。 (我們在鏡像的40核心服務器上的SSD上有1.5TB數據庫)。我們發現的最佳解決方案是使用單獨的存儲過程或使用動態SQL。許多「專家」都對動態SQL感到不滿,但現實情況是,如今在任何體面的環境中,動態SQL的重新編譯在CPU使用和性能延遲方面都是微不足道的,它消除了因爲消除而出現的問題類型WHERE子句中的條件會混淆查詢優化器。

領先的通配符在每種情況下也會導致表掃描。全文索引可以比常規SQL更有效地執行此類搜索。一些SQL Server支持全文索引和查詢,有些則不支持。