1. 程式人生 > 實用技巧 >.NET深入學習筆記(1):DataSet和SqlDataReader效能差異深入剖析與測試(1)

.NET深入學習筆記(1):DataSet和SqlDataReader效能差異深入剖析與測試(1)

宣告:這篇文章可能存在錯誤,我對於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 />

硬體:

CPU

Intel T2300 1.66GHz

記憶體

<?XML:NAMESPACE PREFIX = ST1 />Kingston DDR2 667 1G

硬碟

80G 5400 8m

軟體:

作業系統

Windows Server 2003

資料庫系統

SQL Server 2005 Enterprise

資料規模

1000000條資料

資料庫表結構 Test
名稱 型別 備註
id int 標誌\聚集索引
name nvarchar(50) 非聚集索引
birthday datetime 生日
height int 身高
sex int 性別
address nvarchar(100) 地址
lastlogintime datetime 非聚集索引
具體的實驗程式c#程式碼如下,使用了using System.Data.SqlClient;
using System.Diagnostics;兩個namespace下的類,Stopwatch物件用來進行計時.

測試DataSet的程式碼:
1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2ExpandedBlockStart.gifContractedBlock.gif{
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();
17ExpandedSubBlockStart.gifContractedSubBlock.gif/**////textBox3.Text=sizeof(DataSet);
18}

19 測試DataReader的程式碼: ContractedBlock.gifExpandedBlockStart.gifCode
1using(SqlConnectionconn=newSqlConnection("DataSource=127.0.0.1;InitialCatalog=Test;IntegratedSecurity=True"))
2ExpandedBlockStart.gifContractedBlock.gif{
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())
13ExpandedSubBlockStart.gifContractedSubBlock.gif{
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
從試驗結果分析可以得出如下結論: 1.在查詢資料量很少的情況下100條內,DataReader和DataSet幾乎沒有什麼明顯的效能差別. 2.資料量過大,接近10000條的時候的資料查詢,DataReader的效能要明顯優於DataSet. 對於兩者的效能對比,不應該輕易下結論,除了參考實驗裝置,也要考慮實際的資料規模. 具體專案應用中,選擇適合具體需求的物件進行資料處理,才能有效的提高系統的效能. 本文的測試環境和結果可能存在偏差,但是希望能給大家帶來一些幫助,一起交流學習.謝謝. 【2】補充: DataAdapter的Fill方法的原始碼,我們使用反射器檢視,程式碼如下: .NET深入學習筆記(1):DataSet和SqlDataReader效能差異深入剖析與測試(2) 本文出自 51CTO.COM技術部落格

轉載於:https://blog.51cto.com/yaozefeng/326112