我有一个简单的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)之前等待,然后继续执行。
ASYNC_NETWORK_IO