- PR -

DBから取得した値をVBの配列に格納する方法

投稿者投稿内容
gt-f
会議室デビュー日: 2006/10/05
投稿数: 18
投稿日時: 2007-12-12 14:25
こんちには。gt-fと申します。
VB2005, SQLServer2005 を使って開発しております。
(OS:WinXP(sp2))

SQLServerから取得したオブジェクトを、コレクション(または配列)
に格納する処理をコーディングしております。
VCで作成した関数に、配列を渡す必要があるためです。

以下のようにSqlDataReaderを用いるとできるのですが、
レコード件数が多いと、処理に時間がかかってしまいます。

処理時間をかけずに、DBから取得した配列値をVBのコレクション
(または配列)に格納する手段はあるのでしょうか?

ネットで調べたものの見つからないため、質問させて頂きました。
よろしくお願いいたします。

--------- ソースの抜粋 ---------
Dim colAry As New ArrayList
sqlStr = "SELECT col FROM TBL"
Dim cmd As New SqlCommand(sqlStr, con)
Dim dr As SqlDataReader = cmd.ExecuteReader

'レコード件数分ループ()
Do While dr.Read()
colAry.Add(dr("col"))
Loop
-----------------------------------------------
まるく
大ベテラン
会議室デビュー日: 2004/01/09
投稿数: 181
投稿日時: 2007-12-12 14:48
引用:

gt-fさんの書き込み (2007-12-12 14:25) より:
こんちには。gt-fと申します。
VB2005, SQLServer2005 を使って開発しております。
(OS:WinXP(sp2))

SQLServerから取得したオブジェクトを、コレクション(または配列)
に格納する処理をコーディングしております。
VCで作成した関数に、配列を渡す必要があるためです。

以下のようにSqlDataReaderを用いるとできるのですが、
レコード件数が多いと、処理に時間がかかってしまいます。

処理時間をかけずに、DBから取得した配列値をVBのコレクション
(または配列)に格納する手段はあるのでしょうか?

ネットで調べたものの見つからないため、質問させて頂きました。
よろしくお願いいたします。

--------- ソースの抜粋 ---------
Dim colAry As New ArrayList
sqlStr = "SELECT col FROM TBL"
Dim cmd As New SqlCommand(sqlStr, con)
Dim dr As SqlDataReader = cmd.ExecuteReader

'レコード件数分ループ()
Do While dr.Read()
colAry.Add(dr("col"))
Loop
-----------------------------------------------



掲示されているコードは、処理の一部だと思いますが、処理に時間がかかっているのはこの部分である、という事までは、特定できているのでしょうか?

最終的な配列(どんな形式?)への変換に時間がかかっている、とかいう話では?
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-12-12 14:51
引用:

gt-fさんの書き込み (2007-12-12 14:25) より:

以下のようにSqlDataReaderを用いるとできるのですが、レコード件数が多いと、処理に時間がかかってしまいます。処理時間をかけずに、DBから取得した配列値をVBのコレクション(または配列)に格納する手段はあるのでしょうか?


一気に DataAdapter で DataTable、DataSet (型付) という素晴らしい入れ物に突っ込んだ (Fill した) 方が良いと思いましたが、

引用:

VCで作成した関数に、配列を渡す必要があるためです


これがあるために悩ましいですね。 配列でないとダメでしょうか? ご提示のコードには配列が見当たりませんが ArrayList のことでしょうか。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
gt-f
会議室デビュー日: 2006/10/05
投稿数: 18
投稿日時: 2007-12-12 14:59
引用:
--------------------------------------------------------------------------------

掲示されているコードは、処理の一部だと思いますが、処理に時間がかかっているのはこの部分である、という事までは、特定できているのでしょうか?

--------------------------------------------------------------------------------

説明不足ですみません。時間がかかっているのは以下のループ処理です。

'レコード件数分ループ()
Do While dr.Read()
colAry.Add(dr("col"))
Loop
gt-f
会議室デビュー日: 2006/10/05
投稿数: 18
投稿日時: 2007-12-12 15:06
引用:

これがあるために悩ましいですね。 配列でないとダメでしょうか? ご提示のコードには配列が見当たりませんが ArrayList のことでしょうか。



ArrayListのことです。

サンプルコードでは、コレクション(ArrayList)を使っておりますが、
配列でも構いません。
こあら
大ベテラン
会議室デビュー日: 2007/06/26
投稿数: 157
投稿日時: 2007-12-12 15:09
ぱっと見。

colAry.Add(dr(0)) の方が速そう。

dr.Read() が重いのかもしれない。

仮説ですが、内部的なFETCHが細切れに発生していて、それがボトルネックなら、
DataAdapter.FillしたDataTableから配列にコピーした方が速いかも。

[追記]
配列自体のパフォーマンスについても向上の余地がありそうです。

C#&VBジェネリック超入門(前編)
http://www.atmarkit.co.jp/fdotnet/special/generics01/generics01_01.html

第 5 章 「マネージ コード パフォーマンスの向上」
http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt05.aspx
[/追記]


[ メッセージ編集済み 編集者: こあら 編集日時 2007-12-12 15:16 ]
todo
ぬし
会議室デビュー日: 2003/07/23
投稿数: 682
投稿日時: 2007-12-12 21:42
引用:

説明不足ですみません。時間がかかっているのは以下のループ処理です。

'レコード件数分ループ()
Do While dr.Read()
colAry.Add(dr("col"))
Loop



SQL文を実行するのに時間がかかっているのか、ループに時間がかかっているのか切り分けは出来ているのでしょうか?
クエリアナライザなどでSQL文を計測してみましょう。
ループにかかる時間も計測して比較しましょう。

DataReaderの問題であれば、

第 12 章 「ADO.NET パフォーマンスの向上」
http://www.microsoft.com/japan/msdn/enterprise/pag/scalenetchapt12.aspx#scalenetchapt12_topic13

これを読む限りは、

DataAdapterよりDataReaderが吉
dr("col")よりdr(0)が吉
CommandBehavior.SequentialAccessが吉

実際に効果があるのかを時間を計測して確認しましょう。
gt-f
会議室デビュー日: 2006/10/05
投稿数: 18
投稿日時: 2007-12-13 14:08
こあら様、todo様

レス遅くなりました。
多くの情報をありがとうございます。
以下、その後の状況です。

引用:

DataAdapterよりDataReaderが吉
dr("col")よりdr(0)が吉
CommandBehavior.SequentialAccessが吉

実際に効果があるのかを時間を計測して確認しましょう。



こちらに関しましては、あまり処理速度は変わらないようでした。

計測結果:10000レコードで計測(単位:秒)
dr("bir"):
 00:00:07.2179096
dr(0):
 00:00:07.3226173
dr("bir") + CommandBehavior.SequentialAccess:
 00:00:07.2779197

引用:

仮説ですが、内部的なFETCHが細切れに発生していて、それがボトルネックなら、
DataAdapter.FillしたDataTableから配列にコピーした方が速いかも。



DataTableを使うように変更したら、ループ部分の処理速度が
劇的に早くなりました。

計測結果:10000レコードで計測(単位:秒)
00:00:00.0056927

しかし、以下のソースコードの
da.Fill(dt)で、00:00:07.3469876(秒)
かかるため、結局はループ終了まで7.3秒程かかってしまいます。

Dim da As New SqlDataAdapter(sqlStr, con)
Dim dt As New DataTable
 〜途中省略〜
da.Fill(dt)
 〜途中省略〜
For i = 0 To dt.Rows.Count - 1
 birAry.Add(dt.Rows(i).Item(0))
Next

引き続きで恐縮ですが、
da.Fill(dt) の処理速度を上げる方法をご存知でしたら、
ご教示ください。

よろしくお願いいたします。

スキルアップ/キャリアアップ(JOB@IT)