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。这应该为您交换大约 35K *(实际字段数)参数添加调用的开销,以调用对现有参数的 setparameter 调用。而且我还将调用类型更改为 ExecuteNonQuery 而不是 ExecuteScalar。

现在,通常情况下,传统观点认为您只在需要时打开/关闭与数据库的连接,我认为这隐含在此结构中(每次插入都打开/关闭),但在这种情况下,对于数据像这样的更新场景,我认为这将是一个合理的例外。

于 2012-09-12T15:58:28.193 回答