我在使用EF6时遇到了一个非常奇怪的错误。我在第一次传球时上传了大约38K的记录。然后在我的第二轮,我用条件linq语句查询表。这行代码大约需要4分钟才能运行。这是我的实体。
[Table("RAW_ADWORDS")]
public class AdWord
{
[Key]
public int ID { get; set; }
public bool Processed { get; set; }
public string Client { get; set; }
public long ClientID { get; set; }
public bool Active { get; set; }
public bool ProcessedAllFile { get; set; }
public DateTime LastTimeRun{ get; set; }
public DateTime? LastDateTimeProcessed { get; set; }
public virtual List<AdWordCampaign> Campaigns { get; set; }
}
[Table("foobar")]
public class AdWordCampaign
{
[Key]
public int ID { get; set; }
public string Campaign { get; set; }
public long CampaignID { get; set; }
public string Day { get; set; }
public long Clicks { get; set; }
public string CampaignStatus { get; set; }
public long Cost { get; set; }
public long Impressions { get; set; }
public double CTR { get; set; }
public long AvgCPC { get; set; }
public double AvgPosition { get; set; }
public DateTime DownloadDate { get; set; }
}
}
首先我运行这个:
AdWord objAdWord = adwordsContext.AdWords.Where(c => c.ClientID == iCampaignID).FirstOrDefault();
然后
AdWordCampaign objAdWordCampaign = objAdWord.Campaigns.Where(c => c.CampaignID == iElementCampaignID && c.Day == sElementDate).FirstOrDefault();
上面的行似乎在进行查询之前首先加载所有记录。如果我在查询中添加Take(5),它仍然需要4分钟。
答案 0 :(得分:1)
我希望这些信息有用。
尝试将索引添加到LINQ中WHERE包含的表的字段中。
您始终可以创建额外的视图并将其添加到EF模型中并对其执行LINQ。它也会缩短时间。
如果您希望1条记录始终尝试使用SingleOrDefault
答案 1 :(得分:0)
尝试:
objAdWord.Campaigns.FirstOrDefault(c => c.CampaignID == iElementCampaignID && c.Day == sElementDate)
.Where
是一个O(n)操作,我不确定Where
然后FirstOrDefault
子句是否会被优化但是如果不是你就浪费了很多时间使用Where
。要进一步提高效果,请确保将CampaignID
编入索引
答案 2 :(得分:0)
您需要观看生成的查询&amp;在服务器上执行并确保它们已经过优化。
如果您使用的是MS SQL Server,则需要运行SQL Server Profiler工具。在调用执行查询的方法之前,在代码中放置断点。清除探查器的显示,然后执行该方法。您可以从那里捕获SQL,然后将其放入SSMS并查看计划。如果查询不使用索引,则需要添加下次运行时将使用的索引。
我只使用过Database First,而不是Code First,所以我不知道如何告诉Entity Framework在Code First场景中创建索引,抱歉。但您仍需要优化所有查询。
答案 3 :(得分:0)
我之前在使用EF时通过“主要对象”引用链接对象时看到过这种情况 - 即当你做
时 AdWordCampaign objAdWordCampaign = objAdWord.Campaigns.Where(...).FirstOrDefault();
。
很简单,它一个接一个地迭代所有记录 - 因此慢查询。
如果您更改为以下内容,则应立即得到响应:
AdWord objAdWord = adwordsContext.AdWords.Where(c => c.ClientID == iCampaignID).FirstOrDefault();
AdWordCampaign objAdWordCampaign = <adwordsContext>.Campaigns
.Where(c => <c.AdwordId = objAdWord.Id> && c.CampaignID == iElementCampaignID && c.Day == sElementDate)
.FirstOrDefault();
我对角括号进行了更改,我不确定AdWordCampaign中的哪个属性通过一瞥模型标记了AdWord的ID,但我确信你明白了 - 直接去使用AdWord作为附加Where
子句,而不是通过AdWord的广告系列集合,通过上下文对Capaigns表进行处理。