Является ли datareader быстрее, чем набор данных при заполнении данных?
Что было бы быстрее.
1) Зацикливание datareader и создание пользовательских строк и столбцов, заполняемых datatable
2) Или создайте объект dataAdapter и просто (.Fill) с данными.
Сохраняется ли производительность datareader при динамическом создании данных?
Ответы
Ответ 1
DataAdapter использует DataReader под капотом, поэтому ваш опыт, вероятно, будет таким же.
Преимущество DataAdapter заключается в том, что вы вырезали много кода, требующего обслуживания.
Эта дискуссия является немного религиозной проблемой, поэтому обязательно осмотритесь и решите, что лучше всего подходит для вашей ситуации:
Ответ 2
Предполагая, что вы действительно хотите, чтобы все данные возвращались из базы данных, время, затраченное на базу данных и в сети, почти наверняка затмевает время, затраченное на процесс, для заполнения структур данных в памяти.
Да, в некоторых случаях вы можете получить небольшую экономию с помощью DataReader - и, в частности, если вы хотите передавать данные, это может быть полезно, но если вам действительно нужно все это, я бы придерживался простейшего кода, Если вы считаете, что совокупность данных DataSet вызывает значительную проблему с производительностью, профилируйте ее, а затем попытайтесь ее улучшить.
Ответ 3
Ваш вариант №1 будет медленнее. Однако есть лучший способ конвертировать datareader в datatable, чем добавлять пользовательские строки вручную:
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);
}
Я не могу прокомментировать разницу между этим и использованием .Fill()
.
Ответ 4
Я не могу говорить о заполнении данных как таковых, но использование datareader - самый эффективный метод чтения.
Ответ 5
Датчик данных быстрее. И если вы используете 2.0+, вам, вероятно, даже не придется использовать datatable. Вы можете использовать общий список вашего объекта.
Ответ 6
Приятно иметь DataReader, когда вам нужно, например, показать ход загрузки данных. В DataSet вы не можете сделать что-то в середине загрузки данных.
С другой стороны, DataSet - это объект "все-в-одном". Таким образом, DataSet намного медленнее. DataReader может дать вам дополнительный импульс в местах вашего кода, где обработка данных происходит очень медленно. В этих местах измените его с DataSet на DataReader. DataReader также занимает меньше места в памяти.
Конечно, для хорошего кода DataReader требуется больше времени, но это того стоит. Например, когда вы играете с изображениями или музыкой, взятой из базы данных.
Подробнее об этой теме в журнале MSDN
Ответ 7
Как и во многих вопросах, таких как ответ: зависит.
Если вы не знаете структуру своих данных и создаете "TableAdapters" на лету, тогда динамический DataTable будет более эффективным. Существует большое количество генерации кода, участвующих в создании TableAdapter.
Однако, если вы знаете структуру своих данных спереди, тогда возникает вопрос, насколько мне нужна функциональность?
Если вам нужна полная реализация CRUD, тогда есть некоторая эффективность, полученная с помощью TableAdapter, а не для написания всего этого кода CRUD. Кроме того, реализация TableAdapter в порядке (невелика). Если вам нужно что-то более эффективное, вам может быть лучше использовать nHibernate или какой-либо другой ORM.
Если вам не нужна полная реализация CRUD (т.е. это решение только для чтения) и вы знаете свою структуру данных, вам нужно будет проверить эффективность реализации TableAdapter для чтения только с динамически созданный DataTable. Если бы я был игроком ставок, я бы поместил свои деньги в реализацию TableAdapter, так как вы связываете данные один раз и читаете их несколько раз.
Ответ 8
Переход на DataReader
Read
, который представляет собой подход только по принципу "только для прямого доступа", который читает данные последовательно, чтобы вы получали записи, как только они были прочитаны при подключении, будут лучшее для памяти и производительности.
Таким образом, между двумя подходами я нахожу IDataAdapter.Fill
намного быстрее, чем DataTable.Load
. Конечно, это зависит от реализаций. Вот эталонная точка между двумя, которые я разместил здесь:
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
выглядит лучше на глазах, но адаптер данных работает лучше (не путать, что один db превосходил другой, все были разные запросы). Однако разница между ними зависела от запроса. Причина может заключаться в том, что Load
требует, чтобы различные ограничения проверялись по строке из документации при добавлении строк (его метод на DataTable
), а Fill
- в DataAdapters, которые были предназначены именно для этого - быстрое создание DataTables.