- - PR -
ADO.NETで、データベースの初回更新が遅い
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2008-01-30 12:23
いつもお世話になっております。
Visual Basic 2005のWindowsアプリケーションで、社員の出社時刻を登録する単体プログラムを作成しています。 データベースは、SQL Server 2005のExpressで、ローカルのデータベースです。 そのプログラムは、朝社員が出社する前には起動していて、画面に表示されている状態です。 で、社員は、自分の社員番号をバーコードリーダーから入力して、そうすると登録されるのようになっているのですが、起動後の初回更新時の遅いです(7〜10秒)。 更新には、SqlCommandでInsert文を発行して、Commandのパラメータに 更新内容をセットして、CommandのExequteNonQueryで更新しています。 原因は、接続(SqlConnection)を作成してOpenするときに時間がかかっているようでした。 それで、SqlConnectionをプログラムの起動時にOpenして、そのままにしておくようにしたら早くなりました。 ただ、基本的に接続は、使用する直前に作成して、必要なくなったらクローズして開放するのがよいと聞くので、この作り方は問題なのではないかと思います。 これを別の方法で解消することはできるのでしょうか? なにか、方法がありましたら、どうぞよろしくお願いします。 | ||||
|
投稿日時: 2008-01-30 12:34
そのプログラムは毎日、再起動してるんですか?
コネクションプーリングを使用してるなら、初回起動時にOpenしてすぐCloseでいいと思います。 | ||||
|
投稿日時: 2008-01-30 13:09
burton999さん、ありがとうございます。
はい、毎日再起動しています。 おっしゃる通りにしたら、開きっぱなしのときと応答速度は変わりませんでした。 こういう風にすればよいのですね。 どのプログラムでも、初回更新時がやたら遅かったので、 これからはそうしてみようと思います。 ありがとうございます。 | ||||
|
投稿日時: 2008-01-30 15:01
たびたびすみません。
元々投稿した問題の、更新速度は改善されたのですが、別のプログラムも同じ方法で直そうとしたら、速度が改善されませんでした。 そのプログラムというのは、データベースはSqlServer 2005で、Visual Basic 2005のWindowsアプリケーションです。 データプロバイダは、.NET Framework Data Provider for SQL Serverを使用しました。 二つのテーブルを一度に更新します。 親テーブルは一画面で1レコード、子テーブルは、1画面で複数レコード更新します。 画面上は、DataGridViewを使用して、編集や追加を行い、内部では、DataSetを利用していて、その中にリレーションを組んだ親子関係のある2つのDataTableを定義してあります。 更新には、SqlDataAdapterを使用しています。 これは、つくりは、型付のDataSetでデザイナから自動生成されるコードを元にして、更新Commandのクエリの中身などを少し編集して作りました。 で、このプログラムも、初回更新時が遅いので、画面の起動時に実際には使用しないSqlConnectionを作成して、オープンして解放しました。 接続文字列は、常に同じ文字列の変数から取得しているので、そうすれば、接続プールに入ると思ったのですが、やっぱり初回の更新時は遅いです。 とすると、意味のない処理をしているように思えます。 Insertでも、UpdateでもDeleteでも、何かしらの更新処理を一度実行すると、次からは早いのですが。。。 これは、回避できないのでしょうか。 それとも私の認識が間違っているのでしょうか。 自分でも引き続き調べてみますが、ご存知の方がいらっしゃいましたら、どうかよろしくお願いいたします。 [ メッセージ編集済み 編集者: むーみん 編集日時 2008-01-30 15:19 ] | ||||
|
投稿日時: 2008-01-30 15:46
1コネクションで2つのテーブルを更新しているのでしょうか? それとも、2つの異なるコネクションを同時のOpenしてテーブルを更新していますか? | ||||
|
投稿日時: 2008-01-30 16:14
burton999さん、たびたびありがとうございます。
親テーブル、子テーブル、それぞれ別のインスタンスのSqlConnectionです。 接続文字列の取得元のみ同じ接続文字列変数です。 説明不足ですみません。 型付のDataSetというのは、作成方法は、プロジェクトに新規の項目追加で、DataSetを選択して、そこにサーバエクスプローラからテーブルをDrag&Dropして、そうすると、その型付のDataTableとTableAdapterというものが自動生成されるので、それをデザイナファイルのコードを見て、そのTableAdapterクラスというのを元にしました。 このTebleAdapterクラスは、プライベートプロパティで、SqlDataAdapterとSqlConnectionを持っています。 また、FillやUpdateメソッドも持っています。FillやUpdate時にこのSqlDataAdapter型(?)プロパティやSqlConnection型プロパティが使用されています。 このTableAdapterクラスのUpdateメソッドは、結局SqlDataAdapterのUpdateメソッドを呼び出しています。 私は、これを利用して、画面で更新ボタンを押したときに、親のTableAdapterクラスをインスタンス化して、そのインスタンスのUpdateメソッドを呼び出して、親DataTableを渡してあげました。 その後、全く同様の手順で、子のTableAdapterインスタンスのUpdateメソッドを呼び出しました。 更新ボタン押下時の更新処理が終了したら、このTableAdapterのインスタンスは解放します。 (ので、更新ボタンを押下するたびに、SqlDataAdapterもSqlConnectionもインスタンス化されてOpenされます。 なのに、初回だけ遅いです。。。) そのUpdateの中で、実際には、SqlDataAdapterをインスタンス化して、SqlConnectionもインスタンス化してSqlDataAdapterのUpdateメソッドを呼び出しています。 SqlConnectionのオープンは明示的に行わないので、DataAdapterがそのSqlConnectionをOpenしてくれて、Closeしてくれていると思います。 実際のコードを載せると膨大な量になってしまうので、一応説明したのですが、分かりにくいでしょうか。。 [ メッセージ編集済み 編集者: むーみん 編集日時 2008-01-30 16:20 ] | ||||
|
投稿日時: 2008-01-30 16:58
コネクションプールはDBサーバーとの物理的な接続を使いまわす技術です。
アプリケーション起動時はプールには接続は無い状態です。 起動時に接続をOpenすることで、DBサーバーと物理的な接続が確立されます。(おそらくこの処理がボトルネックになっている) その後、すぐCloseすることで、接続がプールに戻されます。(物理的な接続は確立されたままです) この状態では、プールには接続が1つしかない状態です。 ここである処理が接続をOpenすると、プールにある接続が再利用されます。(既に物理的な接続は確立されているので処理が速い) さらに、別の処理で接続をOpenすると、プールに有効な接続が無いので、DBサーバーと物理的な接続を確立する必要がでてきます。 上記が原因だと思います。 対処方法としては、アプリケーション起動時に、コネクションプールに十分な接続を溜めておけばいいと思います。
| ||||
|
投稿日時: 2008-01-30 17:11
SQL Server 2000だからなのかな?
試してみたら、AdapterのConnectionはinternalなプロパティになったんだけどなぁ。 それは置いといて、データセットデザイナで親テーブルのアダプタのプロパティを表示させると、Connectionプロパティの中にModifireというプロパティがあります。 まずこれをinternal(private?)からpublicにします。 子テーブルのアダプタについても同様に処理します。 親テーブル、子テーブルのアダプタをインスタンス化する際
と、Connectionを共有させてやってはいかがでしょうか? こうすると、ひとつのConnectionだけのOpenとなるので、起動時にひとつ接続が開いていれば、初回の子テーブルの更新が遅くなることはないように思えます。 ちなみに、DataSetが定義されたアセンブリと呼び出しているアセンブリが同じなら、internalのままでも、Connectionを共有できると思います。 DataSetの定義はdllに呼び出しはexeというように、アセンブリが分かれる場合は、publicにする必要があるでしょう。 また、Connection共有しとかないと、ひとつのトランザクションで親・子を更新できない気がするんだけど、気のせい? [ メッセージ編集済み 編集者: かずくん 編集日時 2008-01-30 17:14 ] |