2014-10-30 48 views
0

我正在查看遺留代碼,因爲它的性能很差。 我跟蹤這個問題到當使用OR @Parameter IS NULL與函數時出現奇怪的性能問題

DECLARE @Parameter AS VARCHAR(50) = '12345' 
SELECT * 
FROM MyTable 
WHERE 
(
    MyIndexedField IN (SELECT Value from fn_Function(@Parameter)) 
    OR @Parameter ISNULL; 
) 
AND OtherCriteria = 'Something' 

查詢是想從表中拉,有一個非聚集索引的字段的所有數據。當我刪除OR @Parameter IS NULL它運行在一秒鐘之內,但是當我添加@Parameter IS NULL時,它需要40s +。

如果我用函數替換函數,它會在一秒之內運行。 例

SELECT * 
FROM MyTable 
WHERE 
(
    MyIndexedField IN ( '12345') 
    OR @Parameter ISNULL; 
) 
AND OtherCriteria = 'Something' 

任何想法怎麼回事,和一個更好的方式來重寫此查詢?

這是對正在運行的SQL 2008

感謝,


編輯

我是能夠得到解決的問題,但溶液奇,見下文。 不要以爲這是最好的解決方案,如果您有任何建議,將不勝感激。

DECLARE @Parameter AS VARCHAR(50) = '12345' 
SELECT DISTINCT MyIndexedField 
INTO #T 
FROM MyTable WHERE @Parameter IS NULL 

UNION ALL 

SELECT Value FROM fn_Function(@Parameter) 

SELECT * 
FROM MyTable AS X 
JOIN #T  AS T ON T.MyIndexedField = X.MyIndexedField 
WHERE OtherCriteria = 'Something' 

回答

0

沒有看到執行計劃,並知道什麼是fn_Function函數實際上確實很難給出定論的意見,但一對夫婦的想法,這將是值得探討的是:

1)如果您添加OPTION (RECOMPILE)添加到語句末尾,那麼優化器將能夠「查看」@Parameter參數的值,並因此能夠優化OR參數IS NULL條件(針對該特定輸入值)這個語句的'成本'必須在每次被調用時被重新編譯(而不是被存儲在執行計劃緩存中)。根據呼叫頻率/編譯成本,這可能是視功能fn_Function的複雜性的可行策略

2)你可以重新寫在網上。如果它是一個多語句或內聯表值函數,我無法看到該函數,這與此處相關。

希望這給出了一些事情要看的指針。

相關問題