2009-11-05 61 views
8

大部分关于NHibernate懒惰加载的知识是,最好是使用它,而不是使用它。看起来像减少数据库访问是合理的,以减少瓶颈。但很少有东西没有权衡,当然它通过强制你拥有virtual属性来限制设计。但我也注意到一些开发人员在某些经常使用的对象上关闭延迟加载。什么时候应该避免使用NHibernate的延迟加载功能?

这让我想知道是否存在一些使用延迟加载来伤害数据访问性能的确定情况。

所以我想知道,什么时候应该避免延迟加载我的一个NHibernate持久对象?

延迟加载的缺点仅仅是在额外的处理时间,还是可以nhibernate延迟加载也增加了数据访问时间(例如,通过额外的往返数据库)?

谢谢!

回答

19

数据库中的急切和惰性加载对象之间存在明显的性能折衷。

如果您使用急切加载,您会在单个查询中吸收大​​量数据,然后您可以缓存该数据。这在应用程序启动时最为常见。您正在交易数据库往返的内存消耗。

如果使用延迟加载,可以在单个查询中获取最少量的数据,但每次需要更多与该初始数据相关的信息时,都需要对数据库进行更多查询,而数据库性能命中常常是主要性能瓶颈在大多数应用中。

因此,一般来说,您总是希望检索完整的“unit of work”所需的数据,不多也不少。在某些情况下,你可能不知道你需要什么(因为用户正在通过向导或类似的工作),在这种情况下,延迟加载可能是有意义的。

如果您正在使用ORM,并且专注于快速添加功能并且稍后返回并优化性能(这是非常常见的并且是一种很好的方法),但将延迟加载作为默认值是正确的方法。如果您稍后通过性能分析/分析发现有一个查询获取对象,然后N个查询获取与该原始对象相关的N个对象,则可以更改该代码块以使用预先加载来仅命中数据库一次而不是N + 1次(N + 1问题是使用延迟加载的众所周知的缺点)。

+0

但是如果你在项目变得如此庞大之后开始使用lazyloading,那么改变很多东西的时间就晚了。我认为最好的方法是在单个查询中找出需要从数据库中提取的数据。在这种方法中,你可以后者缓存这些对象,但不能缓存那些有延迟加载的对象。 – Meysam 2017-11-28 01:49:06

1

简短的版本是这样的:

  1. 开发更简单,如果你使用延迟加载。您只需以自然的OO方式遍历对象关系,并在您请求时获得所需的内容。
  2. 如果在找到需要之前弄清楚需要什么,性能通常会更好,并在一次访问数据库时提出要求。

在过去的几年中,我们一直专注于快速开发时间。现在我们有了一个稳定的应用和用户基础,我们正在优化我们的数据访问。

+2

总体性能可能会更好,但有时大对象图负载会影响*表观*性能,这对用户来说有时可能是一个更大的交易。 – 2009-11-05 17:35:15

+1

优秀点。加载基础知识。显示。 Ajax根据需要遍历值。 (例如)。 – z5h 2009-11-05 17:59:52

3

延迟加载的通常折衷方法是,您预先对数据库产生较小的影响,但您最终会长时间对其进行更多点击。 没有延迟加载,你会抢先一个完整的对象图,一次吸入大量的数据。这可能会导致您的用户界面滞后,因此经常不鼓励。然而,如果你有一个共同的对象图(不仅仅是单个对象 - 否则它无所谓!),你知道会经常被访问,并从上到下,那么它立即拉下来是有道理的。

举例来说,如果您正在执行订单管理系统,您可能不会在汇总屏幕上拉下每个订单的所有行或所有客户信息。延迟加载可以防止发生这种情况。

我想不出一个不使用它的好例子,但我相信有些情况下你会想要做大量的对象图,比如在应用程序初始化时,按顺序以避免进一步处理滞后。

2

如果您在使用nhibernate处理数据库访问的客户端和服务器之间使用webservice,则使用延迟加载可能会产生问题,因为对象将被序列化并通过webservice发送,随后在“服务器”对象关系需要使用其他Web服务重新访问数据库服务器。在这种情况下,使用延迟加载可能不太好。一个谨慎的话,如果你转换懒惰加载时要小心,它的方式很容易不会想到这一点,并通过最终获取几乎整个数据库...

0

我见过很多性能问题在Hibernate中从错误的加载行为配置引发。我认为NHibernate的情况非常相似。我的建议是始终使用惰性关系,然后在查询中使用渴望获取statemetns - 就像获取连接一样。这可以确保您不会加载太多的数据,并且可以避免执行许多SQL查询。

很容易让一个懒惰的查询渴望。相反,这几乎是不可能的。