始终如一地减慢EF查询速度

时间:2015-04-06 17:03:36

标签: c# mysql entity-framework

我有以下查找:

using (var ctx = new dbContext())
{
   if (page == 0) page = 1;
   //_query = "SELECT * FROM [Log] WHERE [ApplicationId] = {0} and  [LogTime] >= '{1}' ORDER BY [LogTime] DESC OFFSET (({2} - 1) * {3}) ROWS FETCH NEXT {3} ROWS ONLY"
   var logs = ctx.Logs.SqlQuery(string.Format(_query, id, time, 1, 20000)).ToList();

   //var logs = ctx.Logs.Where(x => x.ApplicationId == id && x.LogTime >= time).ToList();

   return logs;
}

给定正确的时间,此查询返回大约20000个条目。执行查询需要13-18秒,但在SQLMS中它立即完成。

表格如下:

Log
  LogId (PK,int, not null)
  ApplicationId (FK,int,not null)
  Type(nvarchar(50), not null)
  Code(nvarchar(50), null)
  Source(nvarchar(50), not null)
  Message(ntext, null)
  LogTime(datetime, not null)

我不指望这应该花那么长时间。 我有什么遗漏或者应该改变以改善我的表现吗?

2 个答案:

答案 0 :(得分:1)

20000个条目是在单个查询中返回的大量记录。在SQL Management Studio中运行它时,查询立即返回。在SQL Management Studio中运行它时没有额外的开销。它只是在屏幕上返回结果。

当您将其作为EF查询运行时,会有网络开销来获取结果。其中一个关键原因,它会减慢是因为它需要将获取的结果转换为Log类型的对象。这将占用您提到的大部分时间(13-18秒)。

总而言之,您的EF查询包含多个步骤。 1.查询数据库 2.将结果转换为对象(这需要20000条记录的时间)

答案 1 :(得分:1)

通过EF执行查询时,涉及以下几个步骤:

  1. 查询数据库
  2. 将响应转移到查询过程。
  3. 将返回的数据具体化为.NET对象。
  4. 将对象添加到更改跟踪器。
  5. 它很慢的原因可以是任何一个步骤。可以通过在AsNoTracking()来电之前插入ToList()来停用更改跟踪器。