对调用实体框架的性能影响是什么在循环中等待(与同步)



我正在使用 EF6,并试图了解实际发生的情况以及对 EF 的异步调用在紧密循环中运行数千次的性能影响。 也就是说,这个循环:

using (var db = dbContext()) {
  vary query = db.MyTable.Where(...);
  cnt = 10000;
  for (var i = 0; i < cnt; i++)
    await query.ToListAsync();
}

我的想法是,在"using"语句结束时,所有 10000 个将按顺序处理。

将其与同步调用进行比较时(只是查询。ToList(( without await(,将发生完全相同的事情,并且性能应该是相同的。 我的结果显示跑步时间相差 1.5 倍。

问题:为什么时间不同,我上面的假设是否正确?

我的想法是,在"使用"语句的末尾,所有 10000 将按顺序处理。

不,每次等待时都会处理它们...ToListAsync(( 被调用。

问题:为什么时间不同,我的假设是上面的吗 正确?

因为在这种情况下使用异步会产生开销,因此会降低性能...ToListAsync((,因为您正在尝试最大化单线程吞吐量。

如果您进行一些添加,这将起作用,例如。但是您需要提前了解cnt

cosnt int cnt = 10000;
const int pageSize = 1000;
int pageNumber = 0;
var list = new List<MyTableRecord>();
using (var db = dbContext())
{
    for (var i = 0; i < cnt ; i++)
    {
        vary query = db.MyTable.Where(...).Skip(pageNumber++ * pageSize).Take(pageSize);
        list.AddRange(await query.ToArrayAsync());
    }
}

请注意,如果您尝试将 1000 * 10000 条记录加载到计算机中,list可能会炸毁计算机的内存(OutOfMemoryException(。

更现实的解决方案:

using (var db = dbContext())
{
    IEnumerable<MyTableRecord> rows;
    while ((rows = db.MyTable.Where(...).Skip(pageNumber++ * pageSize).Take(pageSize)).Any())
    {
        list.AddRange(rows);
    }
}

请注意,您可能会在同一连接内运行所有查询,这可能会导致其超时。

最新更新