对于SQL Server 2008 +中大型表的批量更新,我将不胜感激,并对其提出了一些想法,讨论和可行性。
目前我有一个包含10,000行和160列的表。此表经常更新,每行有1到100多列更改,具体取决于过程。使用DataAdapter
使用“标准新手”表更新非常缓慢且不合适。
任务是寻找更快的方法。我尝试使用批量大小微调DataAdapter.Update
,无论更重的更新需要10-15秒。同时SqlBulkCopy
导入整个桌子(球场)1-3秒。当更新过程在一个过程中发生30-50次时,10s-15s加起来!
互联网自我思考,我的经验有差距,但我可以想到有两种可能更好地完成更新任务。
转储数据库中的表格内容,并使用SqlBulkcopy
重新填充表格。
使用带有合并SQL语句传递给它的表的存储过程。
主要问题是数据安全,虽然这是本地单用户应用程序,但需要有一种方法来处理错误回滚。根据我的理解,转储和替换会更简单,但可能更容易丢失数据?存储过程的设置范围要大得多,因为更新语句必须单独键入所有更新列并保持更改。除非有一个'Update *'声明:)。
为了保持这种简短,我希望仅将其保持在概念层面,但会欣赏任何不同的想法或链接和建议。
编辑更多信息: 该表只有一个索引,即ID列。它是将传入(和更改)数据存储到简单数据表的简单过程。并且更新可以是1行到1000行之间的任何位置。程序经常将信息存储到数据库中,并且可以是一些或几乎所有列。为每次更新构建存储过程是不可能的,因为我不知道哪些数据会被更新,你可以说所有列都将被更新(除了ID列和一些“硬”数据列)它依赖于更新输入是什么。因此,除非我每次都列出几乎所有列,否则不会对特定列的更新进行微调。在这种情况下,一个存储过程就可以完成它。
我认为问题是使用当前数据适配器方法对数据库进行'调用'的次数。
编辑: 3关于临时表的问题,我将数据批量复制到存储过程然后执行更新。这不会减少SQL流量吗?我认为这是dataadapter更新的问题。
编辑:在回答此主题时发布了概念1的尝试。
谢谢
答案 0 :(得分:0)
删除表并使用批量复制重新加载整个内容不是正确的方法。
我建议为每个更新表的进程创建一个存储过程。该过程应仅将需要为该特定进程更新的列作为输入,然后运行标准SQL更新命令以更新指定行上的那些列。如果可能,尝试在用于查找需要更新的记录的列上建立索引。
或者,根据您使用的.Net框架版本,如果您不想维护整个存储过程列表,可以尝试使用Entity Framework。
答案 1 :(得分:0)
我编写了以下模型来转储表中的所有行,将内存中的表批量复制到sql staging表中,然后将数据移回原始表中。所以通过更新该表中的数据。
时间为1.1至1.3秒
与更新所需的10-15秒相比,肯定是非常有吸引力的时间。我已将登台表的truncete代码放在最上面,以便数据库中始终有一个信息副本。虽然原始表格没有更新的信息,但直到完成该过程。与这种方法有关的pitfals是什么?我能对他们做些什么?我必须声明该表不可能超过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