在 C# / .NET 中执行批量更新的最快方法
Fastest way of performing Bulk Update in C# / .NET
我正在尝试找出通过 SQL 服务器中的迷你控制台应用程序执行批量更新的最佳方法。我已经编写了自己的批量更新方式,如下所示:
SqlCommand command = new SqlCommand();
command.Connection = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI");
command.Connection.Open();
for (int i = 0; i < items.Count; i = i + 1000)
{
var batchList = items.Skip(i).Take(1000).ToList();
for (int j = 0; j < batchList.Count(); j++)
{
command.CommandText += string.Format("update Items set QuantitySold=@s_id{0} where ItemID = @id{0};", j);
command.Parameters.AddWithValue("@s_id" + j, batchList[j].QuantitySold);
command.Parameters.AddWithValue("@id" + j, batchList[j].ItemID);
}
command.ExecuteNonQuery();
command = new SqlCommand();
command.Connection = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI");
command.Connection.Open();
}
command.Connection.Close();
但我对这个的性能不太满意,在我的数据库中更新 50000-100000 条记录时这样做会变得非常慢,即使它以 1000 条为一批....
有没有 library/solution 可以 "speed things up"?
有人可以帮我吗?
最快的方法是 bulk insert the data into temporary table using the built in SqlBulkCopy
Class, and then update using join to that table
或者您可以使用诸如 SqlBulkTools 之类的工具,它可以轻松完成此操作。
var bulk = new BulkOperations();
using (TransactionScope trans = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI")
{
bulk.Setup()
.ForCollection(items)
.WithTable("Items")
.AddColumn(x => x.QuantitySold)
.BulkUpdate()
.MatchTargetOn(x => x.ItemID)
.Commit(conn);
}
trans.Complete();
}
我不知道你的代码中有哪些项目,所以我不知道如何将这些项目放入 table 值参数中。如果您需要,我可以提供帮助,但我需要知道那个对象是什么。
无论如何,您可以在 sql 方面做这样的事情。然后,您只需将项目集合作为入站参数来执行此过程。
create type Items as TABLE
(
ItemID int
, Quantity int
)
GO
create procedure UpdateItemsBulk
(
@Items Items READONLY
) as
set nocount on;
Update i
set QuantitySold = items.Quantity
from items i
join @Items items on items.ItemID = i.ItemID
GO
您可以使用 Kros.KORM 进行批量操作。
using (var database = new Database("connectionstring ...", "ado client name ..."))
{
database
.Query<Movie>()
.AsDbSet()
.BulkUpdate(_data);
}
或者如果您不需要使用 ORM 并且有源数据 reader 可用,您可以使用 SqlServerBulkInsert
/ SqlServerBulkUpdate
或 MsAccessBulkInsert
/ MsAccessBulkUpdate
类 执行批量操作。
例如:
using (var bulkInsert = new SqlServerBulkInsert("connection string"))
{
bulkInsert.Insert(reader);
}
您可以看到与纯 ADO.NET 命令的比较 https://github.com/Kros-sk/Kros.Libs/wiki
我正在尝试找出通过 SQL 服务器中的迷你控制台应用程序执行批量更新的最佳方法。我已经编写了自己的批量更新方式,如下所示:
SqlCommand command = new SqlCommand();
command.Connection = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI");
command.Connection.Open();
for (int i = 0; i < items.Count; i = i + 1000)
{
var batchList = items.Skip(i).Take(1000).ToList();
for (int j = 0; j < batchList.Count(); j++)
{
command.CommandText += string.Format("update Items set QuantitySold=@s_id{0} where ItemID = @id{0};", j);
command.Parameters.AddWithValue("@s_id" + j, batchList[j].QuantitySold);
command.Parameters.AddWithValue("@id" + j, batchList[j].ItemID);
}
command.ExecuteNonQuery();
command = new SqlCommand();
command.Connection = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI");
command.Connection.Open();
}
command.Connection.Close();
但我对这个的性能不太满意,在我的数据库中更新 50000-100000 条记录时这样做会变得非常慢,即使它以 1000 条为一批....
有没有 library/solution 可以 "speed things up"?
有人可以帮我吗?
最快的方法是 bulk insert the data into temporary table using the built in SqlBulkCopy
Class, and then update using join to that table
或者您可以使用诸如 SqlBulkTools 之类的工具,它可以轻松完成此操作。
var bulk = new BulkOperations();
using (TransactionScope trans = new TransactionScope())
{
using (SqlConnection conn = new SqlConnection("Data Source=.;Initial Catalog=mydb;Integrated Security=SSPI")
{
bulk.Setup()
.ForCollection(items)
.WithTable("Items")
.AddColumn(x => x.QuantitySold)
.BulkUpdate()
.MatchTargetOn(x => x.ItemID)
.Commit(conn);
}
trans.Complete();
}
我不知道你的代码中有哪些项目,所以我不知道如何将这些项目放入 table 值参数中。如果您需要,我可以提供帮助,但我需要知道那个对象是什么。
无论如何,您可以在 sql 方面做这样的事情。然后,您只需将项目集合作为入站参数来执行此过程。
create type Items as TABLE
(
ItemID int
, Quantity int
)
GO
create procedure UpdateItemsBulk
(
@Items Items READONLY
) as
set nocount on;
Update i
set QuantitySold = items.Quantity
from items i
join @Items items on items.ItemID = i.ItemID
GO
您可以使用 Kros.KORM 进行批量操作。
using (var database = new Database("connectionstring ...", "ado client name ..."))
{
database
.Query<Movie>()
.AsDbSet()
.BulkUpdate(_data);
}
或者如果您不需要使用 ORM 并且有源数据 reader 可用,您可以使用 SqlServerBulkInsert
/ SqlServerBulkUpdate
或 MsAccessBulkInsert
/ MsAccessBulkUpdate
类 执行批量操作。
例如:
using (var bulkInsert = new SqlServerBulkInsert("connection string"))
{
bulkInsert.Insert(reader);
}
您可以看到与纯 ADO.NET 命令的比较 https://github.com/Kros-sk/Kros.Libs/wiki