简体   繁体   English

使用实体框架检索许多嵌套实体的性能降低

[英]Slow performance retrieving many nested entities using Entity Framework

I'm using Entity Framework 6 to retrieve an entity which has several navigation properties to deep nested entities. 我正在使用Entity Framework 6检索具有多个导航属性的实体,这些导航属性可用于深层嵌套的实体。 I'm facing a huge performance impact which has been highlited by logging Entity Framework's requests. 我面临着巨大的性能影响,通过记录Entity Framework的请求可以提高性能。 I have hundred of records in my deepest entity (Geocoordinate) and retrieving a Session entity takes up to 8 seconds (I'd like less than 1 sec). 我最深的实体(Geocoordinate)中有数百条记录,而检索Session实体最多需要8秒(我希望少于1秒)。

Here's a Gist sample of the log: https://gist.github.com/bbougot/837419c682a75d4741a5 这是日志的Gist示例: https : //gist.github.com/bbougot/837419c682a75d4741a5

Here's my code: 这是我的代码:

        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);
        }

I'm retrieving the red entities of my model (notice the only one-to-many relation between Route and Geoposition): 我正在检索模型的红色实体(注意“路线”和“地理位置”之间唯一的一对多关系):

模式

(Link to large size image: http://i.imgur.com/adRw6br.jpg?1 ) (链接到大尺寸图片: http : //i.imgur.com/adRw6br.jpg?1

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来渴望加载我的实体,但更糟糕的是,我达到了SQL Server超时。

The reason that the entity is taking so long to load is that you're suffering from a classic select N+1 problem. 实体加载时间如此之久的原因是,您遇到了经典的select N + 1问题。

As you already seem to be aware Entity Framework by default lazy-loads all navigation properties by creating a dynamic proxy object around them. 正如您已经知道的那样,默认情况下,Entity Framework通过在它们周围创建动态代理对象来延迟加载所有导航属性。 If it detects that the proxy is accessed (ie you follow the navigation property) then it issues a query to the database to actually go off and fetch the data. 如果它检测到代理已被访问(即,您遵循导航属性),则它将向数据库发出查询以实际启动并获取数据。 The reason that this has a performance impact is that each database query that gets executed has a certain overhead associated with it (eg the latency to the database server), and therefore the best option is to execute a single query that brings back all of the data you need in one go rather than separate queries for each individual entity. 之所以会影响性能,是因为执行的每个数据库查询都有一定的关联开销(例如,数据库服务器的延迟),因此最好的选择是执行单个查询,以将所有只需一次即可获得所需的数据,而不是为每个单独的实体分别查询。

When it comes to collection properties (eg your Route -> Geoposition relation) then things get even worse because Entity Framework will generate a separate select for each item in the collection. 当涉及到集合属性(例如您的Route -> Geoposition关系)时,情况会变得更糟,因为Entity Framework将为集合中的每个项目生成一个单独的select。 This is why you're seeing so many hundreds of queries in your log. 这就是为什么您在日志中看到如此多的查询的原因。

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来渴望加载我的实体,但更糟糕的是,我达到了SQL Server超时。

Using the Include method is the correct approach to eagerly-load a navigation property as part of the initial query. 使用Include方法是在初始查询中急于加载导航属性的正确方法。 If after Include ing the relevant navigation properties you still find your query is taking too long to execute you should look at the execution plan of the query to see where the performance problem lies. 如果在Include相关的导航属性之后,您仍然发现查询执行所需的时间太长,则应查看查询的执行计划以了解性能问题所在。 Post another question if you need help analyzing it. 如果您需要帮助分析它,请发布另一个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM