現在工作中很少使用原生的sql了,大多數的時候都在使用EF。剛開始的時候,只是在注重功能的實現,最近一段時間在做服務端接口開發。開發的時候也是像之前一樣,鍵盤噼里啪啦的一頓敲,接口秒秒鍾上線,但是到聯調測試的時候就悲劇了。。。。那叫一個慢啊,客戶端有種“千年等一回的趕腳” 。由於訪問量和數量都提升了一個數量級,之前沒有 考慮過的問題,都在此時暴露了,根據自己百度、google的經歷實踐,整理了這一些優化點。歡迎各位大神批評指正!
1.使用AsNoTracking(),無跟蹤查詢,查詢出的數據不可以修改,但是可以提高查詢速度
2.合理使用延遲加載。
如果用不到導航屬性中的數據,那么使用懶加載就行了,不會加載不需要的數據到內存中。但是,如果會在 foreach 中使用導航屬性中的數據,那么最好是禁用懶加載,通過Include()方法,一次加載全部數據,防止在 foreach 多次和數據庫進行交互。當然,一般情況下是這樣的,具體的還是要根據當時的業務情況而定。
3.判斷List中是否含有數據的時候,最好使用Any(),避免使用Count()>0,這么Low的方式,真是慢的一逼啊。
4.在where子句中進行中文字符模糊匹配值的時候,記得加上使用DbFunctions.AsNonUnicode("要匹配的字符")。
5.錯誤的使用OrderBy() 導致的錯誤排序。
要對多個字段進行先后組合排序的時候,正確的是Orderby().ThenBy();切記不要這樣啊:OrderBy().OrderBy(),這樣達不到你想要的效果,只會按照最后的那個排序字段進行排序。
6.真假分頁的問題
line1:query.ToList().Skip((PageIndex - 1) * PageSize).Take(PageSize); line2: query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();
line1就是加分頁,直接從DB中取出全部的數據,然后在內存中進行分頁;line2才是真正分頁。沒有ToList()的時候,返回值類型還是IQueryable<T> ,執行了ToList(),之后直接查詢數據庫了,返回值類型直接是IEnumerable<T>。
7.按需加載部分列。
通過在Select子句中使用select(t=>{t.id,t.name}),只加載需要的列來提升速度。
8.使用擴展庫Entity Framework Extendeds 進行批量Insert和delete操作,避免生成大量的sql語句和數據庫進行多次交互。
9.這些做了,性能還是不行?那SqlQuery(),或者通過儲存過程,將多條sql語句作為一個提交單元,也可以減少與數據庫的交互次數,從而提高性能。
對於EF首次啟動慢的問題,可通過下面的措施進行優化:
1.EF的預熱問題,在應用程序進行初始化的時候就事先進行預熱。比如,mvc應用程序可在global文件中添加如下操作。
protected void Application_Start() { using (var ctx = new mcccEntities()) { var objectContext = ((IObjectContextAdapter)ctx).ObjectContext; var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace); mappingCollection.GenerateViews(new List<EdmSchemaError>()); } //記得,連接了幾個DB就要寫幾個using啦。 }
