我听说NHibernate懒惰加载的大部分内容是使用它比使用它更好。似乎最小化数据库访问是有意义的,以减少瓶颈。但很少有事情没有取舍,当然它会通过强迫你拥有virtual
属性来略微限制设计。但我也注意到一些开发人员对某些经常使用的对象进行了延迟加载。
这让我想知道是否存在使用延迟加载会损害数据访问性能的某些明确情况。
所以我想知道,何时以及在什么情况下我应该避免延迟加载我的一个NHibernate持久化对象?
懒惰加载的缺点是仅在额外的处理时间内,还是nhibernate延迟加载也会增加数据访问时间(例如,通过额外的往返数据库)?
谢谢!
答案 0 :(得分:20)
数据库中的eager和lazy加载对象之间存在明显的性能折衷。
如果您使用预先加载,则会在单个查询中吸收大量数据,然后您可以缓存该数据。这在应用程序启动时最常见。您正在交换数据库往返的内存消耗。
如果使用延迟加载,则在单个查询中吸收最少量的数据,但是当您需要与该初始数据相关的更多信息时,它需要对数据库进行更多查询,并且数据库性能命中通常是主要性能大多数应用程序都存在瓶颈。
因此,一般来说,您总是希望准确检索整个“unit of work”所需的数据,不多也不少。在某些情况下,您可能无法确切地知道您需要什么(因为用户正在使用向导或类似的东西),在这种情况下,延迟加载可能是有意义的。
如果您正在使用ORM并专注于快速添加功能,并且会在以后返回并优化性能(这是非常常见并且是一种很好的方法),延迟加载是默认的正确方法。如果您稍后发现(通过性能分析/分析)您有一个查询来获取一个对象然后N个查询来获取与该原始对象相关的N个对象,您可以更改该段代码以使用预先加载来仅触及数据库一次而不是N + 1次(N + 1问题是使用延迟加载的众所周知的缺点)。
答案 1 :(得分:3)
懒惰加载的通常权衡是你先在数据库上做一个较小的命中,但最终你会对它进行更长时间的点击。 在没有延迟加载的情况下,您将预先获取整个对象图,同时吸取大量数据。这可能会导致您的UI出现延迟,因此通常不鼓励这样做。但是,如果你有一个共同的对象图(不只是单个对象 - 否则无关紧要!),你知道它会被频繁访问,从上到下,那么立即将其拉下来是有道理的。
例如,如果您正在执行订单管理系统,您可能不会在摘要屏幕上下拉每个订单的所有行或所有客户信息。延迟加载可防止这种情况发生。
我无法想到一个好的例子,不能随意使用它,但我确信在某些情况下你需要对应用程序初始化进行大量的对象图,以便避免在进一步处理中滞后。
答案 2 :(得分:2)
简短版本是:
过去几年来,我们一直专注于快速开发时间。现在我们拥有了坚实的应用和用户群,我们正在优化数据访问。
答案 3 :(得分:2)
如果您在使用nhibernate处理数据库访问的客户端和服务器之间使用Web服务,则使用延迟加载可能会出现问题,因为对象将被序列化并通过Web服务发送,并随后在对象中使用“对象” relationship需要使用其他Web服务重新访问数据库服务器。在这种情况下,使用延迟加载可能不太好。需要注意的是,如果你转动延迟加载,请小心你所取的内容,这样就很容易不去思考这个过程并最终获取几乎整个数据库......
答案 4 :(得分:0)
我在Hibernate中看到了许多因错误的加载行为配置而导致的性能问题。我觉得NHibernate的情况大致相同。我的建议是始终使用惰性关系,然后在查询中使用eager fetching statemetns - 比如fetch join - 。这可以确保您不会加载大量数据,并且可以避免许多SQL查询。
通过查询很容易让人感到厌倦。反过来几乎是不可能的。