@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

MySQLのデータをCSVにする処理がだんだん遅く。

投稿者投稿内容
バニラミント
ベテラン
会議室デビュー日: 2005/05/27
投稿数: 58
投稿日時: 2006-06-30 11:29
MySQLのデータをCSVにする処理を作ってます

SQLを発行し1件単位で読み出しながら
文字列を連結して最後にファイルに書き込むという
処理にしてみました。

500件程度なら問題ない処理速度なんですが、1000件を超えた
あたりから極端に処理速度が落ちてしまいます。

いろいろと処理内容を変えてみたりしてみましたが
早くなる気配がありません。
もともとの処理の考え方がおかしいんでしょうか。。。

開発環境は次の通りです
WindowsXP Pro SP2
MySQL4.1.18(win32版)
接続方法ODBC
VisualStudio.NET2003

以下ソースです。(長くてすみません)
---------------------------------------------------------------------------

Dim cdb As New db
Dim oCmd_m As Odbc.OdbcCommand
Dim oRd_m As Odbc.OdbcDataReader

Dim ret As String = ""
Dim expStringD As String = ""
Dim expFileName As String = ""

Dim sqltxt As String = ""
sqltxt = "SELECT * FROM data_table"

Dim expCNT As Integer = 0

Try

oCmd_m = New Odbc.OdbcCommand(sqltxt, cdb.cn)
oRd_m = oCmd_m.ExecuteReader

If oRd_m.HasRows = False Then
Exit Try
End If

While oRd_m.Read

ret = ret & _
"""" & oRd_m("field00") & """" & "," & _
"""" & oRd_m("field01") & """" & "," & _
"""" & oRd_m("field02") & """" & "," & _
"""" & oRd_m("field03") & """" & "," & _
"""" & oRd_m("field04") & """" & "," & _
"""" & oRd_m("field05") & """" & "," & _
"""" & oRd_m("field06") & """" & "," & _
"""" & oRd_m("field07") & """" & "," & _
"""" & oRd_m("field08") & """" & "," & _
"""" & oRd_m("field09") & """" & "," & _
"""" & oRd_m("field10") & """" & "," & _
"""" & oRd_m("field11") & """" & "," & _
"""" & oRd_m("field12") & """" & "," & _
"""" & oRd_m("field13") & """" & "," & _
"""" & oRd_m("field14") & """" & "," & _
"""" & oRd_m("field15") & """" & "," & _
"""" & oRd_m("field16") & """" & "," & _
"""" & oRd_m("field17") & """" & "," & _
"""" & oRd_m("field18") & """" & "," & _
"""" & oRd_m("field19") & """" & "," & _
"""" & oRd_m("field20") & """" & "," & _
"""" & oRd_m("field21") & """" & "," & _
"""" & oRd_m("field22") & """" & "," & _
"""" & oRd_m("field23") & """" & "," & _
"""" & oRd_m("field24") & """" & "," & _
"""" & oRd_m("field25") & """" & "," & _
"""" & oRd_m("field26") & """" & "," & _
"""" & oRd_m("field27") & """" & "," & _
"""" & oRd_m("field28") & """" & "," & _
"""" & oRd_m("field29") & """" & "," & _
"""" & oRd_m("field30") & """" & "," & _
"""" & oRd_m("field31") & """" & "," & _
"""" & oRd_m("field32") & """"

ret = ret & ControlChars.NewLine

expCNT += 1
Me.Text = "CSVデータ出力中・・・・・ " & expCNT & " 件目を処理しています"

End While

expStringD = ret

expFileName = cs_share.GetAppPath & "\data.csv"
Dim sw As New System.IO.StreamWriter(expFileName, False, System.Text.Encoding.Default)
sw.Write(expString)
sw.Write(expStringD)
sw.Close()

Me.Text = "CSVデータ出力完了"

Catch ex As Exception

MessageBox.Show(ex.Message)

Finally

oRd_m.Close()
oCmd_m.Dispose()
cdb.cn.Dispose()

End Try
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2006-06-30 11:42
引用:

500件程度なら問題ない処理速度なんですが、1000件を超えた
あたりから極端に処理速度が落ちてしまいます。

いろいろと処理内容を変えてみたりしてみましたが
早くなる気配がありません。
もともとの処理の考え方がおかしいんでしょうか。。。



どのように変えてみたのでしょうか?
とりあえず、Stringで連結するよりはStringBuilderを使ったほうがよいでしょうし、
それよりも、1行毎にファイルに書きこんだほうがいいような気がします。
囚人
ぬし
会議室デビュー日: 2005/08/13
投稿数: 1019
投稿日時: 2006-06-30 12:57
DataReader のインデクサに文字列を使うよりも序数を使った方が効率が良いでしょうね。
さらに言うなら、インデクサを使わないで、Get〜() メソッドを使う方が良いでしょう。

引用:

とりあえず、Stringで連結するよりはStringBuilderを使ったほうがよいでしょうし、
それよりも、1行毎にファイルに書きこんだほうがいいような気がします。


前者は確かにそうですが、後者は、ん〜、どうなんでしょうか。
_________________
囚人のジレンマな日々
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2006-06-30 13:02
引用:

前者は確かにそうですが、後者は、ん〜、どうなんでしょうか。



現状だと、CSVの内容を全てメモリ内に保持していることになるので
大量データの場合、マズイのかと思いました。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-06-30 15:32
処理時間のグラフでわかることもあります。
200件 300件 400件ので計測して 、N2乗のカーブが見えるかどうですか
かるあ
ぬし
会議室デビュー日: 2003/11/16
投稿数: 1190
お住まい・勤務地: センガワ→ムサシノ
投稿日時: 2006-06-30 15:40
引用:

burton999さんの書き込み (2006-06-30 13:02) より:
引用:

前者は確かにそうですが、後者は、ん〜、どうなんでしょうか。



現状だと、CSVの内容を全てメモリ内に保持していることになるので
大量データの場合、マズイのかと思いました。



一件一件書くとさすがにファイルIOが大変なんじゃないでしょうか
50件とか100件とかの単位で書いていけばいいのかな
と思いました
burton999
ぬし
会議室デビュー日: 2003/10/06
投稿数: 898
お住まい・勤務地: 東京
投稿日時: 2006-06-30 15:47
引用:

一件一件書くとさすがにファイルIOが大変なんじゃないでしょうか
50件とか100件とかの単位で書いていけばいいのかな
と思いました



Flushしないと一定のサイズになるまで書き込まないはずなので(IOが発生しない)、意識する必要はない気がします。(多分)
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-06-30 17:04
[quote]
かるあさんの書き込み (2006-06-30 15:40) より:
引用:

burton999さんの書き込み (2006-06-30 13:02) より:
一件一件書くとさすがにファイルIOが大変なんじゃないでしょうか
50件とか100件とかの単位で書いていけばいいのかなと思いました


FileStreamは既定でバッファリングが有効なはずなので問題ないでしょう。
サイズが不足とかであれば、必要なサイズを指定すればよいです。

もしバッファリング機能がないとしても、そのためにBufferedStreamが
用意されてるんですからそれを使うべきでしょう。

わざわざ独自にメモリ上で操作することのメリットはあまりありません。
※一時的に文字列として作成しておく必要があるなら別ですが。


[ メッセージ編集済み 編集者: なちゃ 編集日時 2006-06-30 17:05 ]

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