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