EntityFramework 性能優化


在談談EF的性能優化之前請允許筆者廢話幾句。雖然說筆者以前有接觸EF,但真正意義上的接觸EF算是今年的8月份吧!那時公司里面有一個產品模塊化的項目需要用到ORM。當時有兩個選擇1.EF,2.NHibernate。 說實在的兩者的口碑都不怎么樣...最后我還是支持了下微軟的EF,畢竟做.Net開發用自家的會方便很多把。一開始在網上查得的一些博文會說EF各種性能不好!(PS:今天跟客戶談項目的時候又被噴了)不過我還是傻里傻氣的保持樂觀的態度,性能不好就想辦法讓它好起來!!!不做怎么知道呢!下面我一些優化的方案一一列舉出來(目前只總結了查詢),寫的不准確的地方,還希望大家能夠指出來。

說到EF性能優化不得不說一個工具MiniProfiler,(不過也可以直接用Sqlserver profiler)MiniProfiler是StackOverFlow團隊設計的一款對.net的性能分析小程序。在這里我們可以使用MiniProfiler嵌入頁面查看頁面處理的周期和Sql語句執行的周期及Sql語句

可以通過以下步驟來使用它:(環境.NET4.0 + EntityFramewrok4.4)

1.通過Nuget下載MiniProfiler和MiniProfiler.EF (MiniProfiler.EF5兼容EntityFramework5.0以下的版本)

2.修改Global.asax文件,添加如下代碼

protected void Application_Start()
{
    //SQL跟蹤
    StackExchange.Profiling.MiniProfilerEF.Initialize();
}

protected void Application_BeginRequest() 
{
    MiniProfiler.Start();
}

protected void Application_EndRequest() 
{
    MiniProfiler.Stop();
}

3.在需要調試的頁面中使用它,需要在_Layout.cshtml添加MiniProfiler的引用(我這里使用的是ASP.NET MVC)

//引用
@using StackExchange.Profiling
//Body
@MiniProfiler.RenderIncludes()

若是在頁面中出現如下畫面就表示MiniProfiler已經配置成功了,可以正式進入優化的環節了!!!




具體解決問題我總結了下有幾個方案:

1.使用EntityFramework5及以上的版本代替EF4.0及以下的版本(使用.Net4.0的可以略過)
2.禁用延遲加載

默認情況下,延遲加載被支持,如果你希望禁用它,必須顯式聲明,最好的位置是在 DbContext 的構造器中。

public MyContext() 
{ 
    this.Configuration.LazyLoadingEnabled = false; 
} 

因為若使用延遲加載,每次我們需要訪問屬性的時候都會訪問數據這樣累加起來的開銷是很大的。

3.使用貪婪加載(又叫預加載就是數據庫的多表查詢)
這點其實也跟上面的一樣響應了一個原則盡量的減少數據庫的訪問次數

articles = dbContext.Articles.Include("Category");


4.盡量在sql語句拼湊好的時候進行ToList()或者遍歷IQueryable<T>,因為一旦調用IQueryable<T>就相當於進行的數據庫的查詢
錯誤寫法:

dbContext.Articles.ToList().Where(u=>u.id==1);

正確寫法:

dbContext.Articles.Where(u=>u.id==1).ToList();

這些寫法的意思就是把數據拼湊好,再訪問數據庫。不然就成了從數據庫獲取全部數據就再過濾,假如數據庫有幾萬甚至幾十萬數據。那就不得了了!
這里再提供一個篩選+分頁的寫法(很好用)

var model =
dbContext.MyModules.OrderByDescending(u => u.CreateTime).Skip((pageInfo.PageIndex - 1) * pageInfo.PageSize).Take(pageInfo.PageSize).Select(u => new
{
    u.ID,
    u.Name,
    u.Version,
    u.TagList,
    u.UserID,
    u.DownLoadTimes,
    u.CreateTime
}).ToList();


5.緩存數據
盡量把頻繁用到的數據一次性加載到內存當中,適應一些頻繁調用數據庫進行計算的功能(好像跟第4調有些沖突,但是又的時候減少數據庫訪問次數反而更好。具體問題具體分析了)
我項目中有個導航菜單就是頻繁的訪問數據庫導致性能低下(一開始得到1級菜單,然后通過1級獲取2級菜單,2級獲取3級....)
解決方法就是一次性把所有數據載入內存,然后通過內存進行檢索,時間馬上就降了3s左右。相對這種情況其實還是比較多的!


說了這么多,總結一下就兩點:
1.保證拼湊的sql語句性能要高
2.減少數據庫的訪問次數

可能大牛覺得這估計都是廢話!不過這些方法還是挺適合中下階級的。
不足的以后再補充~!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM