どちらが速いでしょう。
1)データリーダーをループし、入力されたデータテーブルに基づいてカスタムの行と列を作成する
2)または、dataAdapterオブジェクトを作成し、データテーブルを(.Fill)だけ入力します。
データテーブルを動的に作成しても、データリーダーのパフォーマンスは維持されますか?
どちらが速いでしょう。
1)データリーダーをループし、入力されたデータテーブルに基づいてカスタムの行と列を作成する
2)または、dataAdapterオブジェクトを作成し、データテーブルを(.Fill)だけ入力します。
データテーブルを動的に作成しても、データリーダーのパフォーマンスは維持されますか?
DataAdapterは内部でDataReaderを使用するため、経験は同じである可能性があります。
DataAdapterの利点は、メンテナンスが必要な多くのコードを切り取ることができることです。
この議論は少し宗教的な問題なので、間違いなく周りを見回して、自分の状況に最適なものを決定してください。
実際にすべてのデータをデータベースから取得する必要があると仮定すると、データベースとネットワークでかかる時間は、インプロセスでデータ構造をメモリに入力するのにかかる時間よりも確実に小さくなります。
はい、場合によっては、DataReader を使用することで少し節約できる場合があります。特に、データをストリーミングしたい場合は便利かもしれませんが、実際にすべてが必要な場合は、最も単純なコードを使用します。DataSet の人口が重大なパフォーマンスの問題を引き起こしていると思われる場合は、それをプロファイリングしてから改善を試みてください。
オプション#1は遅くなります。ただし、手動でカスタム行を追加するよりも、datareader をデータテーブルに変換するためのより良い方法があります。
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);
}
これと using の違いについてはコメントできません.Fill()
。
データテーブル自体を埋めることについて話すことはできませんが、データリーダーを使用するのが最も効率的な読み取り方法です。
データリーダーの方が高速です。また、2.0 以降を使用している場合は、おそらくデータテーブルを使用する必要さえありません。オブジェクトの汎用リストを使用できます。
たとえば、データの読み込みの進行状況を表示する必要がある場合は、DataReader があると便利です。DataSet では、データのロード中に何かを行うことはできません。
一方、DataSet はオールインワン オブジェクトです。そのため、DataSet は非常に遅くなります。DataReader は、データ操作が非常に遅いコード内の場所で追加のブーストを提供できます。これらの場所で、DataSet から DataReader に変更します。DataReader はメモリ内のスペースも少なくて済みます。
もちろん、優れた DataReader をコーディングするには時間がかかりますが、それだけの価値はあります。たとえば、データベースから取得した画像や音楽で遊ぶ場合。
このような多くの質問と同様に、答えは次のとおりです。
前もってデータの構造がわからず、その場で TableAdapter を作成している場合は、動的 DataTable の方が効率的です。TableAdapter の作成には、大量のコード生成が必要です。
ただし、データの構造を前もって知っている場合は、「どのくらいの機能が必要ですか?」という質問になります。
完全な CRUD 実装が必要な場合は、すべての CRUD コードを自分で作成するよりも、TableAdapter を使用する方が効率が向上します。また、TableAdapter の実装は問題ありません (あまり良くありません)。より効率的なものが必要な場合は、nHibernate やその他の ORM を使用することをお勧めします。
完全な CRUD 実装を必要とせず (つまり、これは読み取り専用ソリューションです)、データ構造を前もって知っている場合は、動的に生成された DataTable に対して TableAdapter 読み取り専用実装の効率をテストする必要があります。 . 私が賭け屋だったら、データを 1 回バインドして複数回読み取るため、TableAdapter の実装にお金をかけます。
接続時にレコードが読み取られるとすぐにレコードを取得できるように、順方向のみ、一度に 1 行ずつデータを読み取るアプローチであるDataReader
'sを使用すると、メモリとパフォーマンスが最適になります。Read
とはいえ、2 つのアプローチの間ではIDataAdapter.Fill
、DataTable.Load
. もちろん、それは実装に依存します..ここに私が投稿した2つの間のベンチマークがあります:
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];
}
}
}
}
2 番目のアプローチは常に最初のアプローチよりも優れていました。
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 つのデータベースが他のデータベースより優れていることを混同しないように、クエリはすべて異なっていました)。ただし、2つの違いはクエリに依存していました。その理由は、行を追加するときにドキュメントからLoad
行ごとにさまざまな制約をチェックする必要があるためです (メソッド on )が、そのためだけに設計された DataAdapters にある場合 - DataTables の高速作成。DataTable
Fill