在关闭连接之前查询完成后,实体框架将挂起

时间:2018-09-07 21:36:49

标签: c# sql-server entity-framework logging entity-framework-6

我正在尝试提高相对复杂的实体框架查询的性能。使用DbContext.Database.Log操作,在执行感兴趣的主要查询时检查了输出,发现有些奇怪的地方。根据日志,查询本身仅花费约10,000毫秒,但是查询“完成”与连接关闭之间相隔一分钟以上。我不知道这次发生了什么,因为日志显示为空行。输出如下:

  

2018-09-07 14:10:3​​4,641 [1] INFO EntityDataRepository [jobInstanceID:0]--在2018年9月7日2:10:34 PM -07:00执行

     

2018-09-07 14:10:46,421 [1] INFO EntityDataRepository [jobInstanceID:0]--在11776毫秒内完成,结果:SqlDataReader

     

2018-09-07 14:10:46,458 [1] INFO EntityDataRepository [jobInstanceID:0]-

     

2018-09-07 14:11:48,667 [1] INFO EntityDataRepository [jobInstanceID:0]-在9/7/2018 2:11:48 PM -07:00关闭连接

有人可以教育我这里发生了什么吗?请参见下面的代码的简化/通用版本:

(from child in entities.SelectMany(e => e.children.Where(childFilter))
join read in childReads on child.ID equals read.childID
join readType in readTypes on read.readTypeID equals readType.ID
where readFilter
select new {child, read, readType}).ToList()

1 个答案:

答案 0 :(得分:0)

  

2018-09-07 14:10:46,421 1信息EntityDataRepository [jobInstanceID:0]--在11776毫秒内完成,结果:SqlDataReader

这意味着SqlCommand.ExecuteReader()已完成,并且服务器开始向客户返回行。此时,SQL Server中的查询仍在执行。它可能已假脱机处理了所有查询结果,或者可能刚刚使用流式查询计划找到并返回了前几个匹配的行。因此,要完成您的IQueryable<T>.ToList(),查询需要在服务器上完成执行,结果行必须传输到客户端,EF必须读取行并将它们具体化为类型{{1 }}。

可以使用Visual Studio Profiler,性能计数器或System.Diagnostics.Process分析客户端的工作。

如果在SQL 2016+中使用query execution stats,SQL Server将跟踪Query Store,以查询计划缓存中的查询以及所有查询。这些统计信息将向您显示查询经过的时间,其中包括等待客户端读取(和处理)行以及所有其他等待的时间,以及“工作时间”,即查询使用的CPU时间。 SQL 2017和Azure SQL数据库中的查询存储还跟踪每个查询的等待状态,因此您可以区分等待客户端(T)和其他等待,例如数据文件读取(ASYNC_NETWORK_IO),锁定等待({PAGEIOLATCH)等