如何減少 Entity Framework 4 查詢編譯時間?
摘要:我們遇到了 EF4 查詢編譯時間超過 12 秒的問題。記憶體查詢只能讓我們走這麼遠;有什麼方法可以真正減少編譯時間?有什麼我們可能做錯的事情我們可以尋找嗎?謝謝!
我們有一個通過 WCF 服務公開的 EF4 模型。對於我們的每個實體類型,我們公開了一個方法來獲取和返回整個實體以進行顯示/編輯,包括許多引用的子對象。
對於一個特定實體,我們必須 .Include() 31 個表/子表來返回所有相關數據。不幸的是,這使得 EF 查詢編譯速度非常慢:編譯和建構一個 7,800 行、300K 的查詢需要 12-15 秒。這是 Web UI 的後端,需要比這更敏捷。
我們能做些什麼來改善這一點嗎?我們可以 CompiledQuery.Compile 這個 - 在第一次使用之前不會做任何工作,因此有助於第二次和隨後的執行,但我們的客戶擔心第一次使用也不應該很慢。同樣,如果託管 Web 服務的 IIS 應用程序池被回收,我們將失去記憶體計劃,儘管我們可以增加生命週期以最小化這種情況。此外,我看不到提前預編譯和/或序列化 EF 編譯查詢記憶體(缺少反射技巧)的方法。CompiledQuery 對象僅包含對記憶體的 GUID 引用,因此它是我們真正關心的記憶體。(寫出來這件事發生在我身上,我可以從 app_startup 在後台啟動一些東西來執行所有查詢以編譯它們 - 這安全嗎?)
但是,即使我們確實解決了這個問題,我們也會根據我們正在搜尋的參數使用 LINQ-to-Entities 子句動態建構搜尋查詢:我認為 SQL 生成器做得不夠好,我們可以移動所有這些邏輯都進入 SQL 層,所以我認為我們不能預編譯我們的搜尋查詢。這不太嚴重,因為搜尋數據結果使用較少的表,因此編譯時間僅為 3-4 秒而不是 12-15 秒,但客戶認為最終使用者仍然無法接受。
所以我們確實需要以某種方式減少查詢編譯時間。有任何想法嗎?
- Profiling 指向 ELinqQueryState.GetExecutionPlan 作為開始的地方,我試圖介入,但沒有真正的 .NET 4 源可用,我無法走得很遠,Reflector 生成的源不會讓我介入函式或在其中設置斷點。
- 該項目是從 .NET 3.5 升級的,因此我嘗試在 EF4 中從頭開始重新生成 EDMX,以防萬一出現問題,但這並沒有幫助。
- 我已經嘗試過這裡宣傳的 EFProf 實用程序,但它看起來並沒有幫助。無論如何,我的大型查詢會使它的數據收集器崩潰。
- 我已經通過 SQL 性能調整執行了生成的查詢,它已經有 100% 的索引使用率。我看不出數據庫有什麼問題會導致查詢生成器出現問題。
- 執行計劃編譯器中是否存在 O(n^2) 的內容 - 是否將其分解為單獨的數據載入塊,而不是一次可能有幫助的所有 32 個表?將 EF 設置為延遲載入沒有幫助。
- 我已經購買了 O’Reilly Julie Lerman EF4 的預發行書,但除了“編譯您的查詢”之外,我無法在其中找到任何幫助。
我不明白為什麼需要 12-15 秒才能在 32 個表中生成單個選擇,所以我很樂觀,還有一些改進的餘地!
感謝您的任何建議!我們在 SQL Server 2008 上執行以防萬一,而 XP / 7 / server 2008 R2 使用 RTM VS2010。
讓您的查詢更簡單。嚴重地; 查詢複雜度和編譯時間之間幾乎呈線性關係。兩個簡單的查詢通常比一個真正複雜的查詢快得多(即使是預編譯的!)。如果速度是最終目標,請選擇最快的選項。
您可以為一些更複雜的查詢創建一個視圖,從而完全控制 SQL。然後將該視圖包含在您的數據模型中。