SQL 和 VB.net winform 的批量更新概念
Posted
技术标签:
【中文标题】SQL 和 VB.net winform 的批量更新概念【英文标题】:Bulk Updates Concept for SQL and VB.net winform 【发布时间】:2015-05-05 00:55:27 【问题描述】:对于 SQL Server 2008+ 中大型表的批量更新,我将不胜感激。
目前我有一个包含 10,000 行和 160 列的表。此表会非常频繁地更新,每行有 1 到 100+ 列更改,具体取决于流程。使用DataAdapter
使用“标准新手”表更新非常缓慢且不合适。
任务是找到更快的方法。我已经尝试使用批量大小微调DataAdapter.Update
,不管更繁重的更新需要 10-15 秒。同时SqlBulkCopy
在(球场)1-3秒内输入整个表。当更新过程在一个过程中发生 30-50 次时,10s-15s 加起来!
作为互联网自我思考,我的经验存在差距,但是我可以想到有两种可能性,它们可能会更好地完成更新任务。
从数据库中转储表格内容并使用SqlBulkcopy
重新填充表格。
使用存储过程和通过合并 SQL 语句传递给它的表。
主要问题是数据安全,尽管这是一个本地单用户应用程序,但需要一种方法来处理错误回滚。据我了解,转储和替换会更简单,但可能更容易丢失数据?存储过程的设置范围要大得多,因为更新语句必须单独键入所有更新列并为更改进行维护。除非有一个“更新 *”声明:)。
为了保持简短,我只想将其保持在概念级别,但会感谢任何不同的想法或链接和建议。
编辑更多信息: 该表只有一个索引,即 ID 列。它是将传入(和更改)数据存储到简单数据表的简单过程。并且更新可以是 1 行到 1000 行之间的任何位置。该程序经常将信息存储到数据库中,并且可以是部分或几乎所有列。为每个更新构建一个存储过程是不可能的,因为我不知道哪些数据将被更新,你可以说所有的列都将被更新(除了 ID 列和一些“硬”数据列)它取决于更新输入是什么。因此,除非我每次都列出几乎所有列,否则没有对特定列的更新进行微调。在这种情况下,一个存储过程可以做到这一点。
我认为问题在于对数据库的“调用”次数是使用当前数据适配器方法进行的。
编辑: 3 关于一个暂存表,我将数据批量复制到其中,然后让存储过程进行更新。这不会减少 SQL 流量吗?我认为这是数据适配器更新的问题。
编辑:在此线程的答案中发布了概念 1 的尝试。
谢谢
【问题讨论】:
你能详细说明一下表格的结构和更新吗?表上有哪些索引(尤其是聚集索引)?这些更新的确切频率是多少,为什么? 【参考方案1】:删除表格并使用批量复制重新加载整个内容不是正确的方法。
我建议为每个更新表的进程创建一个存储过程。该过程应仅将需要为该特定进程更新的列作为输入,然后运行标准 SQL 更新命令来更新指定行上的这些列。如果可能,请尝试在用于查找需要更新的记录的列上建立索引。
或者,根据您使用的 .Net 框架版本,如果您不想维护完整的存储过程列表,您可以尝试使用实体框架。
【讨论】:
用于查找行的列已编入索引。不幸的是,更新可能包含 1 到 120 列的更新,所以我会在每个更新命令中命名几乎所有更新。【参考方案2】:我编写了以下模型来转储表中的所有行,将内存中的表批量复制到 sql 暂存表中,然后将数据移回原始表中。因此,通过更新该表中的数据。
耗时 1.1 到 1.3 秒
与更新所需的 10 到 15 秒相比,这无疑是一个非常有吸引力的时间。我已将临时表的截断代码放在顶部,以便数据库中始终存在一份信息副本。虽然原始表在该过程完成之前不会有更新的信息。
与这种方法相关的陷阱是什么?我能对他们做些什么?我必须说明该表不可能超过 10000 行,因此该过程将起作用。
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()
Catch ex As Exception
ErrMess = "ERROR - occured at " & ESTP & " " & ex.ToString
Call WriteError()
Call ViewError()
End Try
【讨论】:
以上是关于SQL 和 VB.net winform 的批量更新概念的主要内容,如果未能解决你的问题,请参考以下文章
VB.NET如何在winform中“刷新”数据DbContext