EF Core的延迟加载非常缓慢

6

我进行了一个小测试,启用了延迟加载:loading.optionsBuilder.UseLazyLoadingProxies().UseSqlServer(ConnectionString);

(使用EF Core 2.1.4)

我正在循环处理有和没有乐器的情况,以下是我的结果:

情况1

var instruments = db.instruments.OrderBy(t=>t.id).Include(t=>t.NavPro1).ThenInclude(t=>t.NavPro2).Take(200);

案例2

var instruments = db.instruments.OrderBy(t=>t.id).Include(t=>t.NavPro1).ThenInclude(t=>t.NavPro2).Take(200);

那么

   foreach (var i in instruments)
   {
        var props = i.NavPro1;
        foreach (var prop in props)
        {
            sbPrintGreeks.AppendLine(prop.NavPro2.Name + " - " + prop.id + " - " + prop.Value);
        }
   }

没有使用懒加载时,获取100k行数据需要7秒。

使用懒加载时,获取3k行数据需要160秒。

如何提高性能?


1
这可能也会有所帮助,EF 中的 Eager, Lazy 和显式加载 是什么时候使用?https://dev59.com/TlsW5IYBdhLWcg3wwZYP#34628138 - Salah Akbari
1
请参考以下链接:https://dev59.com/lnVD5IYBdhLWcg3wE3Xz - Salah Akbari
3个回答

4

这是一个被称为N+1问题的普遍问题。

当使用懒加载时,你将会有更多的请求。

当你使用 Include 时,你只有一个巨大的请求可以获取到所有数据——或者可能是每个表格一个请求,因此在你的情况下是三个请求。这取决于你的数据具体结构。

而当使用懒加载时,对于每个乐器,你都需要一个请求来获取NavPro1。而对于每个 NavPro1 元素,你又需要一个请求来获取NavPro2。

因此,如果你有1000个乐器,每个乐器有10个NavPro1,那么现在你需要 1 + (1000 * (1 + 10)) = 11001 个请求,而不是最多的三个请求。这很慢,没有疑问。


4

避免使用懒加载,这是毋庸置疑的。

问题在于 - 无论回到任何一个ORM,如果你使用懒加载,每个引用都是懒加载的。这是1+次往返(每个属性至少一次)。单独的SQL执行,单独的网络时间。这些加起来非常快。

这就是为什么每个ORM都支持非懒加载,EF版本通过.Include语句实现,可以扩展SQL或生成单独的SQL(ef core,tolist以使用高效的sql实现关系)。

如果你坚持使用懒加载 - 正如你的问题所暗示的那样,没有魔法尘可用于避免懒加载带来的隐含负面影响。

此外,任何EF Core 3.0之前的版本都存在问题。是的,我指的是3.0 - 不是2.2。因为有许多问题与各种组件有关,包括相当基础的LINQ和性能问题。至少2.2(希望在一个月内发布)应该能解决某些问题。在此之前,尝试使用.Include和AsNoTracking-因为我IRC中有一个性能错误,可能会影响加载200k行数据时的性能。


1
懒加载本来就不应该存在。等待数据库神奇地加载你想要的值...我以前在使用 EF 6 时就会关闭它。 - Camilo Terevinto
好的,谢谢。你能详细说明一下关于相当基础的LINQ的问题吗?如果我没记错的话,有一个性能漏洞?你是否在所有查询中都使用AsNoTracking还是只在某些地方使用? - sofsntp
请前往 Github 存储库,查看错误报告。这些问题包括联合被客户端评估、空检查导致 LINQ 执行失败等。其中还有一个关于大负载下更改跟踪变得非常缓慢的 bug,这正是您所做的事情。修复程序应该在 2.2 版本中。 - TomTom

-1

服务 .AddDbContext<MyContext>(b => b.ReplaceService<ILazyLoader, CustomLazyLoader >()); - Alexander Tretjakov
你能解释一下吗? - sofsntp
此解决方案仅适用于一个DbContext。我需要替换所有未来注册的DbContext的默认服务。 - Alexander Tretjakov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接