4

我有一个简单的 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 Profiler 分析 EF 调用时,SQL 命令的持续时间约为 1.2 秒,即使在后续调用中也是如此。但是,如果我复制并粘贴 EF 生成的相同 SQL 并直接通过 SSMS 运行它,则持续时间是一半。

下面是 EF 调用(红色椭圆)和直接调用(绿色椭圆)的屏幕截图:

在此处输入图像描述

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

(我应该补充一点,查询本身已经完全优化了所有外键的索引。)

谢谢!

4

2 回答 2

3

两条迹线之间的读数相同,因此看起来与计划无关。

很可能只是因为实体框架在使用结果集时会做更多事情,因此需要更长的时间。

例如创建以下标量 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

第一行和最后一行之间的时间戳差异为 7 秒。前三行几乎立即返回,并且在 SQL Server 延迟等待客户端(使用 wait type ASYNC_NETWORK_IO)之后,然后继续执行。

于 2013-08-21T19:15:59.970 回答
1

众所周知,包含语句会导致速度变慢。我不确定为什么。尝试注释掉您的包含语句并改用延迟加载。这是另一篇具有相同结论的 SO 文章: 为什么 Entity Framework 需要 30 秒来加载记录,而生成的查询只需要 1/2 秒?

于 2013-08-21T17:48:29.483 回答