前幾天是臨危受命,跟著師哥一起解決資料查詢太慢的問題。最近時間太少,沒有靜下心來好好總結一下,都過了乙個多星期了,再不寫點東西就快忘了。- -
一開始的時候我們都認為資料查詢太慢是wcf傳輸得問題,所以師哥帶著我們從最簡單的開始,把現在用的框架逐個擊破。我們的框架使用ef進行對資料庫的操作,首先就分成了兩組,一組做使用ef查詢的demo,一組使用ado.net寫了乙個sqlhelper進行查詢。
這兩組查詢的結果,總共60萬條資料,全部查詢出來都是10秒多一點,
從監控的時間來看是差不多的,ef會慢一點。之後進行了分頁查詢模擬,僅在60萬條資料中查詢前10條,檢測到的資料在零點幾秒,時間差很小可以忽略不計。
到這裡我們確定了,查詢緩慢並不是使用了ef的問題,再然後我們在前兩個demo的基礎上加入了wcf,再次測試之後,發現就算是經過wcf,查詢的速度僅僅比不用wcf多了1秒。現在看來,並不是wcf的問題,那麼問題到底在哪呢?
我們在專案中使用的查詢,是繼承了底層封裝好的查詢功能,那麼我們就直接使用了現在系統中的底層查詢方法。結果很奇怪,在更換了基礎的資料庫之後,裡面總共有4萬條資料,查詢所有資料的時間是6秒,而查詢前10條的結果卻是26秒,查詢前十條資料怎麼會比查詢所有的還慢呢?而且還慢了20秒。
那麼現在我們的眼光就訂到了底層的分頁查詢上了,詢問了熟悉底層方法的人了解到了乙個情況,底層從來沒有實現分頁查詢,從來都是查詢出來多有的資料,然後根據分頁擦查詢的引數進行篩選,選出應該看到的那十條資料,換句話說,假分頁。
如果我們不用底層呢?直接使用ef進行查詢,查詢條件都一直的情況下,查出10條的時間是2秒多。現在看來,是底層的問題。
根據師哥的指導,我們分別對使用底層和不使用底層兩種查詢方式,進行了資料庫的監測,看了一下ef發給sql server的語句。
使用底層查詢的sql語句是這樣的。
select
[extent1].[operator] as [operator],
[extent1].[timestamp] as [timestamp],
[extent1].[isenabled] as [isenabled],
[extent1].[onclassstudentid] as [onclassstudentid],
[extent1].[onclassid] as [onclassid],
[extent1].[studentid] as [studentid]
from[dbo].[basiconclassstudententities] as [extent1]
很明顯能讀出來這個是查詢所有的資料。而是用ef進行查詢的語句是這樣的。
select top (10)
[extent1].[operator] as [operator],
[extent1].[timestamp] as [timestamp],
[extent1].[isenabled] as [isenabled],
[extent1].[onclassstudentid] as [onclassstudentid],
[extent1].[onclassid] as [onclassid],
[extent1].[studentid] as [studentid]
from ( select [extent1].[operator] as [operator], [extent1].[timestamp] as [timestamp], [extent1].[isenabled] as [isenabled], [extent1].[onclassstudentid] as [onclassstudentid], [extent1].[onclassid] as [onclassid], [extent1].[studentid] as [studentid], row_number() over (order by [extent1].[studentid] asc) as [row_number]
from [dbo].[basiconclassstudententities] as [extent1]
) as [extent1]
where [extent1].[row_number] > 159990
order by [extent1].[studentid] asc
現在看來就有點眉目了,查詢的條件沒有傳給ef,但是為什麼查詢出來的結果依然是正確的呢?這個當時是沒有解決的乙個疑問,之後我會說明,繼續我們的故事。
這個時候,我又嘗試了一次條件查詢,發現查詢的結果是一樣的,資料庫監控到的是查詢所有,但是返回的結果就只用那麼幾條資料,兩個方法相同的引數有乙個,lambda表示式。
當我們使用lambda表示式進行查詢的時候,如果直接給ef,那麼ef會根據這個表示式生成sql語句。而是用底層的時候lambda表示式出了問題,沒有被識別,就說明了傳遞引數的過程中出現了問題,引數傳遞的不對。
之後我們進行了資料查詢,最終得到了解決的方案,在傳遞lambda表示式的時候,引數型別使用的是func,當我們把這個引數型別改為expression>,問題解決了,秒查。
這兩天我在做總結,發現了一片同樣的部落格,內容也是這個,裡面解釋了為什麼會查詢所有。
將func型別的變數作為引數傳給where方法進行linq查詢時,enitity framework會產生全表查詢,將整個資料庫表中的資料載入到記憶體,然後在記憶體中根據where中的條件進一步查詢。(
我們遇到的所有問題都是有人遇到的,解決不了不是什麼問題,但是我們一直忍受著緩慢的查詢就是我們的問題了,還記得老師說過不將就是發現的原動力,這次3.0的專案中我們將就了那麼長時間,最終也只是乙個簡單的小問題,哎,都把老師說得話都忘了啊。
下次總計總結expression>和func到底都是什麼意思,看看為什麼這兩個會引起查詢上的區別。
GOF23之備忘錄模式
在不破壞封裝的前提下,捕獲乙個物件的內部狀態,並在該物件之外儲存這個狀態,這樣可以在以後將物件恢復到原先儲存的狀態 棋類遊戲中的悔棋操作 普通軟體中的撤銷 事務管理中的回滾操作 原發器 originator 他是乙個普通類,可以建立乙個備忘錄,並儲存他的內部狀態,也可以使用備忘錄來恢復其內部狀態,一...
B S備忘錄14 IIS新增MIME型別
搬得差不多了,最近發布wcf服務端的時候又是遇到了svc打不開的情況,記得最早的時候遇到過這個問題,後來解決了就忘了,重灌了電腦之後又出現了。wcf錯誤 無法啟用服務,因為它不支援 asp.net 相容性。已為此應用程式啟用了 asp.net 相容性。請在 web.config 中關閉 asp.ne...
B S備忘錄19 就說多查查有好處
放假之前接了個大活,說是要把工作流做活,做到登陸的學生提交申請,提交給老師,這個老師是根據組織結構查出來的。其實這個是基礎系統自己的邏輯,查詢資料而已,當時並沒有多放多少精力在這上面。重點是另外乙個,怎麼把工作流執行的業務做靈活,具體要求就是改變繫結的業務時,不要改 起碼不要改基礎內部的 這個就感覺...