2015-06-01 61 views
1

我有這樣的LINQ查詢,查詢保留做任何表中的任何改變歷史構造像這樣的表:工作LINQ查詢,但性能下降

History (Primary Key) | Table_Name | Primary_Key | Field_Name | Old_Value | New_Value | Action_Type | Action_Date | Action_User 

LINQ查詢我有一個查詢該表是這樣的:

var complaintHistory = from histories in DbContext.Histories 
             where ((from c in taskIds 
               select "<Task_ID=" + c + ">").Contains(histories.Primary_Key) || 
               (from c in notificationListIds 
               select "<Notification_List_ID=" + c + ">").Contains(histories.Primary_Key) || 
               (from c in emailSentIds 
               select "<Email_Sent_ID=" + c + ">").Contains(histories.Primary_Key) || 
                histories.Primary_Key == "<Complaint_ID=" + Complaint.Complaint_ID + ">") && 
                histories.Field_Name != "rowversion" 
             select histories; 

每當我調用這個查詢時,我都會有嚴重的延遲。這個linq查詢可以重新編寫以顯着提高性能嗎?還是我想在沒有槳的情況下去爬溪?

+1

這對於http: //codereview.stackexchange.com/ –

+0

哦?這個問題對於這個問題是不恰當的嗎? –

+0

我有點困惑,因爲還有其他關於LINQ查詢優化的問題。 –

回答

3

當性能不佳時,總是先查看生成的SQL。你會看到這很可怕。它包含許多單行表格,其中包含字符串from c in taskIds select "<Task_ID=" + c + ">"等。

請記住,整個查詢被翻譯成SQL。如果你只擁有...

where taskIds.Contains(histories.Primary_Key) 

...等等,那麼這些謂詞可能已被翻譯成IN語句。在您的查詢中,組成字符串"<Task_ID=" + c + ">"必須構建在笨重的SQL中。這足以拉下查詢優化器。此外,taskIds中的元素數量極大地影響性能,並且不需要很多元素(〜50)來觸及最大嵌套級別。

嘗試第一件事是由第一這樣做你自己建立這些組成串緩解數據庫引擎:

var task_Ids = (from c in taskIds 
       select "<Task_ID=" + c + ">").ToArray(); 

而且

where task_Ids.Contains(histories.Primary_Key) 

同其他兩個ID列表。

如果taskIds不包含太多的元素(不數千),您也可以構建包含三個字符串組成一個列表:

var ids = (from c in taskIds select "<Task_ID=" + c + ">") 
       .Union(
       (from c in taskIds select "<Notification_List_ID="" + c + ">")) 
       .Union(
       (from c in taskIds select "<Email_Sent_ID=" + c + ">")) 
       .ToArray(); 

,並且只使用一個Contains聲明。

更重要的是,我認爲你不應該以這種形式存儲主鍵。它混合了數據和特定的演示實現(本身足夠邪惡),並且不必要地使查詢複雜化。如果Primary_Key本來就是一個簡單的值,等於原始記錄,可能是在類型字段確定爲Task,Notification等的組合鍵中。

1

就像人們提到的那樣,CR可以給你徹底的表現評論。但這是第一次戳。

從您的LINQ查詢,它看起來像一條直線向前確認這樣的:

「給我所有的歷史記錄,其中字段名稱不是‘rowversion’和主鍵要麼(投訴編號或電子郵件發送ID,通知ID或任務ID列表'

從linq-to-sql的角度來看,'contains'子句是唯一棘手的部分,但LInq-to-sql足夠智能翻譯將它帶入具有值的SQL IN子句中。

所以最終的SQL查詢應該做3 IN檢查。不應該是SQL的問題。

只要Primary_key列被索引(從名稱開始,我假設它是,因爲主鍵是集羣索引的)並且可能還有'Field_name'列,查詢看起來很好。

嘗試捕獲SQL事件探查器中的查詢,並在SQL管理工作室中運行它並查看執行計劃。