Linq对于大规模更新极度缓慢

时间:2013-10-24 20:02:41

标签: c# sql linq tsql

我想对可能的一百万条记录进行更新。我喜欢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中正确地做到这一点。

2 个答案:

答案 0 :(得分:6)

您正在查询数据库中的每个项目。那很糟。这几乎总是错的,而且几乎总是很慢。

就像在T-SQL代码中所做的那样,在LINQ代码中使用Join来获取一个查询中所需的所有信息。

接下来,不要在每条记录后更新数据库;而是批量更新它们以减少网络流量。您将无法一次性完成一百万次,但您可以每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();
}

答案 1 :(得分:4)

在这种情况下提高LINQ速度的绝对最佳方法是不使用LINQ。可以直接运行T-SQL更新查询,也可以将其放入proc中并调用它。

现在,当你明显喜欢LINQ时,为什么我会提倡这个呢?简单:LINQ不会为用例提供任何好处,同时也会对性能产生不利影响。简而言之,这是这项工作的错误工具。更好地使用一件事情的一部分就是知道什么时候使用它是不合适的。