如何“熱身”實體框架?什麼時候“冷”?
不,我第二個問題的答案不是冬天。
前言:
我最近一直在對 Entity Framework 進行大量研究,一直困擾我的是它在查詢未預熱時的性能,即所謂的冷查詢。
我瀏覽了 Entity Framework 5.0 的性能注意事項文章。作者介紹了暖和****冷查詢的概念以及它們之間的區別,我自己也注意到了這一點,但並不知道它們的存在。在這裡可能值得一提的是,我背後只有六個月的經驗。
現在我知道如果我想在性能方面更好地理解框架,我還可以研究哪些主題。不幸的是,Internet 上的大多數資訊都已過時或帶有主觀性,因此我無法找到有關暖與冷查詢主題的任何其他資訊。
到目前為止,我基本上註意到的是,每當我必須重新編譯或回收命中時,我的初始查詢都會變得非常慢。正如預期的那樣,任何後續數據讀取都很快(主觀)。
我們將遷移到 Windows Server 2012、IIS8 和 SQL Server 2012,作為一名初級學生,我實際上為自己贏得了在其餘時間之前測試它們的機會。我很高興他們引入了一個預熱模組,可以讓我的應用程序為第一個請求做好準備。但是,我不確定如何繼續預熱我的實體框架。
我已經知道值得做的事情:
- 按照建議提前生成我的意見。
- 最終將我的模型移動到一個單獨的組件中。
通過常識,我考慮做的事情可能是錯誤的方法:
- 在應用程序啟動時讀取虛擬數據以預熱、生成和驗證模型。
問題:
- 在任何時候在我的實體框架上獲得高可用性的最佳方法是什麼?
- 在什麼情況下實體框架會再次“變冷”?(重新編譯、回收、IIS重啟等)
- 在任何時候在我的實體框架上獲得高可用性的最佳方法是什麼?
您可以混合使用預生成的視圖和靜態編譯查詢。
靜態CompiledQuery很好,因為它們編寫起來既快速又容易,並且有助於提高性能。但是,對於 EF5,沒有必要編譯所有查詢,因為 EF 會自動編譯查詢本身。唯一的問題是這些查詢在記憶體被掃描時可能會失去。因此,您仍然希望保留對您自己編譯的查詢的引用,這些查詢僅發生非常罕見,但代價高昂。如果您將這些查詢放入靜態類中,它們將在首次需要時進行編譯。對於某些查詢,這可能為時已晚,因此您可能希望在應用程序啟動期間強制編譯這些查詢。
正如您提到的,預生成視圖是另一種可能性。特別是對於那些需要很長時間編譯並且不會改變的查詢。這樣,您就可以將性能成本從執行時轉移到編譯時。這也不會引入任何滯後。但是當然這種變化會傳遞到數據庫,所以處理起來並不容易。程式碼更靈活。
不要使用大量的 TPT 繼承(這是 EF 中的一般性能問題)。既不要將繼承層次結建構構得太深也不要太寬。只有 2-3 個特定於某個類的屬性可能不足以要求自己的類型,但可以作為現有類型的可選(可為空)屬性處理。
不要長時間堅持單一的上下文。每個上下文實例都有自己的一級記憶體,當它變大時會降低性能。上下文創建很便宜,但上下文記憶體實體內的狀態管理可能會變得很昂貴。其他記憶體(查詢計劃和元數據)在上下文之間共享,並將與 AppDomain 一起消失。
總而言之,您應該確保頻繁分配上下文並僅在短時間內使用它們,以便您可以快速啟動應用程序,編譯很少使用的查詢並為性能關鍵且經常使用的查詢提供預生成的視圖。
- 在什麼情況下實體框架會再次“變冷”?(重新編譯、回收、IIS重啟等)
基本上,每次您失去 AppDomain 時。IIS 每29 小時執行一次重新啟動,因此您永遠無法保證您的實例會存在。同樣在一段時間沒有活動後,AppDomain 也會關閉。你應該嘗試再次快速上來。也許您可以非同步進行一些初始化(但要注意多執行緒問題)。您可以在沒有請求阻止 AppDomain 死亡時使用計劃任務來呼叫應用程序中的虛擬頁面,但最終會。
我還假設當您更改配置文件或更改程序集時,將會重新啟動。