ADONET團隊最近討論了ADONET Entity框架的各種性能特征ADONET Entity框架在月已經進入它的第三個beta版本自那時起開發團隊就開始為開發人員提供了使用該框架的相關信息而現在則為開發人員提供了框架性能方面的信息
本文鞭辟入裡地介紹了ADONET Entity框架的性能演示了如何提高簡單查詢速度的方法並闡釋了框架的性能特征
需要重點指出的是當一個抽象層或者類似EDM(譯注指Entity Data Model)的模塊被用來轉換數據庫的關系樣式時會帶來一定的性能損失
查詢與結果
本文使用了NorthWind數據庫作為模型並創建了一個簡單查詢
(NorthwindEntities ne = NorthwindEntities()) { (Order o ne
Orders) { i = o
OrderID; } }
測試時我們的每個查詢對整個行數據進行了次遍歷結果很有意思第次運行時耗費了毫秒而接下來的每次運行則平均耗費毫秒左右的時間最耗時的一部分內容是ObjectContext的創建而在執行任意一個訪問數據庫的操作時都會有一些耗時的操作發生
每次操作的百分比值可以給我們一些啟示
裝載元數據(%)
初始化元數據(%)
打開連接(%)
生成視圖(%)
裝載程序集(%)
跟蹤(%)
實例化(%)
其它(%)
耗時百分比值最大的是視圖生成它達到了驚人的%既然視圖生成是造成性能損耗的罪魁禍首那麼開發人員最好是使用命令行工具EDM生成器(EdmGenexe)運行時需要加上視圖生成命令參數(/mode:ViewGeneration)它的輸出內容為一個代碼文件(C#或者VBNET)可以包含在項目中視圖的預生成可以將啟動時間降低到毫秒而對於循環遍歷操作整個時間可以降低%生成視圖並隨著應用程序一起發布是提高性能的妙方但其缺點則在於視圖不再是動態的一旦模型發生改變就需要重新生成以保持同步
查詢性能
需要指出的是關於性能的主要設計要素是查詢緩存一旦執行了查詢它的一部分內容就被維持在全局緩存中由於查詢與元數據緩存的存在使得第二次運行的執行速度總是比第一次運行快例如如下的Entity SQL查詢
(PerformanceArticleContext ne = PerformanceArticleContext()) { ObjectQuery<Orders> orders = ne
CreateQuery<Orders>(); (Orders o orders) { i = o
OrderID; } }
第一次運行該查詢耗時毫秒但下一次運行則只耗費了毫秒的時間首次運行與後續運行在執行方面的區別在於它構建了能夠為執行傳遞provider的命令樹(command tree)
LINQ查詢在執行方式上與Entity SQL查詢相似例如下面的查詢
(PerformanceArticleContext ne = PerformanceArticleContext()) { var orders = from order ne
Orders select order; (Orders o orders) { i = o
OrderID; } }
首次執行LINQ查詢耗時毫秒而隨後的執行耗時毫秒兩者的差距還要低於Entity SQL可以看到使用編譯了的LINQ查詢對於性能的提高更為明顯編譯LINQ查詢的好處在於它構建了表達樹(expression tree)當查詢被編譯時後續的執行就不需要重建表達樹了編譯的LINQ查詢代碼看起來像這樣
Func<PerformanceArticleContext
IQueryable<Orders>> compiledQuery = CompiledQuery
Compile((PerformanceArticleContext ne) => (from o ne
Orders select o)); (PerformanceArticleContext ne = PerformanceArticleContext()) { (Orders o compiledQuery(ne)) { i = o
OrderID; } }
注意PerformanceArticleContext是一個委托對於編譯了的LINQ查詢而言第一次執行耗時毫秒而隨後的執行時間則為毫秒結果並不驚人值得關注的是編譯的LINQ查詢比之常規方式的LINQ查詢執行時間少了毫秒或許對於幾個查詢而言這算不上什麼但如果有數以千計的查詢這樣的性能提升就倍顯價值所在了
ADONET團隊建議開發人員在查詢中應謹慎使用Track/NoTrack選項
在之前的例子中所有放在對象創建中的查詢結果都被添加到ObjectStateManager中因此我們能夠跟蹤它們的更新如果沒有必要跟蹤對象的更新和刪除那麼最好是使用NoTracking合並項例如在一個ASPNET Web應用程序中如果它要查詢一個指定的分類名稱但卻不需要對返回的數據進行更新那麼NoTracking就會是一個不錯的選擇在這種情形下使用NoTracking的查詢會在性能方面得到改善
基於前面的一組數字NoTracking選項能夠大幅度地降低執行的時間而其中性能的提升主要源自於我們停止了對變更的跟蹤以及對關系的管理如果使用NoTracking查詢無論是第一次執行還是隨後的執行編譯的LINQ查詢都要優於標准的LINQ查詢注意編譯的LINQ查詢的第二次執行與Entity SQL查詢的第二次執行相等
ADONET團隊同時還提醒開發者在創建查詢時有一些內容必須銘記於心
在Entity框架中優化查詢性能時應該針對特定的編程場景做出最佳選擇這裡列舉了幾個關鍵項
ObjectContext的首次創建包含了裝載和驗證元數據的性能損耗
任何一個查詢的首次執行都包含了構建一個查詢緩存的性能損耗以利於提高後續查詢的執行速度
編譯的LINQ查詢比未編譯的LINQ查詢要快
如果不需要跟蹤數據的變更與數據的關系或者對大數據對象進行流操作那麼通過NoTracking合並項執行查詢效果會更佳
From:http://tw.wingwit.com/Article/program/net/201311/15140.html