gpt4 book ai didi

c# - Entity Framework 包括性能

转载 作者:可可西里 更新时间:2023-11-01 08:26:16 26 4
gpt4 key购买 nike

我一直在关注 Entity Framework 的性能,尤其是 Includes 的使用以及生成和执行各种查询所花费的时间。

我将详细说明我所做的更改,但如果您认为这些假设有任何错误,请纠正我。

首先,我们在一个数据库中有大约 10,000 个项目(不多),并且数据库已显着规范化(这导致了大量的导航属性)。目前的做法是延迟加载所有内容,考虑到请求一个项目可以分流出数十个 DB 请求,性能非常差,尤其是对于较大的数据集。(这是一个继承项目,第一步是尝试在不进行重大重组的情况下提高性能)

因此,我的第一步是获取查询结果,然后仅将导航属性的 Includes 应用于这些结果。我知道这在技术上执行了 2 个查询,但如果我们存储了 10,000 个项目,但只想返回 10 个项目,那么只包含这 10 个项目的导航属性更有意义。

其次,在查询结果上使用了多个包含并且结果集大小非常大的情况下,它仍然存在性能不佳的问题。对于何时进行急切加载以及何时保留延迟加载,我一直很务实。我的下一个更改是批量加载查询包含,因此执行:

query.Include(q => q.MyInclude).Load();

这再次显着提高了性能,尽管多了几次 DB 调用(每批包含一次)它比大型查询更快,或者至少减少了 Entity Framework 尝试生成该大型查询的开销。

所以代码现在看起来像这样:

    var query = ctx.Filters.Where(x => x.SessionId == id)
.Join(ctx.Items, i => i.ItemId, fs => fs.Id, (f, fs) => fs);
query
.Include(x => x.ItemNav1)
.Include(x => x.ItemNav2).Load();

query
.Include(x => x.ItemNav3)
.Include(x => x.ItemNav4).Load();

query
.Include(x => x.ItemNav5)
.Include(x => x.ItemNav6).Load();

现在,这是合理的性能,但是,进一步改进它会很好。

我曾考虑过使用 LoadAsync(),经过更多的重构后,它是可能的,并且会更好地适应架构的其余部分。

但是,您一次只能在数据库上下文中执行一个查询。所以我想知道是否有任何方法可以创建新的数据库上下文,对每组导航属性执行 LoadAsync()(异步),然后连接所有结果。

从技术上讲,我知道如何创建新的上下文,为每个导航组触发 LoadAsync(),但不知道如何连接结果,我不知道这是否绝对可行或者它是否违反了良好做法。

所以我的问题是;这是可能的,还是有另一种方法可以进一步提高性能?我试图坚持使用 Entity Framework 提供的内容,而不是制作一些存储过程。谢谢

更新

关于性能差异,我看到在一个语句中使用所有包含和在小组中加载它们之间。运行返回 6000 个项目的查询时。 (使用 SQL 事件探查器和 VS 诊断来确定时间)

分组包含:执行包含总共需要大约 8 秒。

在一条语句中包含:SQL 查询加载需要约 30 秒。 (经常超时)

经过更多调查后,我认为 EF 将 SQL 结果转换为模型时没有太多开销。然而,我们已经看到 EF 花费了将近 500 毫秒来生成复杂的查询,这并不理想,但我不确定这是否可以解决

更新 2

在 Ivan 的帮助下并遵循此 https://msdn.microsoft.com/en-gb/data/hh949853.aspx我们能够进一步改进,特别是使用 SelectMany。我会向任何试图提高其 EF 性能的人强烈推荐这篇 MSDN 文章。

最佳答案

您的第二种方法依赖于 EF 导航属性修复过程。问题是每一个

query.Include(q => q.ItemNavN).Load();

声明还将包括所有主记录数据以及相关实体数据。

使用相同的基本思想,一个潜在的改进可能是为每个导航属性执行一个 Load,将 Include 替换为 Select (用于引用)或 SelectMany(用于集合)- 类似于 EF Core 在内部处理 Include 的方式。

以您的第二种方法为例,您可以尝试以下方法并比较性能:

var query = ctx.Filters.Where(x => x.SessionId == id)
.Join(ctx.Items, i => i.ItemId, fs => fs.Id, (f, fs) => fs);

query.Select(x => x.ItemNav1).Load();
query.Select(x => x.ItemNav2).Load();
query.Select(x => x.ItemNav3).Load();
query.Select(x => x.ItemNav4).Load();
query.Select(x => x.ItemNav5).Load();
query.Select(x => x.ItemNav6).Load();

var result = query.ToList();
// here all the navigation properties should be populated

关于c# - Entity Framework 包括性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40155092/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com