C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[3]: バインド配列に関して


(過去ログ 29 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■14019 / inTopicNo.1)  バインド配列に関して
  
□投稿者/ コスケ (6回)-(2008/02/07(Thu) 20:34:07)

分類:[.NET 全般] 

お世話になっております。コスケと申します。
超VB.NET初心者です...

Win2003 VB.net Oracle10gにて開発しております。

約600万件のテーブルに約40万件のCSVデータをInsert処理を
行うプログラムの開発を行っております。

現在、下記の通りバインド変数を用いてInsert処理を行っていますが、
処理時間が遅い為、バインド配列を用いて、Insert処理を何万件が
まとめて発行したいと考えております。
しかしながらバインド変数の記述の仕方がいまいちわからずここに
投稿させていただきました。

ソースを記載します。

Module TableInsert
    Public Sub TblInsert()

        Dim strTD As String
        Dim blnFn1eof As Boolean
	
	'===tableの列定義===
        strTD = mTD_1 & mTD_2 & mTD_3 & mTD_4 & mTD_5

        'SQL作成
        strSQL = "INSERT INTO TD_ZAIKO (" + strTD + ") VALUES ("
        strSQL = strSQL & ":HANCD,:SSCD,:COMCD,:NSTCD,"
        strSQL = strSQL & ":TGNSU,:TGNTA,:TGNKI,"
        strSQL = strSQL & ":TJZSU,:TJZTA,:TJZKI,"
        strSQL = strSQL & ":SHISU,:SHIKO,:SHIKI,"
        strSQL = strSQL & ":TNSSU,:TNSKO,:TNSKI,"
        strSQL = strSQL & ":TNKSU,:TNKKO,:TNKKI,"
        strSQL = strSQL & ":URISU,:URIKO,:URIKI,"
        strSQL = strSQL & ":ZGNSU,:ZGNKO,:ZGNKI,"
        strSQL = strSQL & ":GTZSU,:GTZKO,:GTZKI,"
        strSQL = strSQL & ":RIEKI,:SHIMED,:TATENE,"
        strSQL = strSQL & ":SCOMCD,:SNSTCD,:SHIMEYM,"
        strSQL = strSQL & "to_date('" & mDate & " " & mTime & "','YYYY/MM/DD/ HH24:MI:SS'),"
        strSQL = strSQL & "'" & mUuid & "'"
        strSQL = strSQL & ") "

        blnFn1eof = False

	'===約40万件のCSVをInsert===
        Do Until blnFn1eof = True

	    '===各項目にCSVから読み込んだデータをセット===
            Dim HANCD As String = Mid(strBuf, 1, 6)
            Dim SSCD As String = Mid(strBuf, 8, 6)
            Dim COMCD As String = Mid(strBuf, 15, 6)
            Dim NSTCD As String = Mid(strBuf, 22, 3)
            Dim TGNSU As String = Mid(strBuf, 26, 13)
            Dim TGNTA As String = Mid(strBuf, 40, 10)
            Dim TGNKI As String = Mid(strBuf, 51, 12)
            Dim TJZSU As String = Mid(strBuf, 64, 13)
            Dim TJZTA As String = Mid(strBuf, 78, 10)
            Dim TJZKI As String = Mid(strBuf, 89, 12)
            Dim SHISU As String = Mid(strBuf, 102, 13)
            Dim SHIKO As String = Mid(strBuf, 116, 8)
            Dim SHIKI As String = Mid(strBuf, 125, 12)
            Dim TNSSU As String = Mid(strBuf, 138, 13)
            Dim TNSKO As String = Mid(strBuf, 152, 8)
            Dim TNSKI As String = Mid(strBuf, 161, 12)
            Dim TNKSU As String = Mid(strBuf, 174, 13)
            Dim TNKKO As String = Mid(strBuf, 188, 8)
            Dim TNKKI As String = Mid(strBuf, 197, 12)
            Dim URISU As String = Mid(strBuf, 210, 13)
            Dim URIKO As String = Mid(strBuf, 224, 8)
            Dim URIKI As String = Mid(strBuf, 233, 12)
            Dim ZGNSU As String = Mid(strBuf, 246, 13)
            Dim ZGNKO As String = Mid(strBuf, 260, 8)
            Dim ZGNKI As String = Mid(strBuf, 269, 12)
            Dim GTZSU As String = Mid(strBuf, 282, 13)
            Dim GTZKO As String = Mid(strBuf, 296, 8)
            Dim GTZKI As String = Mid(strBuf, 305, 12)
            Dim RIEKI As String = Mid(strBuf, 318, 12)
            Dim SHIMED As String = Mid(strBuf, 331, 2)
            Dim TATENE As String = Mid(strBuf, 334, 1)
            Dim SCOMCD As String = Mid(strBuf, 336, 6)
            Dim SNSTCD As String = Mid(strBuf, 343, 3)
            Dim SHIMEYM As String = Mid(strBuf, 347, 6)
            mDate = String.Format(Today, "yymmdd")
            mTime = String.Format(TimeOfDay, "hhmmss")

            Try
                Dim cmd As OracleCommand = New OracleCommand

                cmd.Connection = conn
                cmd.CommandText = strSQL

                '===パラメータセット===
                Dim pHANCD As OracleParameter = cmd.Parameters.Add("HANCD", HANCD)
                Dim pSSCD As OracleParameter = cmd.Parameters.Add("SSCD", SSCD)
                Dim pCOMCD As OracleParameter = cmd.Parameters.Add("COMCD", COMCD)
                Dim pNSTCD As OracleParameter = cmd.Parameters.Add("NSTCD", NSTCD)
                Dim pTGNSU As OracleParameter = cmd.Parameters.Add("TGNSU", TGNSU)
                Dim pTGNTA As OracleParameter = cmd.Parameters.Add("TGNTA", TGNTA)
                Dim pTGNKI As OracleParameter = cmd.Parameters.Add("TGNKI", TGNKI)
                Dim pTJZSU As OracleParameter = cmd.Parameters.Add("TJZSU", TJZSU)
                Dim pTJZTA As OracleParameter = cmd.Parameters.Add("TJZTA", TJZTA)
                Dim pTJZKI As OracleParameter = cmd.Parameters.Add("TJZKI", TJZKI)
                Dim pSHISU As OracleParameter = cmd.Parameters.Add("SHISU", SHISU)
                Dim pSHIKO As OracleParameter = cmd.Parameters.Add("SHIKO", SHIKO)
                Dim pSHIKI As OracleParameter = cmd.Parameters.Add("SHIKI", SHIKI)
                Dim pTNSSU As OracleParameter = cmd.Parameters.Add("TNSSU", TNSSU)
                Dim pTNSKO As OracleParameter = cmd.Parameters.Add("TNSKO", TNSKO)
                Dim pTNSKI As OracleParameter = cmd.Parameters.Add("TNSKI", TNSKI)
                Dim pTNKSU As OracleParameter = cmd.Parameters.Add("TNKSU", TNKSU)
                Dim pTNKKO As OracleParameter = cmd.Parameters.Add("TNKKO", TNKKO)
                Dim pTNKKI As OracleParameter = cmd.Parameters.Add("TNKKI", TNKKI)
                Dim pURISU As OracleParameter = cmd.Parameters.Add("URISU", URISU)
                Dim pURIKO As OracleParameter = cmd.Parameters.Add("URIKO", URIKO)
                Dim pURIKI As OracleParameter = cmd.Parameters.Add("URIKI", URIKI)
                Dim pZGNSU As OracleParameter = cmd.Parameters.Add("ZGNSU", ZGNSU)
                Dim pZGNKO As OracleParameter = cmd.Parameters.Add("ZGNKO", ZGNKO)
                Dim pZGNKI As OracleParameter = cmd.Parameters.Add("ZGNKI", ZGNKI)
                Dim pGTZSU As OracleParameter = cmd.Parameters.Add("GTZSU", GTZSU)
                Dim pGTZKO As OracleParameter = cmd.Parameters.Add("GTZKO", GTZKO)
                Dim pGTZKI As OracleParameter = cmd.Parameters.Add("GTZKI", GTZKI)
                Dim pRIEKI As OracleParameter = cmd.Parameters.Add("RIEKI", RIEKI)
                Dim pSHIMED As OracleParameter = cmd.Parameters.Add("SHIMED", SHIMED)
                Dim pTATENE As OracleParameter = cmd.Parameters.Add("TATENE", TATENE)
                Dim pSCOMCD As OracleParameter = cmd.Parameters.Add("SCOMCD", SCOMCD)
                Dim pSNSTCD As OracleParameter = cmd.Parameters.Add("SNSTCD", SNSTCD)
                Dim pSHIMEYM As OracleParameter = cmd.Parameters.Add("SHIMEYM", SHIMEYM)

                cmd.ExecuteNonQuery()
            
	  Catch e As OracleException
                strErrText = "Code: " & e.ErrorCode & vbCrLf & _
                                      "Message: " & e.Message

        'ログファイル出力
                Print(fn2, mDate & mTime)
                Print(fn2, strDbName & strUser & strPass & " データ挿入失敗!")
                Print(fn2, strErrText)
                Call AbortClose()
                End
            End Try

            '最終レコードの場合 blnFn1eofをTrueに設定(LOOP終了条件)。それ以外は一行読み込み
            If EOF(fn1) = True Then
                blnFn1eof = True
            Else
                strBuf = LineInput(fn1)
                cntInp = cntInp + 1
            End If
        Loop
    End Sub
End Module


これをどのようにバインド配列をもちいて記述すればよいのでしょうか?


このような投稿の仕方で誠に申し訳ありませんが、どうか宜しくお願い致します。


引用返信 編集キー/
■14024 / inTopicNo.2)  Re[1]: バインド配列に関して
□投稿者/ やじゅ (123回)-(2008/02/07(Thu) 22:13:52)
やじゅ さんの Web サイト
No14019 (コスケ さん) に返信
> 約600万件のテーブルに約40万件のCSVデータをInsert処理を
> 行うプログラムの開発を行っております。
>

参考リンクだけですが

ODP.NETでOracle固有の機能を活用する
http://www.atmarkit.co.jp/fdb/rensai/odpdotnet01/odpdotnet04.html

Oracle で大量の insert を高速に処理する方法の検討
http://www.drk7.jp/MT/archives/001315.html

大量データについて
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=23323&forum=26&3

PL/SQL によるバルクインサート処理
http://www.shift-the-oracle.com/plsql/bulk-insert.html
引用返信 編集キー/
■14025 / inTopicNo.3)  Re[1]: バインド配列に関して
□投稿者/ はつね (445回)-(2008/02/07(Thu) 22:17:45)
No14019 (コスケ さん) に返信
> 現在、下記の通りバインド変数を用いてInsert処理を行っていますが、

OracleCommandやOracleParameterの宣言をループの中にいれていますけれど、ループの外で宣言してOracleParameterへの値の設定とOracleCommandのExecuteNonQueryメソッドの実行を行ったらどうなりますか?

で、自分だったらSQL*Loader使う方法も検討してみるかも。

引用返信 編集キー/
■14035 / inTopicNo.4)  Re[2]: バインド配列に関して
□投稿者/ コスケ (7回)-(2008/02/08(Fri) 09:27:18)
やじゅ様
はつね様

ご返信ありがとうございます。

>やじゅ様
ご投稿頂いた参考リンクですが、いろいろと調べているうちに
全てチェックしたものでした...申し訳ありません。
こちらのリンクを元にバインド配列に挑戦しようと試みたのですが、
どのようにとっかかってよいのかわからず、こちらに投稿させて頂きました。

  >ODP.NETでOracle固有の機能を活用する
  >http://www.atmarkit.co.jp/fdb/rensai/odpdotnet01/odpdotnet04.html

上記のリンクにてバインド配列の説明があるのですが、

Dim myArrayDeptNo() As Integer = {10, 20, 30}
cmd.CommandText = _
"insert into dept(deptno) values (:deptno)"
cmd.ArrayBindCount = 3
Dim prm As OracleParameter = _
New OracleParameter("deptno", OracleDbType.Int32)
prm.Direction = ParameterDirection.Input
prm.Value = myArrayDeptNo
cmd.Parameters.Add(prm)
cmd.ExecuteNonQuery()

というコードで、まず
1.一行目の配列の宣言をどのようにしたらよいのかわかりません...特に {10, 20, 30}の部分
2.どこでパラメータにCSVから取得したデータをいれてよいかわかりません...

といった感じです。

>はつね様

確かにLOOP処理の中に繰り返さなくてよいものが入っています。
すぐに修正しようと思います。

またSQL*Loaderの件ですが、とても速いと認識しているのですが、
ダイレクトパスインサートですと、こちらの仕様上あまり好ましくない
と考えられており、使用できません。
こちらの都合で大変申し訳ありません。


いろいろ調べてみたのですが、バシッとくるものがなく、こちらに投稿させて
頂いた次第です。
何かよい方法等がございましたら、ご協力お願い致します。

引用返信 編集キー/
■14036 / inTopicNo.5)  Re[3]: バインド配列に関して
□投稿者/ はつね (446回)-(2008/02/08(Fri) 09:33:48)
はつね さんの Web サイト
No14035 (コスケ さん) に返信
> またSQL*Loaderの件ですが、とても速いと認識しているのですが、
> ダイレクトパスインサートですと、こちらの仕様上あまり好ましくない
> と考えられており、使用できません。

どのような仕様が好ましくないのでしょうか。
大抵は食わず嫌いであったり、その考え自体がプロジェクト内でも形骸化していたり、処理速度と天秤にかけたら吹き飛んでしまうくらい些細な場合が多いと思います。

引用返信 編集キー/
■14041 / inTopicNo.6)  Re[3]: バインド配列に関して
□投稿者/ やじゅ (126回)-(2008/02/08(Fri) 10:13:43)
No14035 (コスケ さん) に返信
> 1.一行目の配列の宣言をどのようにしたらよいのかわかりません...特に {10, 20, 30}の部分
> 2.どこでパラメータにCSVから取得したデータをいれてよいかわかりません...
>

下記サイトを参考に配列に値を入れる処理を書けばいいかな。型指定が微妙ですが・・・

配列とArrayListを変換する
http://homepage1.nifty.com/rucio/main/VBdotNet/Samples201/Sample217ArrayAndArrayList.htm

動的配列を使う方法
http://www.geocities.co.jp/SiliconValley-Bay/9960/vb/redim.html
引用返信 編集キー/
■14043 / inTopicNo.7)  Re[4]: バインド配列に関して
□投稿者/ コスケ (8回)-(2008/02/08(Fri) 10:38:48)
No14036 (はつね さん) に返信
> ■No14035 (コスケ さん) に返信
>>またSQL*Loaderの件ですが、とても速いと認識しているのですが、
>>ダイレクトパスインサートですと、こちらの仕様上あまり好ましくない
>>と考えられており、使用できません。
>
> どのような仕様が好ましくないのでしょうか。
> 大抵は食わず嫌いであったり、その考え自体がプロジェクト内でも形骸化していたり、処理速度と天秤にかけたら吹き飛んでしまうくらい些細な場合が多いと思います。
>

はつね様

ご返信ありがとうございます。
ダイレクトパスインサートですと、最高水位標の後ろにデータを追加する為
空洞化が出来てしまうということで、あまり好まれていません。
これを解消するためには定期的なEXP/IMPが必要になる為、こちらも併せて
好まれていないようです。
引用返信 編集キー/
■14045 / inTopicNo.8)  Re[5]: バインド配列に関して
□投稿者/ はつね (447回)-(2008/02/08(Fri) 11:20:46)
はつね さんの Web サイト
No14043 (コスケ さん) に返信
> ダイレクトパスインサートですと、最高水位標の後ろにデータを追加する為
> 空洞化が出来てしまうということで、あまり好まれていません。

Oracle 10gですよね。「セグメントの縮小」機能はご存知ですか?
http://otndnld.oracle.co.jp/obe/obe10gdb/manageability/space/space.htm#t1c

あとは、ダイレクトパスが嫌だって事であれば、SQL*Loaderで従来型パスロードを選択するのでも良いかと。


引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -