天天看點

疑難雜症——關于EntityFramework的SqlQuery方法的執行效率差異的探讨

前言:最近項目上面遇到一個問題,在Code First模式裡面使用EntityFramework的SqlQuery()方法查詢非常慢,一條資料查詢出來需要10秒以上的時間,可是将sql語句放在plsql裡面執行,查詢時間基本可以忽略不計。折騰了半天時間,仍然找不到原因。最後通過對比和原始Ado的查詢方式的差異找到原因,今天将此記錄下。

本文原創位址:http://www.cnblogs.com/landeanfen/p/8392498.html

其實問題很簡單,上面前言已經描述過。就是一個多表的聯合查詢,沒有什麼特殊的文法。大緻代碼如下:(PS:不要問為什麼用了EF還要使用sql語句,你就當這是個梗!)

通用的sql語句查詢方法

然後在外層調用這個方法

然後查詢,每次得到的結果都是一條記錄,但是卻需要10秒以上,可能你不相信,但這是真的!

問題就這麼個問題,沒辦法,出現了問題就要想辦法解決。

我們将SqlQuery<T>()方法轉到定義,最終發現它是EntityFramework.dll裡面的方法。

疑難雜症——關于EntityFramework的SqlQuery方法的執行效率差異的探讨

既然轉到定義已經找不到任何突破口,那我們正常的做法就隻有對比了。然後部落客在本地定義了一個對比的例子。

疑難雜症——關于EntityFramework的SqlQuery方法的執行效率差異的探讨
疑難雜症——關于EntityFramework的SqlQuery方法的執行效率差異的探讨

GetListByDataTable

然後在控制台裡面分别調用。

得到結果:

疑難雜症——關于EntityFramework的SqlQuery方法的執行效率差異的探讨

差别有多大大家可以自行腦補。

既然結果差别這麼大,而sql語句在plsql裡面執行又如此快,那麼問題自然而然轉到了對象序列化的身上了。也就是說這個SqlQuery()方法實際上可以分為兩個步驟:第一步是查詢得到DataTable之類的對象,然後第二步是将DataTable之類的對象轉換為List<T>,既然我們第一步沒有任何效率問題,那麼問題肯定就在第二步上面了。

既然初步判斷是對象轉換的問題,将TestModel這個對象轉到定義一看,我地個乖乖,一百來個屬性,于是更加堅信自己的分析是正确的。接下來,部落客将這一百個字段減少到50個,再次執行發現效率提高了不少,基本在3秒左右,再減少到隻剩20個字段,查詢時間基本在毫秒級别。原來真是反射指派的效率問題啊。至于項目為什麼會有100個字段的對象,部落客也沒有想明白,或許真的需要吧!但是由此我們可以得出如下經驗:

1、查詢的sql語句裡面盡量不要用select * 這種文法,尤其是連表的時候,如果你用了select * ,那有時真的就傷不起了!

2、如果确定實體裡面真的有那麼多字段有用(極端的情況),就不要用SqlQuery()了,而改用原生的Ado+DT轉List<T>的方式。

本來以為找到了原因了,正要下結論的時候。聽到另一個同僚傳來了不同的聲音:騙紙,你的這個測試程式在我這裡跑這麼快,哪裡有你說的10秒以上!去他那邊瞅了一眼,吓我一跳,哪裡有什麼效率問題,簡直快得不要不要的!這就尴尬了,同樣的程式,在我這邊怎麼這麼慢呢?

最後對比一圈下來,發現他那邊用的Visual Studio的版本是2017,而我這邊是2015。難道真是IDE的環境問題?部落客不甘心,在本機裝了一個2017,運作程式,依然快得吓人。而關掉2017,再用2015跑,同樣需要10秒左右,而且找到其他裝了VS 2013的電腦,用2013運作,依然需要10秒左右。好像2017以下的版本速度都會有一些影響。對比各個主要dll的版本,最終找不到任何不同。到這裡,部落客也沒有辦法了。如果哪位有解,感謝賜教!

那就用2017呗,這是最後得出的結論!!!

以上針對最近遇到的一個問題做了一些記錄。如果大家有不同的意見,歡迎交流和斧正!

本文原創出處:http://www.cnblogs.com/landeanfen/

歡迎各位轉載,但是未經作者本人同意,轉載文章之後必須在文章頁面明顯位置給出作者和原文連接配接,否則保留追究法律責任的權利

EF