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



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

797   12  

12 ответов:

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

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

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

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

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

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

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();
        }
    }

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

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

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

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

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

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

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

"только одна рекомендация на ответ"? Тогда я бы пошел на это:

избегайте объединения дубликатов (АКА декартовых произведений) из-за объединения вдоль двух или более параллельных-много ассоциаций; вместо этого используйте Exists-subqueries, MultiQueries или FetchMode "subselect".

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

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

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

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

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

удачи :)

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

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

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

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

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

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

Что сказал lotsoffreetime.

прочитайте главу 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 кэширование данных.

Comments

    Ничего не найдено.