Является ли устройство чтения данных быстрее, чем набор данных при заполнении данных? - PullRequest
9 голосов
/ 02 декабря 2008

Что было бы быстрее.

1) Цикл чтения данных и создание пользовательских строк и столбцов на основе заполненных данных

2) Или создание объекта dataAdapter и просто (.Fill) создание таблицы данных.

Сохраняется ли производительность устройства чтения данных при динамическом создании данных?

Ответы [ 8 ]

11 голосов
/ 02 декабря 2008

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

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

9 голосов
/ 02 декабря 2008

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

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

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

7 голосов
/ 02 декабря 2008

Ваш вариант № 1 будет медленнее. Тем не менее, есть лучший способ преобразовать устройство чтения данных в набор данных, чем ручное добавление пользовательских строк:

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().

3 голосов
/ 02 декабря 2008

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

2 голосов
/ 02 декабря 2008

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

1 голос
/ 14 февраля 2013

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

1 голос
/ 02 декабря 2008

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

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

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

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

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

1 голос
/ 02 декабря 2008

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

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

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

Подробнее об этом в журнале MSDN

...