哪個更快。填充數據表時,datareader比數據集更快嗎?
1)循環一個DataReader以及基於填充的數據表
2)或創建一個DataAdapter對象,只是(.fill僞自定義行和列)荷蘭國際集團的DataTable。
在動態創建數據表時,數據讀取器的性能是否仍然適用?
哪個更快。填充數據表時,datareader比數據集更快嗎?
1)循環一個DataReader以及基於填充的數據表
2)或創建一個DataAdapter對象,只是(.fill僞自定義行和列)荷蘭國際集團的DataTable。
在動態創建數據表時,數據讀取器的性能是否仍然適用?
DataAdapter在引擎蓋下使用DataReader,因此您的體驗可能會相同。
DataAdapter的好處是你截掉了很多需要維護的代碼。
這次辯論是有點宗教問題的所以肯定環顧四周,並決定什麼最適合您的情況:
我不能說填充數據表但使用數據讀取器是最有效的讀取方法。
我一直在想,這是否取決於我們對數據的處理。由於DataReader依賴於數據庫服務器來緩衝信息,所以在一個大的結果集上,如果我們的計算很複雜,比如構建一個網絡圖,每個新節點都會變得越來越困難,那麼它會阻塞數據庫。 – Haoest 2008-12-02 17:36:29
您的選項#1會更慢。然而,有一個更好的方式來一個DataReader轉換爲數據表比手工添加自定義行:我不能在此使用.Fill()
之間的區別評論
DataTable dt = new DataTable();
using (SqlConnection conn = GetOpenSqlConnection())
using (SqlCommand cmd = new SqlCommand("SQL Query here", conn)
using (IDataReader rdr = cmd.ExecuteReader())
{
dt.Load(rdr);
}
。
謝謝!我一直在尋找如何從datareader加載數據表,因爲我有一個存儲過程返回多個表,但我只需要從一個輸出表'填充'數據表。 – Yoopergeek 2009-10-22 21:30:17
當你需要例如顯示加載數據的進度時,很高興有DataReader。在DataSet中,你不能在加載數據的時候做一些事情。
另一方面,DataSet是一體化的對象。所以DataSet慢得多。 DataReader可以爲您的代碼中的數據操作非常緩慢的地方提供額外的提升。在這些地方將它從DataSet更改爲DataReader。 DataReader在內存中佔用更少的空間。
哦,當然它需要更多的時間來編寫好的DataReader,但它是值得的。例如,當您使用從數據庫中獲取的圖像或音樂進行播放時。
DataReader的速度更快。如果您使用的是2.0+,那麼您甚至不必使用數據表。您可以使用對象的通用列表。
從2008年開始,您的聲明現在可以幫助我在2015年底:) SqlDataAdapter和SqlDataReader需要6.x分鐘才能加載DataTable,但Linq僅需1.7秒即可加載List(56460行)。 – 2015-12-29 06:15:46
@PalaniKumar:你能告訴我你將如何直接使用數據讀取器加載存儲過程結果和列表? – 2016-06-22 10:19:35
假設您確實需要從數據庫返回的所有數據,那麼在數據庫和網絡上花費的時間幾乎肯定會縮短進程中將數據結構填充到內存中所花費的時間。
是的,在某些情況下,您可能會通過使用DataReader獲得小額儲蓄 - 特別是如果您想傳輸數據可能會有用 - 但如果確實需要這些數據,我會堅持使用最簡單的碼。如果您認爲DataSet數量導致嚴重的性能問題,請將其設置爲,然後嘗試改進它。
像許多問題一樣,答案是:depends。
如果您事先不知道數據的結構,並且正在創建TableAdapter,那麼動態DataTable會更高效。創建TableAdapter涉及大量的代碼生成。然而,如果您事先知道數據的結構,那麼問題就變成了:我需要多少功能?
如果您需要一個完整的CRUD實現,那麼使用TableAdapter會獲得一些效率,而不是自己編寫所有的CRUD代碼。此外,TableAdapter實現是OK(不是很好)。如果你需要更高效的東西,那麼使用nHibernate或其他一些ORM可能會更好。
如果你不需要一個完整的CRUD實現(即這是一個只讀的解決方案)並且事先知道你的數據結構,那麼你必須測試一個TableAdapter只讀實現的效率,一個動態生成的DataTable。如果我是一個投注人,我會將我的錢放在TableAdapter實現上,因爲您綁定數據一次並多次讀取。
通過DataReader
的Read
這是一種只向前的一行一次的方法,它依次讀取數據,以便在連接時讀取它們時立即獲取記錄,將是最適合內存和性能。
也就是說,在兩種方法之間,我發現IDataAdapter.Fill
比DataTable.Load
快得多。當然,這依賴於實現的。這裏是我貼here兩者之間的風向標:
public DataTable Read1<T>(string query) where T : IDbConnection, new()
{
using (var conn = new T())
{
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = query;
cmd.Connection.ConnectionString = _connectionString;
cmd.Connection.Open();
var table = new DataTable();
table.Load(cmd.ExecuteReader());
return table;
}
}
}
public DataTable Read2<S, T>(string query) where S : IDbConnection, new()
where T : IDbDataAdapter, IDisposable, new()
{
using (var conn = new S())
{
using (var da = new T())
{
using (da.SelectCommand = conn.CreateCommand())
{
da.SelectCommand.CommandText = query;
da.SelectCommand.Connection.ConnectionString = _connectionString;
DataSet ds = new DataSet(); //conn is opened by dataadapter
da.Fill(ds);
return ds.Tables[0];
}
}
}
}
第二種方法總是優於第一。
Stopwatch sw = Stopwatch.StartNew();
DataTable dt = null;
for (int i = 0; i < 100; i++)
{
dt = Read1<MySqlConnection>(query); // ~9800ms
dt = Read2<MySqlConnection, MySqlDataAdapter>(query); // ~2300ms
dt = Read1<SQLiteConnection>(query); // ~4000ms
dt = Read2<SQLiteConnection, SQLiteDataAdapter>(query); // ~2000ms
dt = Read1<SqlCeConnection>(query); // ~5700ms
dt = Read2<SqlCeConnection, SqlCeDataAdapter>(query); // ~5700ms
dt = Read1<SqlConnection>(query); // ~850ms
dt = Read2<SqlConnection, SqlDataAdapter>(query); // ~600ms
dt = Read1<VistaDBConnection>(query); // ~3900ms
dt = Read2<VistaDBConnection, VistaDBDataAdapter>(query); // ~3700ms
}
sw.Stop();
MessageBox.Show(sw.Elapsed.TotalMilliseconds.ToString());
Read1
看起來眼睛比較好,但數據適配器性能更好(不要混淆1分貝優於其他的查詢都是不同的)。兩者之間的差異取決於查詢。原因可能是Load
需要各種約束,當添加行(其方法爲DataTable
)時,行from the documentation需要逐行檢查,而Fill
位於專爲此設計的DataAdapter上 - 快速創建DataTable。
查看我的帖子:這比使用DataAdapter的代碼少。 – 2008-12-02 16:59:20