Когда следует избегать использования функции отложенной загрузки NHibernate?

Больше всего я слышал о ленивой загрузке NHibernate, что лучше ее использовать, чем не использовать. Кажется, что имеет смысл минимизировать доступ к базе данных, чтобы уменьшить узкие места. Но мало что обходится без компромиссов, конечно, это немного ограничивает дизайн, вынуждая вас иметь virtual свойства. Но я также заметил, что некоторые разработчики отключают ленивую загрузку для некоторых часто используемых объектов.

Это заставляет меня задаться вопросом, есть ли определенные ситуации, когда производительность доступа к данным снижается из-за ленивой загрузки.

Поэтому мне интересно, когда и в каких ситуациях мне следует избегать ленивой загрузки одного из моих сохраняемых объектов NHibernate?

Является ли обратная сторона ленивой загрузки просто дополнительным временем обработки, или nhibernate lazy-loading также может увеличить время доступа к данным (например, путем дополнительных обращений к базе данных)?

Спасибо!


person Mark Rogers    schedule 05.11.2009    source источник


Ответы (5)


Существует очевидный компромисс производительности между активной и отложенной загрузкой объектов из базы данных.

Если вы используете активную загрузку, вы забираете тонну данных за один запрос, которые затем можете кэшировать. Чаще всего это происходит при запуске приложения. Вы торгуете потреблением памяти для обхода базы данных.

Если вы используете отложенную загрузку, вы забираете минимальный объем данных в одном запросе, но каждый раз, когда вам требуется дополнительная информация, относящаяся к этим исходным данным, требуется больше запросов к базе данных, и снижение производительности базы данных очень часто является основным узким местом производительности в большинстве случаев. Приложения.

Таким образом, вы всегда хотите получить именно те данные, которые вам понадобятся для всей "единицы работы ", ни больше ни меньше. В некоторых случаях вы можете не знать точно, что вам нужно (потому что пользователь работает с мастером или чем-то подобным), и в этом случае, вероятно, имеет смысл выполнять ленивую загрузку по ходу.

Если вы используете ORM и сосредоточены на быстром добавлении функций, а позже вернетесь и оптимизируете производительность (что является чрезвычайно распространенным и хорошим способом), то ленивая загрузка по умолчанию - правильный путь. Если позже вы обнаружите (с помощью профилирования / анализа производительности), что у вас есть один запрос для получения объекта, а затем N запросов для получения N объектов, связанных с этим исходным объектом, вы можете изменить этот фрагмент кода, чтобы использовать нетерпеливую загрузку, чтобы только ударить базу данных один раз вместо N + 1 раз (проблема N + 1 - хорошо известный недостаток использования отложенной загрузки).

person Michael Maddox    schedule 06.11.2009
comment
Но если вы начнете использовать ленивую загрузку после того, как проект стал таким огромным, то многое менять уже поздно. Я думаю, что лучший подход - выяснить, какие данные вам нужно извлечь из базы данных, за один-единственный запрос. в этом подходе вы можете позже кэшировать эти объекты, но вы не можете кэшировать те объекты, которые имеют отложенную загрузку. - person Meysam; 28.11.2017
comment
@Meysam Я согласен с вами, но очень часто вы создаете прототипы или только начинаете работу над проектом, и поиск максимальной производительности в то время может быть не самым эффективным использованием вашего времени. Например. В конечном итоге вы тратите так много времени на планирование идеального сценария производительности для фрагмента кода, а к спринту 3 обнаруживаете, что проект принимает другое направление из-за отзывов пользователей. - person Jacques; 27.08.2019

Обычный компромисс для отложенной загрузки заключается в том, что вы делаете меньший удар по базе данных заранее, но в конечном итоге вы делаете больше обращений в нее в долгосрочной перспективе. Без ленивой загрузки вы захватите сразу весь граф объекта, забирая сразу большой кусок данных. Это потенциально может вызвать задержку в вашем пользовательском интерфейсе, поэтому это часто не рекомендуется. Однако, если у вас есть общий граф объектов (а не только один объект - иначе это не имело бы значения!), К которому, как вы знаете, будут обращаться часто и сверху вниз, тогда имеет смысл потянуть его вниз сразу.

Например, если вы создаете систему управления заказами, вы, вероятно, не будете выводить все строки каждого заказа или всю информацию о клиенте на итоговый экран. Ленивая загрузка предотвращает это.

Я не могу придумать хороший пример, чтобы не использовать его навскидку, но я уверен, что есть случаи, когда вы захотите сделать большую нагрузку графа объекта, скажем, при инициализации приложения, чтобы избежать задержек в обработка дальше по линии.

person Harper Shelby    schedule 05.11.2009

Краткая версия такова:

  1. Разработка проще, если вы используете ленивую загрузку. Вы просто пересекаете объектные отношения естественным объектно-ориентированным способом и получаете то, что вам нужно, когда просите об этом.
  2. Производительность обычно выше, если вы выясняете, что вам нужно, прежде чем попросите об этом, и запрашиваете это за одно посещение базы данных.

Последние несколько лет мы уделяли особое внимание быстрой разработке. Теперь, когда у нас есть надежное приложение и база пользователей, мы оптимизируем доступ к данным.

person z5h    schedule 05.11.2009
comment
Общая производительность может быть лучше, но иногда загрузка графа больших объектов может влиять на очевидную производительность, что иногда может быть более серьезной проблемой для пользователей. - person Harper Shelby; 05.11.2009
comment
Отличный момент. Загрузите основы. Отображать. Ajax в пройденных значениях по мере необходимости. (Например). - person z5h; 05.11.2009

Если вы используете веб-сервис между клиентом и сервером, обрабатывающий доступ к базе данных с помощью nhibernate, использование отложенной загрузки может быть проблематичным, поскольку объект будет сериализован и отправлен через веб-сервис, а для последующего использования «объектов» ниже в объектных отношениях требуется новый переход к серверу базы данных с использованием дополнительных веб-сервисов. В таком случае использование отложенной загрузки может оказаться не лучшим вариантом. Предупреждение: будьте осторожны с тем, что вы получаете, если вы включаете ленивую загрузку, ее способ легко не продумывать это до конца и в конечном итоге получить почти всю базу данных ...

person Jimmy    schedule 23.11.2009

Я видел много проблем с производительностью, возникающих из-за неправильной конфигурации поведения загрузки в Hibernate. Я думаю, что с NHibernate ситуация такая же. Я рекомендую всегда использовать ленивые отношения, а затем использовать в запросе показатели состояния с нетерпением - например, соединения выборки -. Это гарантирует, что вы не загружаете слишком много данных и можете избежать множества запросов SQL.

Легко сделать ленивый релиз нетерпеливым с помощью запроса. Обратное практически невозможно.

person Alois Reitbauer    schedule 26.11.2009