SqlDataAdapter.Update() 的 200 万条记录非常慢
SqlDataAdapter.Update() of 2 million records is extremely slow
我有一个客户想要每天将他的子客户 pricetools(超过 2.000.000 条记录)导入 SQL 服务器数据库(是的......有超过 900.000 行每天都有变化)。
数据以 CSV 格式提供(不是 RFC-4180 标准 ç_ç,而是 nvm),可以是数据的插入、删除或更新。
我的问题是在数据库中插入数据需要超过 1 晚才能结束,我需要加快速度。
我现在正在做的是:
- 将 csv 文件转换为数据table(Tab1)(~3 分钟)
- Select 之前table(Tab0)里面的所有数据,并将它们与Tab1匹配(~15分钟,未更改的行被标记为未修改,因此它们在[=中被忽略12=],我检查了第一行的那个东西,似乎它有效,我使用
dataRowToProcess.AcceptChanges()
来实现它)。
启动以下命令以应用更改(900.000 个更改超过 5 小时):
cmdSQL = New SqlCommand(superQuery, cn)
Dim adapter As SqlDataAdapter = New SqlDataAdapter(cmdSQL)
adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey
Dim build As SqlCommandBuilder = New SqlCommandBuilder(adapter)
build.SetAllValues = False
adapter.Update(dataTableCustomersDetail) 'Insert/Update records
如果我有很多插入过程,它比相同数量的更新慢。
我究竟做错了什么?我是否遗漏了一些 SqlDataAdapter
选项?
谢谢
感谢@matsnow,我想出了一个使用 SqlBulkCopy 的解决方案。考虑到 table 的一半每次都在变化,那是一个静态的 anag,我决定 Delete/Insert 的数据是最快的跟踪方式(现在需要 5-6 分钟而不是 10 分钟)。
代码:
'Delete all table content
Dim cmd As SqlCommand = New SqlCommand("TRUNCATE TABLE " + tableName, cn)
cmd.ExecuteNonQuery()
'Insert all records
Using sbc As SqlBulkCopy = New SqlBulkCopy(cn)
sbc.DestinationTableName = tableName
sbc.BulkCopyTimeout = 1000
For Each column As DataColumn In dataTableCustomersDetail.Columns
sbc.ColumnMappings.Add(column.ToString(), column.ToString())
Next
sbc.WriteToServer(dataTableCustomersDetail)
End Using
使用 Connection.BeginTransaction() 加速 DataAdapter 更新。
cn.Open() 'open connection
Dim myTrans As SQLTransaction
myTrans = cn.BeginTransaction()
'Associate the transaction with the select command object of the DataAdapter
adapter.SelectCommand.Transaction = myTrans
adapter.Update(dataTableCustomersDetail) 'do the update as before
Try
myTrans.Commit()
Catch ex As Exception
myTrans.Rollback()
End Try
cn.Close()
对于 8000 行,这会将更新时间从 5 分钟以上更改为 2 秒
我有一个客户想要每天将他的子客户 pricetools(超过 2.000.000 条记录)导入 SQL 服务器数据库(是的......有超过 900.000 行每天都有变化)。
数据以 CSV 格式提供(不是 RFC-4180 标准 ç_ç,而是 nvm),可以是数据的插入、删除或更新。
我的问题是在数据库中插入数据需要超过 1 晚才能结束,我需要加快速度。
我现在正在做的是:
- 将 csv 文件转换为数据table(Tab1)(~3 分钟)
- Select 之前table(Tab0)里面的所有数据,并将它们与Tab1匹配(~15分钟,未更改的行被标记为未修改,因此它们在[=中被忽略12=],我检查了第一行的那个东西,似乎它有效,我使用
dataRowToProcess.AcceptChanges()
来实现它)。 启动以下命令以应用更改(900.000 个更改超过 5 小时):
cmdSQL = New SqlCommand(superQuery, cn) Dim adapter As SqlDataAdapter = New SqlDataAdapter(cmdSQL) adapter.MissingSchemaAction = MissingSchemaAction.AddWithKey Dim build As SqlCommandBuilder = New SqlCommandBuilder(adapter) build.SetAllValues = False adapter.Update(dataTableCustomersDetail) 'Insert/Update records
如果我有很多插入过程,它比相同数量的更新慢。
我究竟做错了什么?我是否遗漏了一些 SqlDataAdapter
选项?
谢谢
感谢@matsnow,我想出了一个使用 SqlBulkCopy 的解决方案。考虑到 table 的一半每次都在变化,那是一个静态的 anag,我决定 Delete/Insert 的数据是最快的跟踪方式(现在需要 5-6 分钟而不是 10 分钟)。
代码:
'Delete all table content
Dim cmd As SqlCommand = New SqlCommand("TRUNCATE TABLE " + tableName, cn)
cmd.ExecuteNonQuery()
'Insert all records
Using sbc As SqlBulkCopy = New SqlBulkCopy(cn)
sbc.DestinationTableName = tableName
sbc.BulkCopyTimeout = 1000
For Each column As DataColumn In dataTableCustomersDetail.Columns
sbc.ColumnMappings.Add(column.ToString(), column.ToString())
Next
sbc.WriteToServer(dataTableCustomersDetail)
End Using
使用 Connection.BeginTransaction() 加速 DataAdapter 更新。
cn.Open() 'open connection
Dim myTrans As SQLTransaction
myTrans = cn.BeginTransaction()
'Associate the transaction with the select command object of the DataAdapter
adapter.SelectCommand.Transaction = myTrans
adapter.Update(dataTableCustomersDetail) 'do the update as before
Try
myTrans.Commit()
Catch ex As Exception
myTrans.Rollback()
End Try
cn.Close()
对于 8000 行,这会将更新时间从 5 分钟以上更改为 2 秒