Как лучше всего повысить производительность NHibernate?

У меня есть приложение, которое использует NHibernate в качестве ORM, и иногда у него возникают проблемы с производительностью из-за того, как оно обращается к данным. Что можно сделать для повышения производительности NHibernate? (Пожалуйста, ограничьтесь одной рекомендацией на ответ)

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
61
0
27 849
12
Перейти к ответу Данный вопрос помечен как решенный

Ответы 12

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

Ответ принят как подходящий

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

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

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

Это приводит нас к активной загрузке, противоположной ленивой загрузке. Во время обхода иерархий объектов или циклов по коллекциям можно легко потерять счет, сколько запросов вы делаете, и вы получите экспоненциальное количество запросов. Активная выборка может выполняться для каждого запроса с помощью FETCH JOIN. В редких случаях, например, если есть определенная пара таблиц, которые вы всегда выбираете для соединения, рассмотрите возможность отключения отложенной загрузки для этой связи.

Как всегда, SQL Profiler - отличный способ найти запросы, которые выполняются медленно или выполняются повторно. На моей последней работе у нас была функция разработки, которая также подсчитывала запросы на запрос страницы. Большое количество запросов к рутине - самый очевидный показатель того, что ваша рутина не работает с NHibernate. Если количество запросов на подпрограмму или запрос выглядит хорошо, вы, вероятно, дошли до настройки базы данных; убедитесь, что у вас достаточно памяти для хранения планов выполнения и данных в кеше, правильно индексируя ваши данные и т. д.

Одна маленькая хитрая проблема, с которой мы столкнулись, была с SetParameterList (). Функция позволяет легко передать список параметров в запрос. NHibernate реализовал это, создав по одному параметру для каждого переданного элемента. Это приводит к разному плану запроса для каждого количества параметров. Наши планы выполнения почти всегда удалялись из кеша. Кроме того, большое количество параметров может значительно замедлить выполнение запроса. Мы сделали специальный хак NHibernate, чтобы отправлять элементы в виде списка с разделителями в одном параметре. Список был разделен в SQL Server функцией табличного значения, которую наш хакер автоматически вставил в предложение IN запроса. В зависимости от вашего приложения могут быть и другие подобные мины. SQL Profiler - лучший способ их найти.

NH не ленивая загрузка ссылок на объекты по умолчанию? Если нет, что вы делаете, чтобы это заставить?

sydneyos 10.05.2012 01:57

@sydneyos Если вы используете Fluent NHibernate, вы можете просто добавить DefaultLazy.Always () в качестве соглашения в вашу конфигурацию Fluent NHibernate. Я не уверен, как это работает с сопоставлениями .hbm, но полагаю, вы можете довольно легко добавить это в конфигурацию NH.

Anshul 04.10.2013 18:16

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

Самое простое решение - изучить планы выполнения ваших запросов и создать правильные индексы, особенно для столбцов внешнего ключа. Если вы используете Microsoft SQL Server, советник по настройке ядра СУБД очень поможет в этом.

Если вы еще не используете отложенную загрузку (соответственно), начните. Получение коллекций, когда они вам не нужны, - это пустая трата времени.

Глава Повышение производительности описывает этот и другие способы повышения производительности.

Профилирование - это первый шаг - даже простые временные модульные тесты - чтобы выяснить, где можно получить наибольшую выгоду.

Для коллекций рассмотрите возможность установки размера пакета, чтобы уменьшить количество выдаваемых операторов выбора - подробности см. В разделе Повышение производительности.

Мне разрешено ограничить свой ответ одним вариантом? В этом случае я бы выбрал, что вы реализуете механизм кеширования второго уровня NHibernate.

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

Ваша цель - определить объекты, к которым ваше приложение постоянно обращается. Среди них будут общие настройки и тому подобное.

Существует много информации о кэше второго уровня nhibernate и о том, как его реализовать.

Удачи :)

Кэширование, кэширование, кэширование - правильно ли вы используете кеширование первого уровня [преждевременное закрытие сеансов или использование StatelessSession для обхода кэширования первого уровня]? Вам нужно настроить простой кеш второго уровня для редко меняющихся значений? Можете ли вы кэшировать наборы результатов запросов, чтобы ускорить запросы, которые меняются нечасто?

[Также конфигурация - можно ли сделать элементы неизменяемыми? Можете ли вы реструктурировать запросы, чтобы вернуть только нужную информацию и преобразовать их в исходную сущность? Сможет ли Бэтмен остановить Загадочника до того, как он доберется до плотины? ... ой, извини увлекся.]

SessionFactory NHibernate - дорогостоящая операция, поэтому хорошей стратегией является создание синглтона, который гарантирует, что в памяти будет только ОДИН экземпляр SessionFactory:

   public class NHibernateSessionManager
    {
        private readonly ISessionFactory _sessionFactory;

        public static readonly NHibernateSessionManager Instance = new NHibernateSessionManager();

        private NHibernateSessionManager()
        {
            if (_sessionFactory == null)
            {
                System.Diagnostics.Debug.WriteLine("Factory was null - creating one");
                _sessionFactory = (new Configuration().Configure().BuildSessionFactory());
            }
        }

        public ISession GetSession()
        {
            return _sessionFactory.OpenSession();
        }

        public void Initialize()
        {
            ISession disposeMe = Instance.GetSession();
        }
    }

Затем в вашем Global.Asax Application_Startup вы можете инициализировать его:

protected void Application_Start()
{
    NHibernateSessionManager.Instance.Initialize();
}

+1 за простой рабочий пример и объяснение. Я бы хотел, чтобы была возможность дать больше 1 за хороший ответ!

Yordan Georgiev 18.05.2009 13:41

Избегайте и / или минимизируйте Выберите задачу N + 1, распознавая, когда переключаться с ленивой загрузки на активную выборку для медленно выполняющихся запросов.

Не согласен с решением. Сохраните ленивую загрузку, но включите пакетная выборка ленивой загрузки. Это устраняет проблему N + 1 с минимальным влиянием на код. Я написал об этом больше в своем ответе на другой вопрос здесь.

Frédéric 12.05.2017 13:39

Это не рекомендация, а инструмент, который поможет вам: NH Prof (http://nhprof.com/) кажется многообещающим, он может оценить ваше использование структуры ORM. Это может быть хорошей отправной точкой для настройки NHibernate.

Ага. Заставьте его работать, ЗАТЕМ заставьте его работать быстро. А профилировщик, такой как NH Prof, может показать вам узкие места.

Matt Hinze 04.02.2009 15:58

Что сказал много свободного времени.

Прочтите главу 19 документации «Повышение производительности» .
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Спящий режим: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Используйте SQL Profiler (или эквивалент для используемой базы данных), чтобы найти долго выполняющиеся запросы. Оптимизируйте эти запросы с помощью соответствующих индексов.

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

Ну и конечно же кеш. Директива OutputCache для страниц / элементов управления. Кеширование данных NHibernate.

Только «Одна рекомендация на ответ»? Тогда я бы выбрал вот это:

Избегайте объединения дубликатов (AKA декартовы произведения) из-за объединений по двум или более параллельным ко многим ассоциациям; вместо этого используйте Exists-subqueries, MultiQueries или FetchMode «подзапрос».

Взято из: Советы по настройке производительности Hibernate

Другие вопросы по теме