EF SaveChangesAsync extremely slow
本文关键字:slow extremely SaveChangesAsync EF | 更新日期: 2023-09-27 18:31:37
>我有一个表,我想一次更新 100 行。我有一个用于查找特定行的 100 个 ID 的列表。找到后,我为每行更新一列 (SyncOk)。
问题是更新 100 行大约需要 23 到 30 秒。
dbContext.Configuration.ValidateOnSaveEnabled = false;
var count = ids.Count;
for (var i = 0; i < count; i++)
{
var id = ids[i];
var record = await dbContext.History
.FirstOrDefaultAsync(r => r.Id == id);
record.SyncOk = syncOk;
}
await dbContext.SaveChangesAsync();
一些注意事项:
-
ids
是保存所有相关 ID 的IList<long>
。 -
syncOk
是一个布尔值。 - 我尝试将
AutoDetectChangesEnabled
属性设置为 false,然后在设置SyncOk
值后手动更新记录 - 不会加快速度。
为什么SaveChangesAsync()
这么慢 - 如何提高上述功能的速度?我担心该表在 23-30 秒内被锁定,并且会使其他服务(使用同一表)也无法更新它。
您正在对数据库执行总共ids.Count
个 SELECT 语句。如果您添加代码,则可以看到这一点:
dbContext.Database.Log += Console.WriteLine;
尝试通过一次获取所有数据来最大程度地减少对 SQL 实例的访问:
var records = await dbContext.History.Where(i => ids.Contains(i.Id)).ToListAsync();
然后,您应该执行所需的修改:
foreach(var record in records)
{
record.SyncOk = syncOk;
}
await dbContext.SaveChangesAsync();
您还可以使用 ForEachAsync
查询结果,就像上面的代码部分一样,也只查询一次:
await dbContext.History.Where(i => ids.Contains(i.Id))
.ForEachAsync(i => i.SyncOk = syncOk);
await dbContext.SaveChangesAsync();
恕我直言,下面执行Select * from History where Id in (YourList)
。
var listOfRecordsToBeUpdated = await dbContext.History
.Where(r => ids.Contains(r.Id)).ToListAsync();
//It will detect the changes each time when you update the entity
// Make sure you re-enable this after your bulk operation
DataContext.Configuration.AutoDetectChangesEnabled = false;
//Iterate through the records and assign your value
listOfRecordsToBeUpdated.Foreach(x=>x.SyncOk = syncOk);
DataContext.Configuration.AutoDetectChangesEnabled = true;
await conn.SaveChangesAsync();
通过禁用自动检测更改启用来提高性能
我尝试实现其他两个答案建议的更改 - 但具有相同的性能结果(即速度没有变化)。
我通过使用原始SQL命令大大提高了性能(并解决了我的问题):
var stringOfIds = string.Join(",", ids);
await dbContext.Database.ExecuteSqlCommandAsync(
$"UPDATE dbo.History SET SyncOk = 1 WHERE Id IN ({stringOfIds})");