2012-11-05 37 views
1

我在ASP.NET應用程序中有一段代碼,它可以從參數列表構建SQL查詢。參數的數量可能會有所不同,因此可以將各種標準添加到此查詢中。該數據庫是Microsoft SQL Server 2008.如何加速此SQL查詢

所有的AND和OR都是以編程方式生成的。

該查詢花費了3秒多的時間執行,但是在一些分析和索引運行後不到一秒鐘。我仍然認爲查詢本身可以進行優化。我已經看過執行計劃,但這對我來說沒有多大意義 - 不是SQL大師。

我不知道是否可以以更聰明的方式完成查詢 - 我一直無法弄清楚。這裏是一個查詢的例子:

SELECT [id], [WorkTitle], [CreateDate], [UpdateDate], [Writer], [ValidFrom], 

[ValidTo], [Text] 
FROM dbo.Texts T 
WHERE Category_id = 3 AND '2012-11-06' BETWEEN ValidFrom AND ValidTo 
AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 1 AND CL.Value = '95068')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 1)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 2 AND CL.Value = 'C')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 2)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 3 AND CL.Value = 'HEL')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 3)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 4 AND CL.Value = 'CC')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 4)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 5 AND CL.Value = NULL)  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 5)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 7 AND CL.Value = '321')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 7)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 9 AND CL.Value = 'DK7778')  
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 9)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 10 AND CL.Value = 'TFS') 
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 10)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 11 AND CL.Value = 'TMP') 
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 11)) 

AND (EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 13 AND CL.Value = 'OY-VKB') 
    OR NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL WHERE T.id = CL.Text_id AND CL.Criteria_id = 13)) 

任何提示和技巧,讚賞。

乾杯 延

+0

是否有表'CL'的指數? – MoonKnight

+0

是的,我使用數據庫優化顧問爲所有表添加索引。 –

+2

你有什麼指標?你是否也可以爲兩個表添加表定義('CREATE TABLE ...')? –

回答

2
  • 對於表Texts我對(Category_id, ValidFrom) INCLUDE (ValidTo)添加索引,如果沒有一個。 (如果您已經有任何(Category_id, ValidFrom, ValidTo)(Category_id, ValidFrom)指標,它們可能過於相當不錯。

  • 對於Criteria_List表上(Text_id, Criteria_id, Value)指數很可能是不夠的優化,產生了良好的執行計劃。

    第二個選項(或者甚至更好,你必須與你的表的大小和分佈測試執行計劃和運行時間)將是兩個指標,一個在(Criteria_id, Text_id),一個在(Criteria_id, Value, Text_id)


你可以重寫10個條件這樣的 - 但索引本來也應該照顧:

WHERE Category_id = 3 AND '2012-11-06' BETWEEN ValidFrom AND ValidTo 
AND NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL 
        WHERE T.id = CL.Text_id AND CL.Criteria_id = 1 
        AND (CL.Value <> '95068' OR CL.Value IS NULL) 
       ) 
AND NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL 
        WHERE T.id = CL.Text_id AND CL.Criteria_id = 2 
        AND (CL.Value <> 'C' OR CL.Value IS NULL) 
       ) 
... 
AND NOT EXISTS (SELECT 'X' FROM dbo.Criteria_List CL 
        WHERE T.id = CL.Text_id AND CL.Criteria_id = 5 
        AND (CL.Value IS NOT NULL) 
       ) 
... 
+0

很好的答案,正是我需要的。非常感謝。 –

0

有一兩件事,我建議是改變你的數據庫設計,使您可以識別CriteriaList.value記錄,而不是它們列爲你。這將使您的查詢更加靈活,並且意味着您應該能夠擺脫所有或大部分存在/不存在並可能加速您的查詢。