SQL数据库表BULK更新的缺陷,使用vb.net中的登台表和批量复制

时间:2015-05-06 22:53:24

标签: sql-server database vb.net

我一直在努力提高我的vb.net程序中表更新的速度。
情况是我有一个包含10,000行和160列的表。
此表已更新通常每行更改1到100+列。
使用DataAdapter更新非常缓慢且不合适,并且在没有改进结果的情况下进行了调查。

下一个选项很可能是使用bulkcopy将数据转储到临时表中的过程,删除原始数据库表中的所有行,然后发出复制命令以将数据从登台表移回到原来的表我想更新。

考虑到在程序执行数据运行期间更新过程发生了30-50次,速度差异是惊人的

Dataadapter update = 10-15s乘以50 = 12.5 MINUTES

如上所述批量更新= 1.2-1.4s乘以50 = 1.16分钟

非凡的差异!所以我真的想采取批量更新选项 据我所知,这不是常规,但这个表将保持10,000行,而程序是单线程单用户本地数据库,消除了很多潜在的问题。

我主要担心的是数据安全性 我已将代码包含在try-catch中,但也许有一种方法可以确保所有进程正确运行,这涉及到SQL事务,就像它们在银行中一样,所以如果出现问题,一切都会颠倒过来。
鉴于我的技能水平不会超过创建下面的代码 该程序的最佳实施方式是什么?

 Try

            ESTP = "Start Bulk DBselection Update"

            Dim oMainQueryT = "Truncate Table DBSelectionsSTAGE"
            Using con As New SqlClient.SqlConnection(RacingConStr)
                Using cmd As New SqlClient.SqlCommand(oMainQueryT, con)
                    con.Open()
                    cmd.ExecuteNonQuery()
                    con.Close()
                End Using
            End Using

            ESTP = "Step 1 Bulk DBselection Update"

            Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(RacingConStr)
                bulkCopy.DestinationTableName = "DBSelectionsSTAGE"
                bulkCopy.WriteToServer(DBSelectionsDS.Tables("DBSelectionsDetails"))
                bulkCopy.Close()
            End Using

            ESTP = "Step 2 Bulk DBselection Update"

            oMainQueryT = "Truncate Table DBSelections"
            Using con As New SqlClient.SqlConnection(RacingConStr)
                Using cmd As New SqlClient.SqlCommand(oMainQueryT, con)
                    con.Open()
                    cmd.ExecuteNonQuery()
                    con.Close()
                End Using
            End Using

            ESTP = "Step 3 Bulk DBselection Update"

            oMainQueryT = "Insert INTO DBSelections Select * FROM DBSelectionsSTAGE"
            Using con As New SqlClient.SqlConnection(RacingConStr)
                Using cmd As New SqlClient.SqlCommand(oMainQueryT, con)
                    con.Open()
                    cmd.ExecuteNonQuery()
                    con.Close()
                End Using
            End Using

            Data_Base.TextBox25.Text = "Deleting data - DONE "
            Data_Base.TextBox25.Refresh()

DBSelectionsDS.Tables("DBSelectionsDetails").AcceptChanges()

        Catch ex As Exception

            ErrMess = "ERROR - occured at " & ESTP & " " & ex.ToString
            Call WriteError()
            Call ViewError()

        End Try

编辑:我将代码合并到我的项目中并采用了Dan建议的更改 更新'现在需要不到一秒钟。这是对以前代码的巨大改进。我不确定它的扩展程度如何,但在我的情况下,桌子大小大致相同(行数)我对结果非常满意。

完成DBSelectionsDS.Tables("DBSelectionsDetails").AcceptChanges()

后,别忘了接受对数据表的更改

2 个答案:

答案 0 :(得分:2)

考虑使用事务TRUNCATESWITCH替换步骤2和3,以使用暂存数据替换DBSelection表的内容。 SWITCH比复制单个行更有效,因为它只是一个元数据操作。

SWITCH通常用于SQL Server企业版,用于将数据移动(不复制)到分区表或从分区表移出数据,但它也可以用于非分区表和较小版本。 SWITCH的基本要求是源表和目标表具有相同的模式(包括索引),驻留在相同的文件组中,目标为空。操作后,源staging表将为空。有关SWITCH

的详细信息,请参阅https://technet.microsoft.com/en-us/library/ms191160.aspx

以下是如何实施此技术的示例。

Try

    ESTP = "Start Bulk DBselection Update"

    Dim oMainQueryT = "Truncate Table DBSelectionsSTAGE"
    Using con As New SqlClient.SqlConnection(RacingConStr)
        Using cmd As New SqlClient.SqlCommand(oMainQueryT, con)
            con.Open()
            cmd.ExecuteNonQuery()
            con.Close()
        End Using
    End Using

    ESTP = "Step 1 Bulk DBselection Update"

    Using bulkCopy As SqlBulkCopy = New SqlBulkCopy(RacingConStr)
        bulkCopy.DestinationTableName = "DBSelectionsSTAGE"
        bulkCopy.WriteToServer(DBSelectionsDS.Tables("DBSelectionsDetails"))
        bulkCopy.Close()
    End Using

    ESTP = "Step 2 and 3 - replace DBselection with staged data"

    oMainQueryT = _
        "SET XACT_ABORT ON;" + _
        "BEGIN TRAN;" + _
        "TRUNCATE TABLE dbo.DBSelections;" + _
        "ALTER TABLE dbo.DBSelectionsSTAGE SWITCH TO dbo.DBSelections;" + _
        "COMMIT;"
    Using con As New SqlClient.SqlConnection(RacingConStr)
        Using cmd As New SqlClient.SqlCommand(oMainQueryT, con)
            con.Open()
            cmd.ExecuteNonQuery()
            con.Close()
        End Using
    End Using

    Data_Base.TextBox25.Text = "Replaced data - DONE "
    Data_Base.TextBox25.Refresh()

Catch ex As Exception

    ErrMess = "ERROR - occured at " & ESTP & " " & ex.ToString
    Call WriteError()
    Call ViewError()

End Try

答案 1 :(得分:0)

您的担忧完全有效。如果需要回滚信息,则必须使用日志事务语句而不是批量复制。

所以,我建议在SQL-SERVER中创建一个STORED PROCEDURE,并为控制事务添加INSERT和UPDATE。

此外,您可以在SP内部使用SET NOCOUNT ON(在第一行),您的性能可能会有一些惊喜。