Linq2sql 更新一个巨大的表中的每一行
本文关键字:一行 一个 更新 Linq2sql 巨大 | 更新日期: 2023-09-27 18:32:28
我有一个巨大的表(超过80M行),我使用linq2sql从数据库创建了一个模型。我遍历表(所有 80M 行)并用几个值更新每一行。我已经做了最多的来优化linq2sql代码周围的代码,但看起来db.SaveChanges()
方法在第一次更新时挂起。
我的代码看起来像这样(我正在解释可读性):
using(MessageListCtx db = new MessageListCtx())
{
foreach(var message in db.MessageList.OrderByDescending(e => e.RecordId))
{
message.hashCode = Hasher.GenerateHash(message.name);
db.SubmitChanges();
}
}
我猜问题是当我调用db.SubmitChanges();
上下文中的所有对象都会迭代更改时,这对于超过 80M 的对象需要一段时间,但我不知道如何解决这个问题。
我正在考虑使用 for
循环对结果进行分页。像这样:db.MessageList.Skip(i).Take(1000)
.但我宁愿采用开箱即用的解决方案,如果存在的话。有人可以指出我正确的方向吗?
算了
Linq 2sql 不是为批处理操作而设计的。您确实需要将其移动到设定的操作级别才能获得一些性能。
无论您做什么,您都会获得单独的更新语句,因此没有性能。
我想最快的方法是做这样的事情:
-
使用不带更改跟踪的 Foreach (
ObjectTrackingEnabled = false
) -
使用哈希构建内存中数据结构
-
使用 SQLBULKCOPY 将大容量插入到临时表中 (http://msdn.microsoft.com/en-US/library/System.data.sqlclient.sqlbulkcopy(v=vs.110).aspx)
-
使用"老式"更新语句更新大表
我想仍然使用这种方法,您可能希望一次将其缓冲为 100k 条记录
性能不佳来自被跟踪的大量对象。这需要删除。
请尝试以下操作:
- 使用一个上下文读取记录,无需状态跟踪
- 使用单独的写入上下文编写每个更新,并在调用 SaveChanges 之前将实体附加到该更新