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 中正确完成。

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 不会为用例提供任何好处,同时也不利于性能。 简而言之,这是这项工作的错误工具。 更好地使用事物的一部分是知道何时不适合使用它。