tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルフォーム内に配置した複数のComboBoxのリストについて
記事No9764
投稿日: 2010/01/06(Wed) 23:55
投稿者たる
初心者です。

WindowsXP(SP3)
VB2008を使用しています。

フォームに複数のComboBoxを配置して、リストをAccessの各テーブルから取得
したい時は通常どのような方法をとるべきなのでしょうか?

データベース接続クラスを作成(OleDbDataAdapter、DataTable使用)し、
フォームロード時にそのクラスをインスタンス化して、DataTableのフィールドを
Combobox.DisplayMemberで表示させる。という方法をとっているのですが
10個程度Comboboxを配置して、すべて違うテーブルからリストを作成するのには
とても時間がかかるので(5秒くらい)、もっと早くできないものでしょうか?

よい方法があればご教授願います。
よろしくお願いします。

[ツリー表示へ]
タイトルRe: フォーム内に配置した複数のComboBoxのリストについて
記事No9765
投稿日: 2010/01/07(Thu) 09:59
投稿者るしぇ
まずは何がボトルネックかもう少し明確に調査してください。

情報としてデータ件数と実行環境のマシンスペックが抜けていますね。

実行時間についてもこちらのサイトにはサンプルがあるのですから、
「ぐらい」とかいう表現を使う必要は無いはずです。
http://hanatyan.sakura.ne.jp/dotnet/day03.htm#no11
プログラムの要所に所要時間をデバッグ出力するような
コードを入れれば、接続に時間が掛かっているのか、
データ検索に時間が掛かっているのか、表示に時間が
掛かっているのか分かるのでは?

CPU 2GHz、960MB RAM、WinXp Pro(SP3)
テーブルのデータ件数20〜100件程度の
テーブルから10個のコンボボックスに
表示するプログラムで掛かった処理時間は
0.984375 秒でした。(初回)
一度MDBファイルに接続し、Closeした後
2回目からの処理時間は平均
0.253 秒でした。(10回平均)

>すべて違うテーブルからリストを作成するのには
>とても時間がかかるので
一度接続してしまえば、接続は使いまわせますし、
テーブルが違うというだけで処理が極端に遅くなる
ことはありません。
まぁ、これもテストプログラム作成して確認すれば
分かるはずですが。

初心者だろうが、常識で考えて調べられることは、もっと
たくさんあるはずです。

[ツリー表示へ]
タイトルRe^2: フォーム内に配置した複数のComboBoxのリストについて
記事No9766
投稿日: 2010/01/07(Thu) 11:53
投稿者たる
るしぇさん回答ありがとうございます。

> まずは何がボトルネックかもう少し明確に調査してください。
申し訳ございません。調査不足でした。

CPU 2GHz、1.99GB RAM、WinXP Pro(SP3)の環境です。
テーブルデータ件数20〜50件程度です。
こちらでテストしたら、10個のComboBoxに表示する処理時間は
2.515秒でした。
MDB接続した後に、後処理としてDisposeしているので
Closeした後も同じように時間がかかります。

データ接続がネックみたいなので、データ接続について調べてみます。
> 初心者だろうが、常識で考えて調べられることは、もっと
> たくさんあるはずです。
以後気をつけます。

[ツリー表示へ]
タイトルRe^3: フォーム内に配置した複数のComboBoxのリストについて
記事No9767
投稿日: 2010/01/07(Thu) 15:12
投稿者たる

DataAdapterを使用せずに、DataReaderで読み込んだら
1.706秒まで改善しましたが、投稿キーNo.9765で
試していただいた結果とはだいぶ遅いです。

どうやったらNo.9765のように早く処理できるのでしょうか?

[ツリー表示へ]
タイトルRe^4: フォーム内に配置した複数のComboBoxのリストについて
記事No9769
投稿日: 2010/01/07(Thu) 16:56
投稿者るしぇ
> MDB接続した後に、後処理としてDisposeしているので
> Closeした後も同じように時間がかかります。
よく勉強されてますね。
ただ、Dispose も微々たる物ですけどね。
あんまり関係ないと思います。

まず、データベースに初回接続時は時間が掛かります。
ここで1秒前後掛かる事は仕方なしと思ってます。
# 今、再度同じテストプログラムを実行したら1.3秒
# 掛かりました。
で、一度接続した場合、「接続プール」という考え方が
ありまして、これはコードで Close した Dispose した
とは別次元の話になります。OS レベルで1度起動した
アプリはメモリ上に残っていて2回目の起動が速くなる
ということがありますので、知識として知っておいて
下さい。アプリのレベルでここを制御する事は、まず、
ありません。
データベースにも一度検索された条件・データはメモリ
上に保持され、2回目以降速くなる機能があります。
アプリで制御することはありません。データベースの
機能です。

しかし、質問内容から、初回のフォームロード時の話
ですから、どうやっても1秒前後は掛かる。
最終的に2秒前後なら、まぁ、アプリとしては合格ライン
ではないでしょうか?

ここから改善するには、フォームロード時には接続だけ
開いておいて、コンボボックスクリック時にそのコンボ
ボックスのデータだけ検索に行く(もちろん初回だけ)
とかいうトリッキーな設計でも考えないと無理な気が
します。

それは置いておいて、もっと基本的なところは押さえて
あるでしょうか?。

速くするには単純にデータ量を少なくすればいいです。
DisplayMember で表示するデータを決めていますが、
他のデータは全て使うのですか?
使わないデータなら、データベースから取り出さなくて
いいですよね?テーブル丸ごと取り出しているのなら
必要なデータだけ取り出すことで速くなります。

テーブル設計はどうでしょう?主キーは?インデックスは?
要求したデータをデータベースが返す時間は最適化
されていますか?

あとは、コンボボックスの描画、データの読込みでも
改善できる可能性はありますが、100件程度のデータでは
必要ないと思いますので省略します。

そういったノウハウを注ぎ込んで、0.5秒から1秒くらい
短縮できる可能性はあるでしょう。

ここまでくると仕様上コンボボックスで選択したレコードの
データを全部使うためにあらかじめ検索してるとかだの
プログラミング設計も関係してきます。
主キーだけ検索しておいて、コンボボックス選択時に
該当データだけ検索しなおすような、根本的な設計改善が
必要になります。

>どうやったらNo.9765のように早く処理できるのでしょうか?
特別なことはしてません。基本を押さえて単純なテーブルを
たるさんの出された条件どおり実行しています。
DataReader にさえしてません。

        Dim Cn As New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Database\Test.mdb")
        Dim SQLCm As OleDbCommand = Cn.CreateCommand
        Dim Adapter As OleDbDataAdapter
        Dim dt As DataTable
        Dim sTime0 As DateTime = Now
        Dim eTime0 As DateTime

        Cn.Open()

        SQLCm.CommandText = "SELECT フィールド1 FROM テーブル1"
        Adapter = New OleDbDataAdapter(SQLCm)
        dt = New DataTable
        Adapter.Fill(dt)
        Me.ComboBox1.DataSource = dt
        Me.ComboBox1.DisplayMember = "フィールド1"

        SQLCm.CommandText = "SELECT フィールド2 FROM テーブル2"
        Adapter = New OleDbDataAdapter(SQLCm)
        dt = New DataTable
        Adapter.Fill(dt)
        Me.ComboBox2.DataSource = dt
        Me.ComboBox2.DisplayMember = "フィールド2"

        ’コンボ10まで同様のため、省略

        Cn.Close()

        eTime0 = Now
        Debug.WriteLine(eTime0.Subtract(sTime0).TotalSeconds & " 秒かかりました。")


あ、実力は魔界の仮面弁士さんの方が上なので、更に極めたいならもう少し頑張ってください。
ボクが提供できる情報は以上です。

[ツリー表示へ]
タイトルRe^5: フォーム内に配置した複数のComboBoxのリストについて
記事No9770
投稿日: 2010/01/07(Thu) 19:47
投稿者たる
るしぇさん回答ありがとうございます。

> まず、データベースに初回接続時は時間が掛かります。
> ここで1秒前後掛かる事は仕方なしと思ってます。
そういうものと理解致します。

> で、一度接続した場合、「接続プール」という考え方が
勉強になります。詳しく調べてみたいと思います。

るしぇさんの書いていただいているコードでテストしたら
初回起動が1.309秒、2回目以降が0.957秒でした。
私のコードではデータ接続と、テーブル生成までをクラス化
していましたので、コンボボックス毎に接続を開いたり、
閉じたりしていたのでそれで遅かったのだと思います。
その分が足を引っ張っていたのだと思います。
書いていただいたコードを参考に、データベースの作り方や、
必要なデータの取り出し方等に注意して作成していきたいと
思います。

ありがとうございました。

[ツリー表示へ]
タイトルRe^3: フォーム内に配置した複数のComboBoxのリストについて
記事No9768
投稿日: 2010/01/07(Thu) 16:48
投稿者魔界の仮面弁士
(質問1) 取得から ComboBox に表示するまでの処理は、どのように記述されていますか?
     ・DataReader で取得した結果を配列にして、.Items.AddRange で一括登録。
     ・TableAdapter で DataTable に取得し、.DataSource でバインド。
     ・DataAdapter で取得した結果を、1 件ずつ .Items.Add で登録。
     ・その他。

→ データバインドなのか、Items への登録なのかでも処理速度は変わります。
 もし、1件ずつ Items.Add するのであれば、BeginUpdate/EndUpdate の併用も忘れずに。

> こちらでテストしたら、10個のComboBoxに表示する処理時間は
> 2.515秒でした。

(質問2) 10 個それぞれは、別の内容ですか? それとも同じ内容ですか?

(質問3) 別の内容の場合、それらの元データはどのように管理されていますか?
     ・データベース自体が10個ある。
     ・データベースは1個だが、テーブルが10個ある。
     ・1個のテーブルに、各 ComboBox 用のデータが一緒に入っている。

> MDB接続した後に、後処理としてDisposeしているので
> Closeした後も同じように時間がかかります。

(質問4) その内訳を記述してみてください。
    たとえば「データを取得するまでの時間」、
    「取得したデータを、ComboBox に表示するまでの時間」
    「後処理にかかる時間」など。

[ツリー表示へ]
タイトルRe^4: フォーム内に配置した複数のComboBoxのリストについて
記事No9771
投稿日: 2010/01/07(Thu) 19:56
投稿者たる
魔界の仮面弁士さん回答ありがとうございます。

> (質問1) 取得から ComboBox に表示するまでの処理は、どのように記述されていますか?
 Whileで1行ずつ読み込んで、ComboBoxに追加しています。

> → データバインドなのか、Items への登録なのかでも処理速度は変わります。
>  もし、1件ずつ Items.Add するのであれば、BeginUpdate/EndUpdate の併用も忘れずに
 忘れないように気をつけます。

> (質問2) 10 個それぞれは、別の内容ですか? それとも同じ内容ですか?
 別の内容です。

> (質問3) 別の内容の場合、それらの元データはどのように管理されていますか?
>      ・データベースは1個だが、テーブルが10個ある。
 これに該当します。
>      ・1個のテーブルに、各 ComboBox 用のデータが一緒に入っている。
 各ComboBox毎にテーブルを作っています。

> > MDB接続した後に、後処理としてDisposeしているので
> > Closeした後も同じように時間がかかります。
>
> (質問4) その内訳を記述してみてください。
 ちょっと所用でPCから席を外れますので、検証してから書き込ませて下さい。
 今日中に書き込みたいと思いますが、明日になるかも知れません。
 よろしくお願いします。

[ツリー表示へ]
タイトルRe^5: フォーム内に配置した複数のComboBoxのリストについて
記事No9773
投稿日: 2010/01/08(Fri) 10:28
投稿者たる
遅くなりました。

質問4の件ですが、テストした結果、
データを取得する時間
最もデータが多いテーブルでは0.218秒
最もデータが少ないテーブルでは0.151秒

ComboBoxに表示する時間
最もデータが重いテーブルでは0.156秒
最もデータが少ないテーブルでは0.015秒かかりました。

トータルで2.0〜2.4秒くらいかかります。

>Closeした後も同じように時間がかかります。
と書いていたのは、FormをCloseした後も初回起動に
かかる時間とあまり変わらないという意味で書きました。
2回目以降の表示では1.7〜1.9秒の範囲です。

るしぇさんが書いていただいたコードで試したら
初回起動は1秒前後、2回目以降表示については1秒未満で
表示できるので、そのコードを参考にさせて頂きたいと
思っています。

[ツリー表示へ]