使用 Entity Framework 检索许多嵌套实体时性能缓慢
Slow performance retrieving many nested entities using Entity Framework
我正在使用 Entity Framework 6 来检索一个实体,该实体具有多个导航属性到深层嵌套实体。我面临着巨大的性能影响,这已通过记录 Entity Framework 的请求得到强调。我在最深的实体(地理坐标)中有数百条记录,检索会话实体最多需要 8 秒(我希望少于 1 秒)。
这是日志的 Gist 示例:
https://gist.github.com/bbougot/837419c682a75d4741a5
这是我的代码:
using (var context = new ModelContainer())
{
context.Database.Log = msg => Trace.WriteLine(msg);
var session= await
context.SessionSet.FirstOrDefaultAsync(a => a.Identifier == sessionIdentifier);
var result = await Json(session).ExecuteAsync(new CancellationToken());
return ResponseMessage(result);
}
我正在检索模型的红色实体(注意路线和地理位置之间唯一的一对多关系):
(Link 到大尺寸图片: http://i.imgur.com/adRw6br.jpg?1)
我试过禁用延迟加载并使用 Include 来预先加载我的实体,但更糟糕的是,我已经达到 SQL 服务器超时。
实体加载时间过长的原因是您遇到了经典的 select N+1 问题。
您似乎已经知道 Entity Framework 默认情况下 lazy-loads 所有导航属性都通过在它们周围创建动态代理对象来实现。如果它检测到代理被访问(即您跟随导航 属性),那么它会向数据库发出查询以实际启动并获取数据。这对性能有影响的原因是每个执行的数据库查询都有一定的开销(例如数据库服务器的延迟),因此最好的选择是执行一个查询,带回所有一次性获取您需要的数据,而不是针对每个单独的实体单独查询。
当谈到集合属性(例如您的 Route -> Geoposition
关系)时,情况会变得更糟,因为 Entity Framework 将为 each[= 生成一个单独的 select 23=] 集合中的项目。这就是您在日志中看到数百个查询的原因。
I've tried disabling lazy loading and use Include to eager load my
entities but it's even worse, I've reached the SQL Server timeout.
使用 Include
方法是将 eagerly-load 导航 属性 作为初始查询的一部分的正确方法。如果在 Include
相关的导航属性之后您仍然发现您的查询执行时间太长,您应该查看查询的执行计划以了解性能问题所在。 Post 如果您需要帮助分析它,另一个问题。
我正在使用 Entity Framework 6 来检索一个实体,该实体具有多个导航属性到深层嵌套实体。我面临着巨大的性能影响,这已通过记录 Entity Framework 的请求得到强调。我在最深的实体(地理坐标)中有数百条记录,检索会话实体最多需要 8 秒(我希望少于 1 秒)。
这是日志的 Gist 示例: https://gist.github.com/bbougot/837419c682a75d4741a5
这是我的代码:
using (var context = new ModelContainer())
{
context.Database.Log = msg => Trace.WriteLine(msg);
var session= await
context.SessionSet.FirstOrDefaultAsync(a => a.Identifier == sessionIdentifier);
var result = await Json(session).ExecuteAsync(new CancellationToken());
return ResponseMessage(result);
}
我正在检索模型的红色实体(注意路线和地理位置之间唯一的一对多关系):
(Link 到大尺寸图片: http://i.imgur.com/adRw6br.jpg?1)
我试过禁用延迟加载并使用 Include 来预先加载我的实体,但更糟糕的是,我已经达到 SQL 服务器超时。
实体加载时间过长的原因是您遇到了经典的 select N+1 问题。
您似乎已经知道 Entity Framework 默认情况下 lazy-loads 所有导航属性都通过在它们周围创建动态代理对象来实现。如果它检测到代理被访问(即您跟随导航 属性),那么它会向数据库发出查询以实际启动并获取数据。这对性能有影响的原因是每个执行的数据库查询都有一定的开销(例如数据库服务器的延迟),因此最好的选择是执行一个查询,带回所有一次性获取您需要的数据,而不是针对每个单独的实体单独查询。
当谈到集合属性(例如您的 Route -> Geoposition
关系)时,情况会变得更糟,因为 Entity Framework 将为 each[= 生成一个单独的 select 23=] 集合中的项目。这就是您在日志中看到数百个查询的原因。
I've tried disabling lazy loading and use Include to eager load my entities but it's even worse, I've reached the SQL Server timeout.
使用 Include
方法是将 eagerly-load 导航 属性 作为初始查询的一部分的正确方法。如果在 Include
相关的导航属性之后您仍然发现您的查询执行时间太长,您应该查看查询的执行计划以了解性能问题所在。 Post 如果您需要帮助分析它,另一个问题。