[英]Entity Framework 6 - Query Performance
我使用 Entity Framework 6,我目前有一个包含许多包含的查询,它将大约 1200 个实体加载到 dbContext 中。 加载实体似乎很慢,因为查询需要将近一分钟的时间。 关于性能我能做些什么吗? 我有 4 个这样的查询需要 2.5 分钟才能加载? LazyLoading 已启用,但出于性能原因,我预加载了实体。
var report = DbContext.REPORT.Single(r => r.ID == reportId);
//this query takes a bit less than 1 minute
DbContext.REPORT_ELEMENT
.Include(re => re.LAYOUT)
.Include(re => re.PAGEMASTER)
.Include(re => re.REPORT_ELEMENTS)
.Include(re => re.SUBTITLE_CONTENT)
.Include(re => re.REPORT_ELEMENT_NOTE)
.Include("SUBTITLE_CONTENT.CONTENT_ELEMENT.LANGUAGE")
.Include("TITLE_CONTENT.CONTENT_ELEMENT.LANGUAGE")
.Where(re => re.REPORT_ID == report.ID)
.Load();
性能建议:
Include
,这会导致性能下降。考虑为此添加AsNoTracking
以提高查询性能。
参考: https ://learn.microsoft.com/en-us/ef/core/querying/tracking#no-tracking-queries
查询速度慢的主要原因是它输出了太多数据。 考虑添加: Take(200)
、 Skip()
以仅获取您需要的数据或当前页面需要的数据。 使用寻呼机生成报告。 这可能会有很大帮助。
Include
Include
生成 SQL 以选择多个表。 这大大增加了复杂性。 可以只选择自己需要的数据,避免写Include
函数。
例如,如果你只想得到盒子里的最后一个球,可以考虑这样写:
public class Box
{
public int Id { get; set; }
public IEnumerable<Ball> Balls { get; set; }
}
public class Ball
{
public int Id { get; set; }
public int BoxId { get; set; }
public Box Box { get; set; }
}
var boxes = await Boxes
// DO NOT Call Include(t => t.Balls) here!
.Where(somecondition)
.Select(t => new Box(){
Id = t.Id,
Balls = t.Balls.OrderByDescending(x => x.CreationTime)
.Take(1) // Only get what you need
})
.ToListAsync()
此外,当我们使用 Select 时,我们可以删除.Include
因为它在这里不会有任何效果。
除了 Anduin 的建议之外,我还想添加在几个不同的查询中拆分Includes()
的建议。 EF 将能够跟踪同一DBContext
中实体之间的引用。 作为一般经验法则 - 不要在同一个查询中使用三个以上的Includes()
。 还要确保您在数据库中为每个生成的 JOIN 都有一个索引。
为此,您必须将实体中的 FK 字段另外公开给导航属性。
您的初始查询将变成这样:
DbContext.LAYOUT
.Where(re => re.LAYOUT_ID == report.LAYOUT_FK)
.Load();
DbContext.PAGEMASTER
.Where(re => re.PAGEMASTERT_ID == report.PAGEMASTER_FK)
.Load();
免责声明:我是Entity Framework Plus项目的所有者
Query IncludeOptimized 功能允许使用 include 进行过滤,同时优化查询性能。
它通常会提高性能(将查询拆分为更小的查询)
DbContext.REPORT_ELEMENT
.IncludeOptimized(re => re.LAYOUT)
.IncludeOptimized(re => re.PAGEMASTER)
.IncludeOptimized(re => re.REPORT_ELEMENTS)
.IncludeOptimized(re => re.SUBTITLE_CONTENT)
.IncludeOptimized(re => re.REPORT_ELEMENT_NOTE)
.IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT)) // SelectMany?
.IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT).Select(ce => ce.LANGUAGE)) // SelectMany?
.IncludeOptimized(re => re.TITLE_CONTENT)
.IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT)) // SelectMany?
.IncludeOptimized(re => re.SUBTITLE_CONTENT.Select(sc => sc.CONTENT_ELEMENT).Select(ce => ce.LANGUAGE)) // SelectMany?
.Where(re => re.REPORT_ID == report.ID)
.Load();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.