我有这个代码,可以查看所有联系人,并计算每封发送给他们的电子邮件,如果他们没有打开/点击最后的X金额,那么将其返回列表< / p>
目前代码需要大约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;
答案 0 :(得分:0)
删除.ToList()&并使用IQueryables。通过使用iqueryables,代码将执行一次并减少内存。 ToList()检索所有实体并将它们存储在您不想要的内存中。
答案 1 :(得分: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);
}
}
}
我没有时间来模拟数据库并对其进行测试。此外,这种方法在联系人和电子邮件之间执行联接,如果您每人有10万封电子邮件,这可能是一个非常糟糕的主意。您可以使用rank函数对其进行优化,但我要说如果性能仍然不好,您可以开始考虑进行数据库端优化,因为这个数据结构是 - 至少对我的非dba眼睛 - 不太适合这种查询。