微軟linq技術已經出現很久,很多公司已經開始商業使用,作為我們暫時沒有用到的人來說,也應該適當的了解下相關知識,但是直到目前網絡上對他的看法仍然是褒貶不一,當然任何事情都不可能完美的,下面就針對大多數人比較關注的效率問題做一次試驗,來實實在在的用事實說次話,(由於過年在家無事突發奇想做的試驗也沒用到專業測試工具,但就大體而言,能說明問題就夠了)
聲明:本測試全部原創,屬於個人愛好測試,如轉載,希望保留作者,另外,如不認同或專業使用可另行測試
測試目的:主要是測試兩者的時間區別
測試者:石曼迪(shiyeping@163.com)
測試環境:
CPU:奔騰雙核T3400(2.16G) 內存:2G 667 硬盤:160G 操作系統:XP SP3 編譯工具:vs 2008+mssql 2005 |
測試依據(非專業精密工具):
Stopwatch 類 提供一組方法和屬性,可用於准確地測量運行時間。 Stopwatch 實例可以測量一個時間間隔的運行時間,也可以測量多個時間間隔的總運行時間。在典型的 Stopwatch 方案中,先調用 Start 方法,然后調用 Stop 方法,最后使用 Elapsed 屬性檢查運行時間。 Stopwatch 實例或者在運行,或者已停止;使用 IsRunning 可以確定 Stopwatch 的當前狀態。使用 Start 可以開始測量運行時間;使用 Stop 可以停止測量運行時間。通過屬性 Elapsed、ElapsedMilliseconds 或 ElapsedTicks 查詢運行時間值。當實例正在運行或已停止時,可以查詢運行時間屬性。運行時間屬性在 Stopwatch運行期間穩固遞增;在該實例停止時保持不變。 默認情況下,Stopwatch 實例的運行時間值相當於所有測量的時間間隔的總和。每次調用 Start 時開始累計運行時間計數;每次調用 Stop 時結束當前時間間隔測量,並凍結累計運行時間值。使用 Reset 方法可以清除現有 Stopwatch 實例中的累計運行時間。 Stopwatch 在基礎計時器機制中對計時器的刻度進行計數,從而測量運行時間。如果安裝的硬件和操作系統支持高分辨率性能的計數器,則 Stopwatch 類將使用該計數器來測量運行時間;否則,Stopwatch 類將使用系統計數器來測量運行時間。使用 Frequency 和 IsHighResolution 字段可以確定實現 Stopwatch 計時的精度和分辨率。 Stopwatch 類為托管代碼內與計時有關的性能計數器的操作提供幫助。具體說來,Frequency 字段和 GetTimestamp 方法可以用於替換非托管 Win32 APIQueryPerformanceFrequency 和 QueryPerformanceCounter。
|
測試前准備:
新建一個數據庫:SpeedTest,插入500萬條記錄用時38分57秒,最終數據庫大小:213M
見表語句如:
CREATE TABLE Tab( Id int IDENTITY(1,1) NOT NULL, Context nvarchar(50) NOT NULL, DoTime datetime NOT NULL ) |
測試代碼見附件
插入語句如:
declare @i int,@start datetime,@end datetime set @i=0 set @start=getdate() while(@i<5000000) begin insert into tab(context,dotime)values('值:'+convert(varchar(20),rand()*10*rand()),getdate()) set @i=@i+1 end set @end=getdate() print '插入500萬條數據用時:'+convert(varchar(20),datediff(ms,@start,@end)) |
第一輪測試——查詢
查詢第100000到120000條數據中的長度為8的數據
查詢用SQL語句如:
--查詢第到條數據中的長度為的數據 declare @start datetime,@end datetime set @start=getdate() select * from ( select top 20000 * from tab where id not in(select top 100000 id from tab)) as t where len(t.Context)=8 set @end=getdate() print '插入萬條數據用時:'+convert(varchar(20),datediff(ms,@start,@end)) |
測試結果如:
單位:秒
第一次 |
第二次 |
第三次 |
第四次 |
第五次 |
第六次 |
第七次 |
第八次 |
第九次 |
第十次 |
|
Linq |
0.6788 |
0.681 |
0.6704 |
0.6804 |
0.686 |
0.6555 |
0.6753 |
0.677 |
0.6717 |
0.6744 |
SQL |
0.5653 |
0.5498 |
0.5699 |
0.5673 |
0.5699 |
0.5795 |
0.5756 |
0.5869 |
0.5749 |
0.5735 |
MSSQL |
0.156 |
0.110 |
0.143 |
0.170 |
0.126 |
0.156 |
0.126 |
0.143 |
0.140 |
0.126 |
第二輪測試——修改
查詢用SQL語句(把能被5整除的數據修改為“測”,應該影響1000000行):
update tab set Context=Context where id%5=0 |
測試結果如下:
本來想批量修改數據的,更新100萬行使用SQL語句用時基本在5.4——5.8秒之間,但是使用LINQ基本就掛了,5分鍾都出不了結果,看來如果是批量修改,特別是大批量修改,還是盡量避免使用LINQ
現在就改變下測試思路,修改其中一條數據。
update tab set DoTime=dateadd(ms,1,DoTime) where id=2500000 |
測試結果如下:
第一次 |
第二次 |
第三次 |
第四次 |
第五次 |
第六次 |
第七次 |
第八次 |
第九次 |
第十次 |
|
Linq |
0.2068 |
0.2022 |
0.2029 |
0.2064 |
0.2055 |
0.2025 |
0.2067 |
0.2012 |
0.2058 |
0.2031 |
Sql |
0.1466 |
0.1425 |
0.1386 |
0.1419 |
0.1457 |
0.1388 |
0.142 |
0.1384 |
0.1388 |
0.1426 |
第三輪測試——插入
批量插入1萬條數據
測試結果如下:
單位:秒
第一次 |
第二次 |
第三次 |
第四次 |
第五次 |
第六次 |
第七次 |
第八次 |
第九次 |
第十次 |
|
Linq |
9.4243 |
9.5757 |
9.2637 |
9.5913 |
9.5264 |
9.573 |
9.5606 |
9.5448 |
9.4261 |
9.7743 |
Sql |
8.7681 |
8.4239 |
7.9236 |
7.8332 |
7.8264 |
8.0614 |
7.997 |
7.979 |
7.888 |
8.2885 |
綜上所述,LINQ這個新技術,在代碼上和思想上的確很有優勢,但是歸根結底還是使用的是.net 2.0 的框架,只是抽象了一個接口而已,生成SQL語句的過程被LINQ完成,所以說LINQ即使到了極限也不能超越傳統的SQL,另外據查資料,LINQ另一個瓶頸在於Lambda表達式。我們可以得出在效率要求不高的應用型系統中,使用LINQ還是很有優勢的,畢竟代碼少,維護方便,但是在修改操作上,特別是批量修改就毫無優勢可言,效率低是一方面,內存在占用也是一個大問題,所以現在很多公司的做法就是兩者混合起來用,不失為一個明智的選擇。
試驗用代碼和文檔:下載