がんふぃーるど室長の不定期ブログ

ただいま助手と悪戦苦闘中!

目次

Blog 利用状況

ニュース


自己紹介

名前:がんふぃーるど
肩書:室長
種別:人間・男
資格一覧:
MCP 70-215 Installing, Configurating, and Administering Microsoft Windows 2000 Server
MCTS .NET Framework 2.0 - Distributed Applications
MCTS .NET Framework 2.0 - Web Applications

犬紹介


名前:なうら
肩書:助手
種別:犬・狆・メス
誕生日:2006/7/9
特技:鼻水飛ばし、甘噛、奇襲・急襲・強襲、そそう、お手、お座り、待て

記事カテゴリ

書庫

日記カテゴリ

ギャラリ

DataSet vs DataReader 検証 .NET2.0

DataSet vs DataReader

某掲示板で.NET2.0のDataSet話題が少しだけ上がったので、気になって調べました。
DataSetとDataReaderはそれぞれ長所と短所があると思いますが、パフォーマンスってことでちょいといろいろやってみました。

テスト方法

テストに使用するデータベース

  • SQL Server 2000 Developer Edition
  • テーブルのフィールドは4つ(int(PK), varchar(50), decimal, char(10) )
  • 総レコード数は2万

測定する対象オブジェクト/メソッド

  • SqlDataAdapterオブジェクトの生成からFillメソッドが完了するまでの時間。

using(SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlCommand command = con.CreateCommand();
command.CommandText = sqlQuery;
  // 測定開始
SqlDataAdapter adapt = new SqlDataAdapter(command);
DataSet ds = new DataSet();
adapt.Fill(ds);
// 測定終了
}

  • SqlCommand.ExecuteReaderメソッドからSqlDataReader.Closeメソッド完了までの時間。

using(SqlConnection con = new SqlConnection(connectionString))
{
con.Open();
SqlCommand command = con.CreateCommand();
command.CommandText = sqlQuery;
  // 測定開始
SqlDataReader reader = command.ExecuteReader();
while(reader.Read())
{
}
reader.Close();
// 測定終了
}

測定方法

  • 測定をそれぞれ7回行い、最大値と最小値を除く5回の平均を取得する。
  • 測定する時間はDateTime.Ticksを使用する。1Ticksは100ナノ秒でTicksの1000万の位の十進数が秒に相当します(文献(1)のこの回りくどい表現は何なんでしょう…)。

測定環境

  • DBサーバ
    CPU PentiumM 1.8GHz 
    Memory 1GB
  • クライアント
    CPU Pentium4 2.66GHz (L1キャッシュとL2キャッシュはOFF)
    Memory 1GB

クライアントの方がスペックがいいように見えますが、実はL1とL2キャッシュを切っているので、パフォーマンスは激悪です。(立ち上げるのに30分かかった(;´Д`)

L1とL2キャッシュを切った理由は簡単で、普通のPCでDataReaderなりDataAdapterを使用するなりした場合、高速過ぎて下記のSQLの実行時間t3が全体の大きな部分を占めてしまうことになってしまうのです。ぶっちゃけSQLの実行時間t3を短くできる手段は持ち合わせていないので、逆にt2の部分を相対的にでかくしてやろうってことにしただけです。

測定できる時間は下図のt1部分なので、t2>>t3となればt1≒t2となるはずなのです。

ということで、計測を行った結果が以下の通り。

結果 .NET 1.1

レコード数

DataReader

DataSet

100

156250

625000

200

312500

1281250

300

468750

2000000

400

531250

2500000

500

656250

3156250

大体5倍程度の差が出ていますね。ネットワークを監視してデータベースとクライアント間のネットワークを監視できればよかったんですが、如何せん劣悪なPCでEtherealを起動するわけにはいきません。ルータに監視用のインタフェースは無いし、バカハブも手元にはねっす。
とりあえず、.NET1.1と.NET2.0の(定性的な)比較はできますので、.NET2.0の方の計測もやってみます。

結果 .NET2.0

レコード数

DataReader

DataSet

100

156250

937500

200

281250

1843750

300

375000

2781250

400

500000

3750000

500

687500

4750000

差が7~8倍に増えてますね…DataReaderの結果が.NET 1.1と変わらないことを考慮すると、DataAdapterかDataSetが遅くなったんでしょう。かなりざっくりとした測定をしているので、あまりはっきりしたことは言えませんが、もしかしたらDataTableの機能を充実させた分パフォーマンスが落ちたのかもしれません。

 

あとは、.NET2.0ではDataReaderをDataTableへと変換することができるようになったので、DataReaderで読み込んだ後にDataTable.Loadを使用しDataReaderをDataTableに変換した結果も見てみたいと思います。

DataTable dt = new DataTable();
  dt.Load(reader);

結果 .NET2.0 DataReader2DataTable

レコード数

DataReader2DataTable

DataSet

100

1968750

937500

200

3562500

1843750

300

4500000

2781250

400

6031250

3750000

500

7250000

4750000

うむ。遅い!DataSetを直接使用するよりも遅いですね。

DataSet vs DataReader グラフ

 

まとめ

文献(1)の様に30倍も差がある結果はでませんでしたが、やっぱり速度差はそれなりにあるみたいです。そんでもって.NET2.0になってちょびっと遅くなったと。

とはいえ、余程レコード数が多くならない限り処理に1秒以上かかることはあまりないですし、文献(2)や文献(3)で述べられてるように、開発効率などはDataSetを使用したほうがサクっとできる場合があります(Genericの登場でArrayListが大活躍するかもしれませんが…)。N階層アーキテクチャを採用した場合、各層を伝播するオブジェクトとしてDataReaderを使用するのは気持ち悪いし、そうするとO/Rマッパー、もしくはそれに近い処理が必要となってしまいます。

この辺はプロジェクトの規模や方針に合わせてやっていくしかなさそうですが、パフォーマンスを考えるうえではDataReaderい軍配が上がりそうです。

参考文献
(1) A Speed Freak's Guide to Retrieving Data in ADO.NET
(2) Why I Don't Use DataSets in My ASP.NET Applications
(3) More On Why I Don't Use DataSets in My ASP.NET Applications

投稿日時 : 2007年2月6日 0:34

コメントを追加

# re: DataSet vs DataReader 検証 .NET2.0 2008/11/09 0:39 Gates

DataReader使うのは大量データをデータベースからファイルに吐くときぐらいだろ?

# DataTableのLoad メソッド 2008/12/08 1:45 やじゅ@アプリケーション・ラボ わんくま支局

DataTableのLoad メソッド

タイトル  
名前  
URL
コメント