關於LINQ和SQL操作數據庫的性能測試(轉)


 微軟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 可以停止測量運行時間。通過屬性 ElapsedElapsedMilliseconds 或 ElapsedTicks 查詢運行時間值。當實例正在運行或已停止時,可以查詢運行時間屬性。運行時間屬性在 Stopwatch運行期間穩固遞增;在該實例停止時保持不變。

默認情況下,Stopwatch 實例的運行時間值相當於所有測量的時間間隔的總和。每次調用 Start 時開始累計運行時間計數;每次調用 Stop 時結束當前時間間隔測量,並凍結累計運行時間值。使用 Reset 方法可以清除現有 Stopwatch 實例中的累計運行時間。

Stopwatch 在基礎計時器機制中對計時器的刻度進行計數,從而測量運行時間。如果安裝的硬件和操作系統支持高分辨率性能的計數器,則 Stopwatch 類將使用該計數器來測量運行時間;否則,Stopwatch 類將使用系統計數器來測量運行時間。使用 Frequency 和 IsHighResolution 字段可以確定實現 Stopwatch 計時的精度和分辨率。

Stopwatch 類為托管代碼內與計時有關的性能計數器的操作提供幫助。具體說來,Frequency 字段和 GetTimestamp 方法可以用於替換非托管 Win32 APIQueryPerformanceFrequency 和 QueryPerformanceCounter

clip_image001注意:

在多處理器計算機上,線程在哪個處理器上運行無關緊要。但是,由於 BIOS 或硬件抽象層 (HAL) 中的 bug,在不同的處理器上可能會得出不同的計時結果。若要為線程指定處理器關聯,請使用 ProcessThread..::.ProcessorAffinity 方法。

測試前准備:

新建一個數據庫: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))

測試結果如:

clip_image003

單位:秒

 

第一次

第二次

第三次

第四次

第五次

第六次

第七次

第八次

第九次

第十次

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

測試結果如下:

clip_image005單位:秒

 

第一次

第二次

第三次

第四次

第五次

第六次

第七次

第八次

第九次

第十次

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萬條數據

測試結果如下:

clip_image007

單位:秒

 

第一次

第二次

第三次

第四次

第五次

第六次

第七次

第八次

第九次

第十次

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還是很有優勢的,畢竟代碼少,維護方便,但是在修改操作上,特別是批量修改就毫無優勢可言,效率低是一方面,內存在占用也是一個大問題,所以現在很多公司的做法就是兩者混合起來用,不失為一個明智的選擇。

       試驗用代碼和文檔:下載


免責聲明!

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



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