2014-02-13 77 views
1

我注意到我的一個查詢與實體框架是如此之慢。我認爲那是我使用的問題,但我沒有得到「任何」速度差異。表我正在做這個查詢有大約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

回答

2

在你的代碼中,在每次迭代中調用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

1

請確保您還查詢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

嗯,我通常不關心被接受與否,但在這種情況下,我真的不能推薦你似乎選擇的方法。 –