我从未听说过,但人们将应用程序中的问题称为“N+1 问题”。他们正在做一个基于 Linq to SQL 的项目,有人发现了一个性能问题。我不太明白 - 但希望有人能引导我。
似乎他们正在尝试获取 obects 列表,然后在此之后的 Foreach 导致过多的数据库命中:
据我了解,源代码的第二部分仅在 forwach 中加载。
因此,加载的项目列表:
var program = programRepository.SingleOrDefault(r => r.ProgramDetailId == programDetailId);
Run Code Online (Sandbox Code Playgroud)
然后,我们使用这个列表:
foreach (var phase in program.Program_Phases)
{
phase.Program_Stages.AddRange(stages.Where(s => s.PhaseId == phase.PhaseId));
phase.Program_Stages.ForEach(s =>
{
s.Program_Modules.AddRange(modules.Where(m => m.StageId == s.StageId));
});
phase.Program_Modules.AddRange(modules.Where(m => m.PhaseId == phase.PhaseId));
}
Run Code Online (Sandbox Code Playgroud)
似乎确定的问题是,他们希望“程序”包含它的孩子。但是当我们在查询中引用孩子时,它会重新加载程序:
program.Program_Phases
Run Code Online (Sandbox Code Playgroud)
他们期望程序完全加载并在内存中,并且分析器似乎表明该程序表,所有连接都在每个“foreach”上被调用。
这有意义吗?
(编辑:我找到了这个链接: linq to sql 会自动延迟加载关联实体吗? 这可能会回答我的问题,但是 .. 他们正在使用更好的 (where person in...) 符号,而不是这个奇怪的 (x => x....)所以如果这个链接是答案——也就是说,我们需要“加入”查询——可以做到吗?)
在 ORM 术语中,“N+1 选择问题”通常发生在具有嵌套集合属性的实体时。它是指使用延迟加载时将实体数据完全加载到内存中所需的查询数。通常,查询越多,从客户端到服务器的往返次数就越多,服务器处理查询所需的工作也就越多,这会对性能产生巨大影响。
有多种技术可以避免这个问题。我不熟悉 Linq to SQL,但 NHibernate 支持在某些情况下有帮助的急切获取。如果您不需要加载整个实体实例,那么您还可以考虑进行投影查询。另一种可能性是更改您的实体模型以避免嵌套集合。
| 归档时间: |
|
| 查看次数: |
954 次 |
| 最近记录: |