Вопрос

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

Это было полезно?

Решение

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

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

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

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

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

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

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

SessionFactory в NHibernate — дорогостоящая операция, поэтому хорошей стратегией будет создание Singleton, который гарантирует наличие только ОДНОГО экземпляра 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();
}

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

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

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

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

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

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

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

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

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

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

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

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

Удачи :)

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

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

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

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

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

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

Что сказал «lotoffreetime».

Прочтите главу 19 документации «Повышение производительности».
НГибернейт: 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.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top