我使用Entity Framework6,目前我有一个包含多个includes的查询,它将大约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();发布于 2020-01-21 17:24:07
性能建议:
Include%s,这会使性能变差。阻止跟踪
考虑添加AsNoTracking,这样可以更好地提高查询性能。
参考:https://docs.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()此外,当我们使用选择时,我们可以删除.Include,因为它在这里不会有任何影响。
发布于 2020-01-21 20:30:41
除了来自Anduin的建议之外,我还想添加一些建议,将Includes()拆分成几个不同的查询。EF将能够跟踪同一DBContext中的实体之间的引用。作为一般经验法则-在同一查询中使用的Includes()不能超过三个。另外,还要确保在数据库中为每个结果连接建立索引。
若要执行此操作,必须将实体中的FK字段另外公开给导航属性。
您的初始查询将如下所示:
DbContext.LAYOUT
.Where(re => re.LAYOUT_ID == report.LAYOUT_FK)
.Load();
DbContext.PAGEMASTER
.Where(re => re.PAGEMASTERT_ID == report.PAGEMASTER_FK)
.Load();发布于 2020-01-21 21:55:06
免责声明:我是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();文档:EF+ Query IncludeOptimized
https://stackoverflow.com/questions/59837585
复制相似问题