.NET深入學習筆記(1):DataSet和SqlDataReader效能差異深入剖析與測試(1)
阿新 • • 發佈:2020-10-13
宣告:這篇文章可能存在錯誤,我對於DataSet和SqlDataReader概念的理解有誤,當時主要是針對網路上一個面試的題目做出的,測試。我在核實資料後與驗證程式碼後會做出更新。
我已經使用Reflector查看了SQLDataAdapter型別的Fill方法以及SqlCommand.ExecuteReader 方法程式碼。確實有使用DataReader的地方。他們是真正負責處理查詢並裝在資料。DataReader和DataSet應該都是資料容器。做個類比的話,應該是茶壺和茶杯的關係。 至於查詢資料,除了取決於容器,還和具體負責查詢和裝載資料的類有關係。 我文章的標題,應該說是有問題的,這種比較忽略了一個數據查詢和裝載的過程。有不合理的地方。現在更正。
2009年已經來臨,中國的新春佳節就要到來.首先祝各位新年快樂,牛年大吉~~此篇文章作為我blog的第一篇文章,寫出來希望能與大家一起分享經驗,交流技術.
DataSet和SqlDataReader 的比較的文章和帖子網上已經很多,我也看了很多前輩的隨筆.自己在面試和實際工作中也遇到這樣的問題.但是始終是沒深入進行學習.最近在工作空閒之餘,特地查閱了一些文章,也包括msdn的官方文件.自己建立資料庫和測試程式,對DataSet和SqlDataReader做了比較.
首先關於兩者比較主流的觀點就是:
1.DataReader使用時始終佔用SqlConnection,線上操作資料庫.DataSet則是將資料一次性載入在記憶體中.支援資料庫訪問的斷開連線模型.
2.DataReader每次只在記憶體中載入一條資料,節約記憶體.DataSet將資料全部載入在記憶體中.比較消耗記憶體.
3.DataReader單向只讀.DataSet 支援查詢\修改\刪除等操作,比較靈活.
4.DataReader與SqlCommand搭配.DataSet與DataAdapter 結合使用.
為什麼會這樣呢?我們就來分析一下具體的原因.檢視一下msdn關於 兩者的不同描述:
1>SqlDataReader 類提供一種從 SQL Server 資料庫讀取行的只進流的方式。無法繼承此類。 名稱空間: System.Data.SqlClient程式集: System.Data(在 System.Data.dll 中).可以使用 ADO.NET DataReader 從資料庫中檢索只讀、只進的資料流。查詢結果在查詢執行時返回,在並存儲在客戶端的網路緩衝區中,直到您使用 DataReader 的 Read 方法對它們發出請求。使用 DataReader 可以提高應用程式的效能,原因是它只要資料可用就立即檢索資料,並且(預設情況下)一次只在記憶體中儲存一行,減少了系統開銷。
2>DataSet 物件是支援 ADO.NET 的斷開式、分散式資料方案的核心物件。DataSet 是資料的記憶體駐留表示形式,無論資料來源是什麼,它都會提供一致的關係程式設計模型。它可以用於多種不同的資料來源,用於 XML 資料,或用於管理應用程式本地的資料。DataSet 表示包括相關表、約束和表間關係在內的整個資料集。下圖將顯示 DataSet 物件模型。
從上面的描述可以看出,DataReader和DataSet具有不同的結構模型.在資料的方式處理上也存在顯著的差別.SqlDataReader 會避免建立不必要的物件或複製不必要的資料.DataSet 可以表示完整的資料模型,包括表格、約束條件和表關係.在物件的建立和銷燬等環節需要消耗更多的資源,因此在效能上也稍顯遜色.因此很多文章得出的結論也是在只進行讀資料操作的情況下,DataReader的效能要強於DataSet.但是很多文章都沒有相應的測試,就盲目下結論.
但是好奇心理的驅使使我很想來做個試驗來驗證一下這個結論,到底DataReader比DataSet在查詢資料的時候,效能會不會勝出,如果前者更優的話那麼會超出多少?我自己寫了個小程式,自己建立的資料庫進行了實驗. 實驗測試環境如下:<?XML:NAMESPACE PREFIX = O />
硬體:
軟體:
資料庫表結構
Test
具體的實驗程式c#程式碼如下,使用了using System.Data.SqlClient;
using System.Diagnostics;兩個namespace下的類,Stopwatch物件用來進行計時.
測試DataSet的程式碼: 1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2{
3Stopwatchst=newStopwatch();
4st.Start();
5conn.Open();
6SqlDataAdapterda=newSqlDataAdapter(sQuery,conn);
7st.Stop();
8//textBox3.Text=st.ElapsedMilliseconds.ToString();
9
10st.Start();
11DataSetds=newDataSet("test");
12da.Fill(ds);
13st.Stop();
14longltimes=st.ElapsedMilliseconds;
15//textBox1.Text=ltimes.ToString();
16conn.Close();
17/**////textBox3.Text=sizeof(DataSet);
18}
19 測試DataReader的程式碼: Code
1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2{
3
4Stopwatchst=newStopwatch();
5st.Start();
6conn.Open();
7SqlCommandComm=newSqlCommand(sQuery,conn);
8st.Stop();
9textBox4.Text=st.ElapsedMilliseconds.ToString();
10st.Start();
11SqlDataReaderreader=Comm.ExecuteReader();
12while(reader.Read())
13{
14
15}
16st.Stop();
17longltimes=st.ElapsedMilliseconds;
18textBox2.Text=ltimes.ToString();
19conn.Close();
20//textBox4.Text=sizeof(SqlDataReader);
21} 測試語句和時間ms分別如下:
從試驗結果分析可以得出如下結論:
1.在查詢資料量很少的情況下100條內,DataReader和DataSet幾乎沒有什麼明顯的效能差別.
2.資料量過大,接近10000條的時候的資料查詢,DataReader的效能要明顯優於DataSet.
對於兩者的效能對比,不應該輕易下結論,除了參考實驗裝置,也要考慮實際的資料規模.
具體專案應用中,選擇適合具體需求的物件進行資料處理,才能有效的提高系統的效能.
本文的測試環境和結果可能存在偏差,但是希望能給大家帶來一些幫助,一起交流學習.謝謝.
【2】補充:
DataAdapter的Fill方法的原始碼,我們使用反射器檢視,程式碼如下:
.NET深入學習筆記(1):DataSet和SqlDataReader效能差異深入剖析與測試(2) 本文出自 51CTO.COM技術部落格
CPU | Intel T2300 1.66GHz |
記憶體 | <?XML:NAMESPACE PREFIX = ST1 />Kingston DDR2 667 1G |
硬碟 | 80G 5400轉 8m |
作業系統 | Windows Server 2003 |
資料庫系統 | SQL Server 2005 Enterprise |
資料規模 | 1000000條資料 |
名稱 | 型別 | 備註 |
id | int | 標誌\聚集索引 |
name | nvarchar(50) | 非聚集索引 |
birthday | datetime | 生日 |
height | int | 身高 |
sex | int | 性別 |
address | nvarchar(100) | 地址 |
lastlogintime | datetime | 非聚集索引 |
using System.Diagnostics;兩個namespace下的類,Stopwatch物件用來進行計時.
測試DataSet的程式碼: 1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2{
3Stopwatchst=newStopwatch();
4st.Start();
5conn.Open();
6SqlDataAdapterda=newSqlDataAdapter(sQuery,conn);
7st.Stop();
8//textBox3.Text=st.ElapsedMilliseconds.ToString();
9
10st.Start();
11DataSetds=newDataSet("test");
12da.Fill(ds);
13st.Stop();
14longltimes=st.ElapsedMilliseconds;
15//textBox1.Text=ltimes.ToString();
16conn.Close();
17/**////textBox3.Text=sizeof(DataSet);
18}
19 測試DataReader的程式碼: Code
1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2{
3
4Stopwatchst=newStopwatch();
5st.Start();
6conn.Open();
7SqlCommandComm=newSqlCommand(sQuery,conn);
8st.Stop();
9textBox4.Text=st.ElapsedMilliseconds.ToString();
10st.Start();
11SqlDataReaderreader=Comm.ExecuteReader();
12while(reader.Read())
13{
14
15}
16st.Stop();
17longltimes=st.ElapsedMilliseconds;
18textBox2.Text=ltimes.ToString();
19conn.Close();
20//textBox4.Text=sizeof(SqlDataReader);
21} 測試語句和時間ms分別如下:
語句 | DataReader費時 | DataSet費時 |
string sQuery = "SELECT * FROM dbo.test where id <= 1" | 0ms | 0ms |
string sQuery = "SELECT * FROM dbo.test where id <=10" | 1ms | 1ms |
string sQuery = "SELECT * FROM dbo.test where id <=100" | 2ms | 3ms |
string sQuery = "SELECT * FROM dbo.test where id <=1000" | 5ms | 6ms |
string sQuery = "SELECT * FROM dbo.test where id <=10000" | 8ms | 50ms |
轉載於:https://blog.51cto.com/yaozefeng/326112