上圖就是這次測試的評比結果,計算方式為將測試時間以 SqlCommand 的時間為 Index (所以1為最快,數字越大越慢),然後來與其他ORM的時間做比較,Read的測試有做兩個,所以Read的分數是兩個測試的Index去平均的。
簡單來說,Read 時的LINQ與EF效能輸SqlCommand不會太多,分別約慢了51%與79%,而SubSonic就爆掉了,分數為5.20,也就是慢了420%。
而 Write 時,反過來是SubSonic慢SqlCommand 34%,領先LINQ與EF的174%與172%。
下面說明這次測試如何進行。
先前做過一個很簡單的LINQ效能測試,不過微軟後來看起來重心不放在LINQ to SQL,所以這次測試加入Entity Framework 4.1、還有SubSonic 3.0一同測試,而上次的對照組是使用SqlDataAdapter,這次也改成只使用SqlCommand,較為單純。
測試是在一般的普通PC上測試,我建了一個簡單的table,裡面三個欄位guid為PK,name與score為亂數的字串與數字(0~999),然後分別建立起LINQ,EF與SubSonic的DateModel。
開始先測試讀取的部分,Table內先亂塞了八萬筆資料,雖然不多,不過拿來做測試還是可以。
我做了三個測試,一個是 Select 某個分數的 Top 1,另一個是 Select * Where In 三個分數,還有一個 Insert 的測試,Insert 測試最後做,以維持Table內資料筆數不變。三個ORM所使用的語法如下:
LINQ to SQL Insert / Select Top / Where In
Entity Framework Insert / Select Top / Where In
SubSonic 3.0 Insert / Select Top / Where In
接下來就是分別的測試結果了。
Select Top 1 Test
這個測試是用SqlCommand與三個ORM參賽者執行一千次下面這段SqlString
select top 1 * from [Died_Test].[dbo].[tbl_Speed_Test] where [score]=@score因為要模擬真實狀況,所以我的寫法是每次呼叫function都給個亂數數字進去,共計時五次,取平均值。
SqlCommand的測試片段長這樣,下面的也差不多,就不列了。
public static void SubSonicSelectTop(int score) public static void SqlCommandSelectTop(int score) { using (SqlConnection connection = new SqlConnection(connectionString)) { SqlCommand command = new SqlCommand("select top 1 * from [Died_Test].[dbo].[tbl_Speed_Test] where [score]=@score", connection); command.Parameters.Add("@score", SqlDbType.Int); command.Parameters["@score"].Value = score; command.Connection.Open(); try { SqlDataReader reader = command.ExecuteReader(); while (reader.Read()) { Console.WriteLine(String.Format("{0}\t{1}\t{2}", reader[0], reader[1], reader[2])); } } catch (Exception e) { throw e; } } }我在計時的時候會把while那段mark掉,避免writeline的時間影響到計時,其他的測試也都這樣做,之後就不提了。
Select Where In Test
這邊的測試則是測拉出多筆資料的速度,使用ORM可以很簡單的做到 Where In 一個陣列的查詢,但是SqlCommand寫起來很麻煩,所以我就偷懶都只生出一個內有三個亂數數字的陣列,然後去做查詢,所以大致上就是做下面這個SqlString的查詢一千次。
select * from [Died_Test].[dbo].[tbl_Speed_Test] where [score] in (@score1,@score2,@score3) order by [score]
Insert Test
然後是寫入的測試,我是做每次寫入一筆新資料,內容是亂數的文字與數字,然後做1000次,SqlString長得像下面這樣。
insert into [Died_Test].[dbo].[tbl_Speed_Test] (name,score) values(@name,@score)
Result
最後用上面三個測試的平均值整合後的數據,可以做出下面這張表。
但是不同的測試,得到的數據起伏有點大,反而不好比較,所以我改以對照組 SqlCommand 的時間當Index,將其他ORM測出的時間拿去除,得出下面的結果。
結論呢,對我來說,取決效能與寫code方便性,我會選擇 Entity Framework ,至於你信不信,我反正信了。
No comments:
Post a Comment