EF6需要5分钟才能在少于40,000条记录上运行查询

时间:2014-04-10 20:15:56

标签: c# performance entity-framework entity-framework-6

我在使用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分钟。

4 个答案:

答案 0 :(得分:1)

我希望这些信息有用。

  1. 尝试将索引添加到LINQ中WHERE包含的表的字段中。

  2. 您始终可以创建额外的视图并将其添加到EF模型中并对其执行LINQ。它也会缩短时间。

  3. 如果您希望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表进行处理。