0

誰かがパフォーマンスの向上を期待していたコードがいくつかあります。毎週インポートする必要のあるスプレッドシートがあります。シートには112列と約35,000行があります。私が持っているコードは機能しますが、データのインポートには約20分かかります。Excelの列名がデータベースの列名と一致しません(これを継承しました)。これが私が使用しているコードです。(読みやすくするために、多くのフィールドを削除しました)

    'Connection String to Excel Workbook   
    Dim excelConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & MyFile & ";Extended Properties=""Excel 12.0;HDR=Yes;"""

    ' Create Connection to Excel Workbook   
    Using connection As New System.Data.OleDb.OleDbConnection(excelConnectionString)

        'List columns you need from the Excel file   
        Dim command As New System.Data.OleDb.OleDbCommand("Select * FROM [" & txtSheetName.Text & "$]", connection)
        connection.Open()

        ' Create DbDataReader to Data Worksheet   
        Using dr As System.Data.OleDb.OleDbDataReader = command.ExecuteReader()

            Dim strSql As String = ""

            strSql = "INSERT INTO MyTestTable (" & _
                        "State, [Store Code], [Store Name], [Store Zone Code], [Store Zone Code Name], " & _
                        "WeekProd, YTDNew, " & _
                        "UpdatedBy, DateUpdated" & _
                     ") VALUES (" & _
                        "@State, @StoreCode, @StoreName, @StoreZoneCode, @StoreZoneCodeName, " & _
                        "@WeekProd, @YTDNew, " & _
                        "@UpdatedBy, @DateUpdated" & _

            Try
                If dr.HasRows() Then

                    While dr.Read()

                        If Convert.ToString(dr.Item(0)) <> "" Then

                            Dim MyZone As String = Convert.ToString(dr.Item(1))
                            MyZone = StrConv(MyZone, vbProperCase)

                            Dim cmd As New SqlClient.SqlCommand
                            cmd.Connection = cn
                            cmd.CommandType = CommandType.Text
                            cmd.CommandText = strSql

                            cmd.Parameters.Add("@State", SqlDbType.VarChar).Value = ""
                            cmd.Parameters.Add("@StoreCode", SqlDbType.VarChar).Value = Convert.ToString(dr.Item(0))
                            cmd.Parameters.Add("@StoreName", SqlDbType.VarChar).Value = MyZone
                            cmd.Parameters.Add("@StoreZoneCode", SqlDbType.VarChar).Value = Convert.ToString(dr.Item(2))
                            cmd.Parameters.Add("@StoreZoneCodeName", SqlDbType.VarChar).Value = Convert.ToString(dr.Item(3))
                            cmd.Parameters.Add("@WeekProd", SqlDbType.Float).Value = Convert.ToDecimal(dr.Item(93))
                            cmd.Parameters.Add("@YTDNew", SqlDbType.Float).Value = Convert.ToDecimal(dr.Item(94))
                            cmd.Parameters.Add("@UpdatedBy", SqlDbType.VarChar).Value = MyUser.Substring(MyUser.Length - 4)
                            cmd.Parameters.Add("@DateUpdated", SqlDbType.Date).Value = Date.Today()

                            cmd.ExecuteScalar()

                        End If

                    End While

                End If

            Catch ex As Exception

                lblMessage.Text = ex.Message
                Exit Sub

            Finally

                cn.Close()
                cn = Nothing

            End Try

        End Using

    End Using
4

1 に答える 1

0

これがパフォーマンスの面で世界に火をつけるとは約束しませんが、それは役立つかもしれません。

私の最初の考えは、Excelテーブルのすべての行に新しいSqlCommandオブジェクトとパラメーターセットを作成しないことです。私はそれを一度作成し(データサイズを指定すると約35Kのオブジェクトインスタンス化のオーバーヘッドを節約するはずです)、すべてリーダーループの外側でパラメーター名を確立してから、SetParameterを呼び出して各列の値をの各行として設定しますExcelがトラバースされます。これにより、既存のパラメーターへのsetparameter呼び出しの約35K *(実数フィールドの数)パラメーター追加呼び出しのオーバーヘッドと引き換えになります。また、呼び出しタイプをExecuteScalarではなくExecuteNonQueryに変更します。

さて、通常、データベースへの接続は必要に応じて開く/閉じるだけであるという従来の知識があります。これは、この構造(挿入ごとに開く/閉じる)に含まれていると思いますが、この場合はデータです。このような更新シナリオでは、これは合理的な例外だと思います。

于 2012-09-12T15:58:28.193 に答える