2015-08-03 99 views
-5

我有這段代碼看起來雖然是所有聯繫人,並且對發送給他們的每封電子郵件進行計數,如果他們沒有打開/點擊最後一個X數量,然後返回它們在列表中我該怎麼做才能提高此代碼的性能

目前代碼需要大約10分鐘才能運行,有什麼我可以做的改進呢?

我知道我可以限制返回的金額,但仍然很慢。

var contactList = 
     (from c in db.Contacts 
      where c.Accounts_CustomerID == Account.AccountID && !c.Deleted && !c.EmailOptOut 
      select c).ToList(); 

    foreach (var person in contactList) 
    { 
     var SentEmails = 
      (from c in db.Comms_Emails_EmailsSents where c.ContactID == person.ID select c).OrderBy(
       x => x.DateSent).Take(Last).ToList(); 

     if (SentEmails.Count == Last) 
     { 
      if (!Clicks) 
      { 
       if (SentEmails.Count(x => x.Opens == 0) == Last) 
       { 
        ReturnContacts.Add(person); 
       } 
      } 
      else 
      { 
       if (SentEmails.Count(x => x.Clicks == 0) == Last) 
       { 
        ReturnContacts.Add(person); 
       } 
      } 
     } 
    } 
    return ReturnContacts; 
+6

先讓一個性能分析器(例如dotTrace)來指導究竟什麼時候緩慢。 – HimBromBeere

+0

您需要加入查詢。 –

回答

0

刪除.ToList()並使用IQueryables。通過使用iqueryables,代碼將執行一次並減少內存。 ToList()檢索所有實體並將它們存儲在內存中,這是你不想要的。

0

在db上運行邏輯 - 使用連接等重寫查詢,以便返回已包含相關數據的結果集。

你現在正在做的是對每個初始查詢結果執行數據庫查詢。這可能意味着很多查詢。

如果您將其卸載到RDBMS中,您可以隨時嘗試並優化它(通過引入索引等)。

編輯:我改寫了在記事本中的代碼:

foreach(var record in (from c in db.Contacts 
join es in db.Comms_Emails_EmailsSents 
on c.Id equals es.ContactId 
where c.Accounts_CustomerID == Account.AccountID && !c.Deleted && !c.EmailOptOut 
orderby c.Id, es.DateSent descending 
select new {opens=es.Opens, clicks=es.Clicks, person=c}) 
.GroupBy(r=>r.person)){ 
    var mails = record.Take(Last).ToList(); 
    if(mails.Count == Last){ 
     if(!Clicks){ 
      if(mails.Count(x=>x.opens == 0) == Last){ 
       ReturnContacts.Add(record.Key); 
      } 
     } 
    }else 
      { 
       if (SentEmails.Count(x => x.Clicks == 0) == Last) 
       { 
        ReturnContacts.Add(record.Key); 
       } 
      } 

} 

我沒有在手的時間來模擬一個數據庫,並對其進行測試。此外,這種方法會在聯繫人和電子郵件之間進行聯接,如果您每個人有100k封電子郵件,這可能是一個非常糟糕的主意。你可以通過使用rank函數來優化它,但我會說如果性能仍然不好,你可以開始考慮做db邊優化,因爲這個數據結構是 - 至少對我的非dba眼睛 - 並不完美適合這種查詢。

+0

在sql中寫這個最好的方法是什麼?使用遊標? – Samw

+0

確實不使用遊標......如果可能;)我會查看代碼並嘗試更新我的答案。 – Gerino