我在使用通用方法进行数据聚合时遇到了实体框架的性能问题。当使用通用方法查询具有几十万行的表的(索引)Id 列的最大值时,性能下降很大。我正在使用代码生成的 int 键而不是 sql 标识,此代码用于获取下一个新 Id。
这是示例插图。MaxTyped
使用Max
on db.Posts
(即DbSet<Post>
),而MaxGeneric
使用泛型方法max
来做同样的事情。
static int MaxTyped()
{
using (var db = new BloggingContext())
{
return db.Posts.Max(p => p.PostId);
}
}
static int MaxGeneric()
{
using (var db = new BloggingContext())
{
return max(db.Posts, p => p.PostId);
}
}
static int max<T>(DbSet<T> set, Func<T, int> func) where T : class
{
// intellisense says its IEnumerable.Max
return set.Max(func);
}
在我的不太旧的家用桌面上,硬盘速度很快,MaxTyped
100k 行的运行时间为 0.5 秒,而MaxGeneric
大约 6.5 秒。这慢了一个数量级。
在我办公室的旧测试服务器上,我们有几秒钟的时间而不是近 10 分钟。
我发现的问题的唯一痕迹是两种情况下 Intellisense 对 Max 方法的输出的差异:在MaxTyped
它将方法标识为IQueryable.Max
时,在它使用的 max 中MaxGeneric
表示它IEnumerable.Max
,这可能意味着 EF 在所有加载的实体上执行 Max 和不在数据库中。我尝试转换set
为IQueryable<T>
,但没有任何改变。为什么会有这样的差异?如何解决?