我一直在努力提高我的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()
答案 0 :(得分:2)
考虑使用事务TRUNCATE
和SWITCH
替换步骤2和3,以使用暂存数据替换DBSelection
表的内容。 SWITCH比复制单个行更有效,因为它只是一个元数据操作。
SWITCH
通常用于SQL Server企业版,用于将数据移动(不复制)到分区表或从分区表移出数据,但它也可以用于非分区表和较小版本。 SWITCH的基本要求是源表和目标表具有相同的模式(包括索引),驻留在相同的文件组中,目标为空。操作后,源staging表将为空。有关SWITCH
。
以下是如何实施此技术的示例。
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(在第一行),您的性能可能会有一些惊喜。