2008-12-02 6 views
9

Который был бы быстрее.Является ли datareader быстрее, чем набор данных при заполнении данных?

1) Многократное воспроизведение DataReader и создания пользовательских строк и столбцов на основе населенной DataTable

2) или создание объекта DataAdapter и просто (.Нанести) ING в DataTable.

Выполняет ли производительность datareader все еще при динамическом создании datatable?

ответ

9

DataAdapter использует DataReader под капотом, поэтому ваш опыт, вероятно, будет таким же.

Преимущество DataAdapter - вырезать много кода, который потребует обслуживания.

Эта дискуссия немного религиозного вопроса так определенно осмотреться и решить, что лучше для вашей ситуации:

+0

Посмотреть мое сообщение: это меньше кода, чем с использованием DataAdapter. – 2008-12-02 16:59:20

3

Я не могу говорить о заполнении se, но использование datareader является наиболее эффективным методом чтения.

+1

Я всегда задавался вопросом, зависит ли это от того, что мы делаем с данными. Поскольку DataReader полагается на сервер базы данных для буферизации информации, поэтому в большом наборе результатов, если наши вычисления сложны, например, построение сетевого графика, который становится сложнее с каждым новым узлом, он забивает базу данных. – Haoest 2008-12-02 17:36:29

7

Ваш вариант №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().

+0

Спасибо! Я искал, как загружать данные из datareader, потому что у меня есть хранимый-proc, который возвращает несколько таблиц, но мне нужно только «заполнить» данные из одной из выходных таблиц. – Yoopergeek 2009-10-22 21:30:17

1

Приятно иметь DataReader, когда вам нужно, например, показать ход загрузки данных. В DataSet вы не можете сделать что-то в середине загрузки данных.

С другой стороны, DataSet является объектом «все-в-одном». Таким образом, DataSet намного медленнее. DataReader может дать вам дополнительный импульс в местах вашего кода, где обработка данных происходит очень медленно. В этих местах измените его с DataSet на DataReader. DataReader также занимает меньше места в памяти.

О, конечно, для хорошего кода DataReader требуется больше времени, но это того стоит. Например, когда вы играете с изображениями или музыкой, взятой из базы данных.

More on this topic in MSDN Magazine

2

DataReader быстрее. И если вы используете 2.0+, вам, вероятно, даже не придется использовать datatable. Вы можете использовать общий список вашего объекта.

+1

Ваше заявление от 2008 года помогает мне сейчас в конце 2015 года :) SqlDataAdapter и SqlDataReader берут 6.x mins для загрузки DataTable, но Linq занимает всего 1,7 секунды для загрузки списка (56460 строк). – 2015-12-29 06:15:46

+0

@PalaniKumar: Не могли бы вы рассказать мне, как бы вы непосредственно загрузили результат хранимой процедуры с помощью списка с помощью считывателя данных? – 2016-06-22 10:19:35

11

Предполагая, что вы действительно хотите, чтобы все данные возвращались из базы данных, время, затраченное на базу данных и в сети, почти наверняка затмевает время, затраченное на процесс, для заполнения структур данных в памяти.

Да, в некоторых случаях вы можете получить небольшую экономию с помощью DataReader - и, в частности, если вы хотите передать данные, это может быть полезно, но если вам действительно нужно все это, я бы придерживался простейшего код.Если вы считаете, что население DataSet вызывает значительную проблему с производительностью, профайл его и , то попытайтесь его улучшить.

1

Как и многие другие вопросы, такие как ответ: зависит.

Если вы не знаете структуру своих данных спереди и создаете «TableAdapters» на лету, тогда динамический DataTable будет более эффективным. Существует много генерации кода, связанных с созданием TableAdapter.

Однако, если вы знаете структуру своих данных спереди, тогда возникает вопрос, насколько мне нужна функциональность?

Если вам нужна полная реализация CRUD, тогда есть некоторая эффективность, получаемая с помощью TableAdapter, а не для написания всего этого кода CRUD. Кроме того, реализация TableAdapter в порядке (невелика). Если вам нужно что-то более эффективное, вам может быть лучше использовать nHibernate или какой-либо другой ORM.

Если вам не нужна полная реализация CRUD (т. Е. Это решение только для чтения) и вы знаете свою структуру данных спереди, вам нужно будет проверить эффективность реализации TableAdapter для чтения только для чтения динамически созданный DataTable. Если бы я был игроком ставок, я бы поместил свои деньги в реализацию TableAdapter, так как вы связываете данные один раз и читаете их несколько раз.

1

Выполняется DataReader's 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 выглядит лучше на глаза, но адаптер данных выполняет лучше (не путать, что один децибел превосходит другой, запросы были все разные). Однако разница между ними зависела от запроса. Причина может заключаться в том, что Load требует, чтобы различные ограничения проверялись по строке from the documentation при добавлении строк (его метод на DataTable), а Fill - на DataAdapters, которые были предназначены именно для этого - быстрое создание DataTables.