淺析Entity FrameWork性能優化


                        淺析EF性能優化

1.       數據Load

延遲加載:當實體第一次讀取時,相關數據沒有加載;當第一次試圖訪問導航屬性時,所需的導航數據自動加載,EF默認使用這種方式加載數據,盡量使用預先加載和顯示加載。

優點:加載數據快

缺點:數據庫交互多次

 

預先加載:當讀取實體時,相關數據同時讀取。這通常會導致一個連接查詢,查詢所有所需的數據,使用Include方法指定預先加載。

優點: 數據庫交互少

缺點:加載實體多,數據量大時,變慢,會有很多冗余字段

 

顯示加載:這種加載方式類似於延遲加載,不同的是我們要在代碼中明確地查詢相關數據,導航屬性是手動控制的,需要調用Collection.Load方法獲取集合,調用Reference.Load方法獲取單個實體來加載相關數據。

優點: 加載數據快,導航屬性如何加載可以自己控制,通常關聯實體集合的數量被限制時,使用Load方法

缺點: 需要自己控制,數據庫交互多次,交互次數由自己控制

 

CompiledQuery提供對查詢的編譯和緩存以供重新使用。當相同的查詢需要執行很多遍的時候,那么我們可以使用ComplieQuery將查詢的語句進行編譯以便下次使用,這樣可以免去對同一語句的多次處理,從而改善性能

優點:減少查詢表達式樹編譯次數

 

AsNoTracking如果數據是只讀操作,用AsNoTracking取消追蹤,提升性能。

 

SqlQuery對於復雜的查詢或存儲過程的使用,考慮用SqlQuery操作原生sql。

 

Skip分頁在數據庫中分頁,不要再內存中分頁,以提升性能

 

IQueryableIEnumerableIQueryable返回的是查詢表達式,也就是說生成了SQL查詢語句但是卻還沒有與數據庫進行交互。IEnumerable則是已經執行查詢數據庫的操作且數據保存在了內存中,所以在進行條件拼接的時候一定要在IQueryable類型后面追加Where條件語句,而不是等到ToList之后再開始寫條件,以提升性能。

 

 

2.       數據Get

Find()方法:查找一個實體,不僅查詢數據庫,而且還查詢新添加的沒有保存到數據庫中的對象。

查找方式:內存查找->新添加還沒保存到數據庫中的對象->數據庫中還沒加載到內存中實體

優點:根據主鍵查找,主鍵有索引,速度快

缺點:只能根據主鍵查找

 

GetObjectByKey()方法:查找一個實體

查找方式:內存查找- >數據庫中實體

優點:先從內存中取速度快

缺點:只能根據主鍵查找,查詢不到拋出異常

 

TryGetObjectByKey()方法:查找一個實體

查找方式:內存查找- >數據庫中實體

優點:先從內存中取速度快 , 查詢不到返回null

缺點:只能根據主鍵查找

 

Single()方法:查找一個實體

查找方式:數據庫中實體

優點:不根據主鍵進行查詢或查詢時加載相關實體

缺點:查詢沒有返回結果或返回的結果多於一個就會拋出異常

 

SingleOrDefault()方法:查找一個實體

查找方式:數據庫中實體

優點:不根據主鍵進行查詢或查詢時加載相關實體, 查詢沒有返回結果返回null

缺點:返回的結果多於一個就會拋出異常

 

First()方法:查找一個實體,不關心是否有多個結果,僅僅取得第一條

查找方式:數據庫中實體

優點:不根據主鍵進行查詢或查詢時加載相關實體, 只取第一條

缺點:查詢沒有結果就會拋出異常

 

FirstOrDefault()方法:查找一個實體,不關心是否有多個結果,僅僅取得第一條

查找方式:數據庫中實體

優點:不根據主鍵進行查詢或查詢時加載相關實體, 只取第一條,查詢沒有結果返回null

缺點:不知道是否有多條數據

 

 

3.       其它優化

事物的簡短性:盡量把查詢語句和影響事物的語句放在事物外面執行,防止資源死鎖。

 

批量修改:盡量用sql執行

 

預生成視圖:在實體框架可以針對概念模型執行查詢或將更改保存到數據源之前,它必須生成一組本地查詢視圖才能訪問數據庫。 由於生成這些視圖會產生很高的成本,因此,您可以在設計時預生成視圖並將它們添加到項目。預生成視圖方式參考:

https://msdn.microsoft.com/zh-cn/library/bb896240.aspx

 

AsEnumerable()ToList()兩者都是延遲執行sql,區別是AsEnumerable()在執行過濾之前,先將所有數據放到內存中,再進行篩選;ToList()則是先拼接成sql再請求數據庫,然后結果放入內存,是真正的篩選數據。

 

IQueryableIEnumberableIQueryable實現了IEnumberable接口,IEnumerable<T> 泛型類在調用自己的SKip 和 Take 等擴展方法之前數據就已經加載在本地內存里了,IEnumerable跑的是Linq to Object,強制從數據庫中讀取所有數據到內存先,

而IQueryable<T> 是將Skip ,take 這些方法表達式翻譯成T-SQL語句之后再向SQL服務器發送命令,它並不是把所有數據都加載到內存里來才進行條件過濾。

 

備注:以上內容僅供參考,是EF性能優化很淺的一部分,如有錯誤大家可以一起討論。

 

更多優化請參考:https://msdn.microsoft.com/zh-cn/library/cc853327.aspx

 


免責聲明!

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



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