Linq 在大规模更新中的极慢
本文关键字:更新 大规模 Linq | 更新日期: 2023-09-27 18:36:56
我想对可能有一百万条记录进行更新。 我喜欢Linq,我在下面写这篇文章是为了尝试实现这一目标。我真的希望我写得非常错误。 运行了几个小时。 我用T-sql编写了它,它在几分钟内运行。 有没有更好的方法来使用 linq 执行此操作?
private static void UpdateZipCodes()
{
Console.WriteLine("Update Zip Codes Started");
DataDataContext _db = new DataDataContext();
var newBadZips = (from n in _db.NewCars
where n.loczip == null || n.loczip == ""
select n).ToList();
foreach (var bad in newBadZips)
{
string lZip = _db.Dealers.Where(x => x.DealerID == bad.DealerID).Select(x => x.Zipcode).SingleOrDefault();
bad.loczip = lZip;
_db.SubmitChanges();
}
Console.WriteLine("Update Zip Codes Finshed");
}
T-SQL 版本
UPDATE n
SET n.loczip = d.Zipcode
FROM NewCars AS n INNER JOIN
Dealers AS d ON n.DealerID = d.DealerID
where n.loczip is null or n.loczip = ''
我知道 linq 正在做更多的事情。 我想知道如何改进我的 linq 查询?
我并不是要比较它们,因为我知道T-sql是实现这一目标的正确方法。这主要是让我更好地使用 linq。 我相信我会想在某个时候以较小的规模做这样的事情,并希望在 linq 中正确完成。
您正在循环中查询数据库中的每个项目。 那是。。。坏。 它几乎总是错误的,而且几乎总是非常慢。
就像在 T-SQL 代码中所做的那样,在 LINQ 代码中使用联接在一个查询中获取所需的所有信息。
接下来,不要在每条记录后更新数据库;而是批量更新它们以减少网络流量。 您不能一次完成一百万次,但您可以每 100 或 1000 行或任何行提交一个批次(使用批次大小的不同值以查看哪种效果最好)。
此外,不要在包含一百万条记录的表上调用ToList
。 只需迭代查询,以便查询提供程序可以流式传输数据。
var newBadZips = (from car in _db.NewCars
where car.loczip == null || car.loczip == ""
join dealer in _db.Dealers
on car.DealerID equals dealer.DealerID
into dealers
select new{
car,
zip = dealers.Select(d => d.Zipcode)
.SingleOrDefault(),
});
int count = 0;
int batchSize = 1000;
foreach(var row in newBadZips)
{
row.car.loczip = row.zip;
if(++count % batchSize == 0)
_db.SubmitChanges();
}
在这种情况下,提高 LINQ
速度的绝对最佳方法是干脆不使用 LINQ。 直接运行 T-SQL 更新查询,或者将其放入进程中并调用该查询。
现在,当您显然喜欢 LINQ 时,我为什么要提倡这样做? 简单:LINQ 不会为用例提供任何好处,同时也不利于性能。 简而言之,这是这项工作的错误工具。 更好地使用事物的一部分是知道何时不适合使用它。