当前位置: 首页 > 面试题库 >

为什么由Entity Framework生成的查询花费的时间是直接运行同一查询的时间的两倍?

晏和风
2023-03-14
问题内容

我有一个简单的EF实现,其中检索了约2万条记录,并包括两个子实体:

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连接字符串进行了更改以优化查询?

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

谢谢!


问题答案:

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

很有可能只是因为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);
            }
        }
    }
}

在事件探查器中显示为持续时间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被延迟在客户端(具有waittypeASYNC_NETWORK_IO)之前等待,然后继续执行。



 类似资料:
  • 我正在尝试执行以下操作:假设我有以下SELECT查询(请原谅德文列名): 这个查询大约需要4秒(数据库总共有大约100万条记录),返回大约400条记录。但是,当我想用以下语句更新这些相同的记录时 查询总是在取“永远”后超时。是我做错了什么,还是这种行为是意料之中的?

  • 问题内容: SQL: 用户索引: 个人资料索引 解释 : 上面的查询大约需要0.1221 我怎样才能使其运行更快? 问题答案: 我删除了此查询,因此搜索完成后不会显示总结果数。 似乎是临时解决方案,甚至是永久解决方案。

  • 问题内容: 我正在尝试测试从Excel数据连接运行的查询的三种变体。 我有三个单独的数据连接和三个单独的选项卡,它们分别从每个连接获取数据。 每个查询的连接字符串相同,只有命令文本(Oracle SQL)不同。 Excel中是否可以查看每个查询的执行时间? 我专门使用版本 问题答案: 可能是这样的事情(假设所有连接都将其结果放置在工作表中,而不是在数据透视表中): 要运行此命令: +转到VBA编辑

  • 问题内容: 说我长时间运行更新查询 some_table中的modification_time的值是什么?它们是相同还是不同(例如,执行查询花了2天的时间)。 如果它们不同,如​​何编写此查询以使它们都相同? 问题答案: 它们都是一样的,因为NOW()在查询开始时被锁定了。 答案太短了吗? 好的,更多信息有关NOW()的MySQL参考 NOW()返回一个 恒定时间 ,该时间指示该语句 开始执行的时

  • 时间比较 使用where方法 where方法支持时间比较,例如: // 大于某个时间 where('create_time', '> time', '2016-1-1'); // 小于某个时间 where('create_time', '<= time', '2016-1-1'); // 时间区间查询 where('create_time', 'between time', ['2015-1-1'

  • 问题内容: 然而,从上述线程中摘录的一个重要观点是: Querydsl和jOOQ似乎是最流行和最成熟的选择,但是需要注意的一件事: 两者都依赖于代码生成的概念, 即为数据库表和字段生成元类。这有助于建立一个漂亮,干净的DSL,但是 在尝试为仅在运行时才知道的数据库创建查询时会遇到问题 。 除了仅使用纯JDBC +字符串串联外,还有什么方法可以在运行时创建查询吗? 我正在寻找的是一个Web应用程序,