实体框架5查询运行缓慢

时间:2013-08-06 13:04:03

标签: performance linq-to-entities entity-framework-5

我在ASP MVC应用程序中针对EF5 DbContext模型的一些查询遇到了性能问题。

查询中有许多包含多个导航图层,例如:

Context.Cars
.Include(c=>c.Model.Maker)
.Include(c=>c.CarOwners.Select(co=>co.Owner))
.Include(c=>c.Navigation1)
.Include(c=>c.Navigation2)
.Include(c=>c.Navigation3)
.ToList();

第一次运行查询时,执行大约需要10秒钟,但是当我第二次刷新页面时,执行时需要的时间少于一秒。

我已经运行了Visual Studio的性能分析工具来查看问题所在,并且看起来GetExecutionPlan()方法在大多数时间都在消耗。

我想该计划正在缓存,因为第二次运行查询(在页面刷新时)查询执行得非常快(少于一秒)。

据我所知,checkp页面加载的性能有限,因为查询非常复杂(转储到DB的SQL代码长约4k行)。但问题是,如果我在一小时左右返回页面,查询再次变慢。似乎执行计划缓存以某种方式被清除?我已经检查了IIS设置,并且所有应用程序池回收设置都已关闭。

为了清楚起见,我不是在寻找优化查询的方法,我想知道为什么我的查询行为奇怪:首先加载缓慢,第二次加载快速并在一小时后再加载缓慢。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

(dotPeek救援。我在Codeplex的源代码中找不到该类,它可能已在v6中删除。)

EntityFramework.dll v5.0.0.0中有一个内部类System.Data.Common.QueryCache.QueryCacheManager,它实现了它所说的,但有点复杂。

以下是我非常肯定的事情:当计划添加到缓存时,会启动一个计时器(如果尚未运行)。定时器每隔60000毫秒(1分钟)触发一次高速缓存扫描,然后如果有超过800个高速缓存计划,则实际扫描高速缓存。自上次扫描后未重复使用的计划将从缓存中逐出。如果缓存中的计划少于800个,则跳过扫描并停止计时器。

以下是我不太确定的事情:我不太了解缓存扫描的一部分,但我认为它很聪明。看起来算法使得计划更难以保持在缓存中,通过逐次向每次扫描增加数量来向右移动其命中计数。在第一次和第二次扫描时,它会移动1,然后是2,然后是4,最多移动到16.我不确定这是什么原因,而且我很难确定计划需要多少次用于使其在缓存中停留超过5分钟。我很感激,如果有人能够提供更多关于1)它正在做什么的信息,以及2)这样做的理由是什么。

无论如何,这就是为什么你的计划不会被永远缓存的原因。