由后台作业处理的每个批处理后性能下降

时间:2017-05-18 13:18:16

标签: c# performance entity-framework batch-processing

我注意到我的后台工作在每批后表现更差。基本上,job需要巨大的csv文件,然后以250个记录的批量更新数据库中的相关记录。在每个批处理之后,我重新创建数据库上下文以保持ObjectContext整洁,但这并没有帮助,看起来每个批处理后一切都变得越来越慢。我的工作是:

  1. 从文件
  2. 中读取250条记录
  3. 创建DbContext
  4. 然后为每条记录
  5. 从DB获取相应的实体
  6. 更新属性(反射)
  7. 处理250条记录时 - SaveChanges
  8. 因此,当工作开始时,4分钟需要约170毫秒,而5分钟需要约6毫秒。

    50批次后,4分钟需要~430ms,5分钟需要 ~500ms

    有人可以解释一下这里发生了什么吗?

    更新 事实证明它并非熄火故障 - 所以我删除了所有对hangfire的引用。

    问题似乎在于DbContext,尽管我正在重新创建DbContext处理,但每次批处理后仍需要更长的时间。此外,我从5中错过了一件事。 - 每次都要花费更长时间来致电dbContext.Entry(entity).Property("Guid").IsModified = false

    //for each 250 items
    var dbContext = new MyDbContext();
    
    dbContext.Configuration.ValidateOnSaveEnabled = false;
    
    foreach (var item in items)
    {
        var entity = dbContext.MyItems
            .Include(x => x.SomeProp) // lots of these
            .FirstOrDefault(BuildFilterFrom(item)); //after each batch this taking longer (starting from 170ms and then after 50 batches it takes 430ms)
    
        //set entity propties from item
        //...
    
        dbContext.Entry(entity).Property("Guid").IsModified = false //after each batch this also taking longer (starting from 6ms and then after 50 batches it takes 500ms)
    }
    dbContext.SaveChanges();
    

2 个答案:

答案 0 :(得分:1)

从您的更新中,我认为您最好的选择是在更改时忽略Guid属性。您应该能够在您的属性集合中添加.Where()以使用该名称消除它们。这样就可以节省设置属性的微秒,也可以保存更改IsModified属性。

答案 1 :(得分:0)

从您发布的信息中提供任何信息都有点困难。无论如何,篝火工作都不会累,但取决于工作类型和重复,异常等,hangfire将数据序列化并保存在数据库并从DB中再次获取它。

您是否遵循此处所述的最佳做法http://docs.hangfire.io/en/latest/best-practices.html。您还可以使用日志记录来了解作业的哪个部分需要时间,利用跟踪日志级别来了解hangfire是否导致问题

http://docs.hangfire.io/en/latest/configuration/configuring-logging.html