缓慢的查询实体框架

问题描述:

我注意到我的一个查询与实体框架是如此之慢。我认为那是我使用的问题,但我没有得到“任何”速度差异。表我正在做这个查询有大约4K条目,所以我不明白为什么需要20秒来做到这一点。我正在使用mysql与最新的.net连接器缓慢的查询实体框架

var errorMessages = msgs.Where(m => m.Type == 1 && 
      (m.StatusCode == (int)ErrorCode.AbsentSubscriber || 
      m.StatusCode == (int)ErrorCode.AbsentSubscriber || 
      m.StatusCode == (int)ErrorCode.Deleted || 
      m.StatusCode == (int)ErrorCode.Error || 
      m.StatusCode == (int)ErrorCode.Expired || 
      m.StatusCode == (int)ErrorCode.InvalidDestination || 
      m.StatusCode == (int)ErrorCode.Rejected || 
      m.StatusCode == (int)ErrorCode.SubscriberError || 
      m.StatusCode == (int)ErrorCode.Undeliverable || 
      m.StatusCode == (int)ErrorCode.UnknownSubscriber)) 
      .GroupBy(m => m.StatusCode); 

foreach (var error in errorMessages) 
{ 
    var eSum = 
      db.ErrorSumMessages.SingleOrDefault(
       m => m.ErrorCode == error.Key 
       && m.MessagesId == oldHourlyMessage.MessagesId); 

    if (eSum != null) 
    { 
     //This gets called 
     eSum.Count += error.Sum(m => m.MessageCount); 
     db.Entry(eSum).Property(m => m.Count).IsModified = true; 
    } 
    else 
    { 
     db.ErrorSumMessages.Add(new ErrorSumMessage 
      { 
       Count = error.Sum(m => m.MessageCount), 
       ErrorCode = error.Key, 
       ErrorText = error.First().StatusText, 
       MessagesId = oldHourlyMessage.MessagesId 
      }); 
    } 
} 
+0

db.ErrorSumMessages是db实体吗? – alexmac

+0

您是否尝试了解代码以查看其速度缓慢?它是第一个查询还是使用果汁的循环? – Ohlin

在你的代码中,在每次迭代中调用db query - db.ErrorSumMessages.SingleOrDefault。如果errorMessages包含4K记录,则可以获得4K查询!

为了减少数据库查询numder,选择所需的(或全部)foreach语句之前db.ErrorSumMessages:

var localErrorSumMessages = db.ErrorSumMessages.ToList(); 
foreach (var error in errorMessages) 
{ 
    var eSum = localErrorSumMessages.SingleOrDefault(....); // selecting from collection in memory 
+0

我不同意你为什么? B'cos你知道'ErrorSumMessages'表中有多少条记录吗?可能是16K。那么会发生什么? – Sampath

+0

是的,这可能是问题,但执行大量的分歧,这是一个非常非常糟糕的做法。如果ErrorSumMessages包含16K,那么这个方法的所有逻辑都应该被重构,只使用一个单一的查询 – alexmac

+0

是的,检索一个大数据树可能比通过导线的4k小数据遍历请求快.Hmm..OP必须测试这个与他的分贝,然后他应该决定它+ 1 – Sampath

请确保您还查询ErrorSumMessages在主查询:

var errorMessages = msgs.Where(...) 
      .GroupBy(m => m.StatusCode) 
      .Select(g => new 
       { 
        StatusCode = g.Key, 
        eSum = db.ErrorSumMessages 
          .FirstOrDefault(
          m => m.ErrorCode == g.Key 
           && m.MessagesId == oldHourlyMessage.MessagesId), 
        Messages = g 
       }) 

foreach(var row in errorMessages) 
{ 
    var eSum = row.eSum; 
    var error = row.Messages; 
    // rest should work unaltered, except error.Key => row.StatusCode 
    ... 

} 

您必须使用FirstOrDefault,否则EF将抛出“方法'Single'和'SingleOrDefault'只能用作最终查询操作”。

+0

嗯,我通常不关心被接受与否,但在这种情况下,我真的不能推荐你似乎选择的方法。 –