sql – 为什么Entity Framework生成的查询运行时间是同一个查询直接运行的两倍?

我有一个简单的EF实现,我在其中检索~20K记录并包含两个子实体:

using (InsightEntities context = new InsightEntities())
{
   return context.Accounts
   .Include(x => x.Division)
   .Include(x => x.Division.Company)
   .OrderBy(x => x.ID)
   .AsNoTracking()
   .ToList();
}

当我通过SQL事件探查器分析EF调用时,SQL命令的持续时间约为1.2秒,即使在后续调用中也是如此.但是,如果我复制并粘贴EF生成的相同SQL并直接通过SSMS运行它,则持续时间只有一半.

以下是EF电话(红色椭圆形)和直接电话(绿色椭圆形)的屏幕截图:

我知道EF做了很多工作,将数据映射到对象,解释关系等等,但为什么单独的查询需要的时间是同一个查询直接运行的两倍?是否有可能优化查询的默认EF连接字符串的更改?

(我应该补充说,查询本身已完全使用所有外键的索引进行优化.)

谢谢!

最佳答案
两条迹线之间的读取是相同的,因此它看起来与计划无关.

很可能只是因为Entity Framework在使用结果集时执行的操作更多,因此需要更长的时间.

例如,创建以下标量UDF

CREATE FUNCTION dbo.GetTime()
RETURNS CHAR(12)
AS
  BEGIN
      RETURN CONVERT(VARCHAR(12), GETDATE(), 114)
  END 

然后在Management Studio中运行

SELECT TOP (10) CAST(dbo.GetTime() AS CHAR(8000))
FROM   sys.all_objects 

几乎立即完成,但模拟一个做更多工作的客户

using (SqlConnection con = new SqlConnection(connectionString))
{
    con.Open();

    using (SqlCommand command = new SqlCommand(
        @"SELECT TOP (10)  CAST(dbo.GetTime() AS CHAR(8000))
          FROM sys.all_objects", con))
    {
        using (SqlDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                Console.WriteLine(reader.GetString(0).TrimEnd());
                System.Threading.Thread.Sleep(1000);
            }
        }
    }
}

在Profiler中显示持续时间为8秒.

上面显示的运行结果是

23:55:54:870
23:55:54:870
23:55:54:870
23:55:55:870
23:55:56:870
23:55:57:870
23:55:58:870
23:55:59:870
23:56:00:870
23:56:01:870

第1行和最后一行之间的时间戳差异为7秒.在继续执行之前,SQL Server在客户端上等待(等待类型为ASYNC_NETWORK_IO)后,几乎立即返回前三行.

转载注明原文:sql – 为什么Entity Framework生成的查询运行时间是同一个查询直接运行的两倍? - 代码日志