在網上關於DataSet和DataReader的使用的討論很多,大都是討論到底該使用DataSet還是DataReader,我也發表一下我的看法。先看一下DataSet和DataReader的區別,DataSet實際上是一個離線資料集,DataSet不用保持資料庫連接,而 DataReader需要保持資料庫連接,這應當是兩者的本質區別,分別對應的ava中的CachedRowSet 和ResultSet,所以兩者各有各的用處,DataSet使用前必須填充,所以必須從記憶體中開闢記憶體儲存DataSet的內容,而 DataReader的使用必須使資料庫連接有效,但是不必開闢記憶體儲存所有的資料,所以在資料量較小時,使用DataSet可以提升效能,因為所有的資料都在記憶體中操作,但資料量較大時(“較大“的標準不一,一般上千條的資料應當稱作較大了吧)使用DataReader就有優勢,因為 DataReader每次讀取都是利用自身保持的資料庫連接從資料庫中動態讀取,不會將大量的資料一下裝入記憶體(也就是所謂的懶裝入 lazyloding),但缺點是唯讀,並且是僅向前的,如果你要多次使用同一個資料,還是得先緩衝該資料,否則讀取一次後將不能重複讀取,所以建議就是資料量較少的時候用DataSet,而資料量大時使用DataReader當然,不管使用那個,都應當盡量將查詢數量降到最低,只有這樣才能做到高效使用,另外,如果你針對每一條資料都需要一個耗時操作的話,要避免使用DataReader,因為資料庫連接資源是非常寶貴的,一個伺服器串連池中一般就十幾個串連罷了,要是每人都保持串連的話,用不了多久就會耗光。
DataSet和SqlDataReader效能測試轉自:http://www.cnblogs.com/frank_xl/archive/2009/01/15/1375976.html
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在查詢資料的時候,效能會不會勝出,如果前者更優的話那麼會超出多少?我自己寫了個小程式,自己建立的資料庫進行了實驗. 實驗測試環境如下:
硬體:
| CPU |
Intel T2300 1.66GHz |
| 記憶體 |
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的代碼:
Code
1
using (SqlConnection conn =
new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Test;Integrated Security=True"))
2 {
3 Stopwatch st =
new Stopwatch();
4 st.Start();
5 conn.Open();
6 SqlDataAdapter da =
new SqlDataAdapter(sQuery, conn);
7 st.Stop();
8 //textBox3.Text = st.ElapsedMilliseconds.ToString();
9
10 st.Start();
11 DataSet ds =
new DataSet("test");
12 da.Fill(ds);
13 st.Stop();
14 long ltimes = st.ElapsedMilliseconds;
15 //textBox1.Text = ltimes.ToString();
16 conn.Close();
17 /**////textBox3.Text = sizeof(DataSet);
18 }
19
測試DataReader的代碼:
Code
1
using (SqlConnection conn =
new SqlConnection("Data Source=127.0.0.1;Initial Catalog=Test;Integrated Security=True"))
2 {
3
4 Stopwatch st =
new Stopwatch();
5 st.Start();
6 conn.Open();
7 SqlCommand Comm =
new SqlCommand(sQuery, conn);
8 st.Stop();
9 textBox4.Text = st.ElapsedMilliseconds.ToString();
10 st.Start();
11 SqlDataReader reader = Comm.ExecuteReader();
12 while (reader.Read())
13 {
14
15 }
16 st.Stop();
17 long ltimes = st.ElapsedMilliseconds;
18 textBox2.Text = ltimes.ToString();
19 conn.Close();
20 //textBox4.Text = sizeof(SqlDataReader);
21 }
測試語句和時間ms分別如下:
| 語句 |
DataSet費時 |
DataReader費時 |
| 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.
對於兩者的效能對比,不應該輕易下結論,除了參考實驗裝置,也要考慮實際的資料規模.
具體項目應用中,選擇適合具體需求的對象進行資料處理,才能有效提高系統的效能.
本文的測試環境和結果可能存在偏差,但是希望能給大家帶來一些協助,一起交流學習.謝謝.