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

<p>у меня есть приложение, которое использует nhibernate в качестве своего orm, и иногда оно испытывает проблемы с производительностью из-за того, как он обращается к данным. какие действия можно предпринять для повышения производительности nhibernate? (пожалуйста, ограничьте одну рекомендацию за ответ)</p>

<p>первая и самая серьезная проблема с производительностью, с которой вы можете столкнуться с nhibernate, - это если вы создаете новую фабрику сеансов для каждого сеанса, который вы создаете. для каждого выполнения приложения должен быть создан только один экземпляр фабрики сеансов, и все фабрики должны быть созданы этой фабрикой.</p><p>в том же духе вы должны продолжать использовать тот же сеанс, если это имеет смысл. это зависит от приложения, но для большинства веб-приложений рекомендуется один сеанс на запрос. если вы часто выбрасываете сеанс, вы не получаете преимуществ от его кэша. интеллектуальное использование кеша сеанса может изменить процедуру с линейным (или хуже) числом запросов на постоянное число без особой работы.</p><p>не менее важно то, что вы хотите убедиться, что лениво загружаете ссылки на ваши объекты. если нет, можно загрузить целые графы объектов даже для самых простых запросов. есть только определенные причины не делать этого, но всегда лучше начинать с отложенной загрузки и переключаться обратно по мере необходимости.</p><p>это приводит нас к стремлению получить, противоположность ленивой загрузки. обходя иерархии объектов или просматривая коллекции, можно легко потерять счет того, сколько запросов вы делаете, и в результате вы получите экспоненциальное количество запросов. стремительное извлечение может быть сделано для каждого запроса с помощью fetch join. в редких случаях, например, при наличии определенной пары таблиц, к которым вы всегда получаете соединение, рассмотрите возможность отключения отложенной загрузки для этих отношений.</p><p>как всегда, sql profiler - отличный способ найти запросы, которые выполняются медленно или выполняются неоднократно. на моей последней работе у нас была функция разработки, которая также подсчитывала количество запросов на страницу. большое количество запросов для подпрограммы является наиболее очевидным показателем того, что ваша подпрограмма плохо работает с nhibernate. если количество запросов на подпрограмму или запрос выглядит хорошо, вы, вероятно, приступили к настройке базы данных; убедитесь, что у вас достаточно памяти для хранения планов выполнения и данных в кеше, правильной индексации данных и т. д.</p><p>одна сложная небольшая проблема, с которой мы столкнулись, была с setparameterlist (). функция позволяет легко передавать список параметров в запрос. nhibernate реализовал это, создав один параметр для каждого переданного элемента. это приводит к разному плану запросов для каждого количества параметров. наши планы выполнения почти всегда выходили из кеша. кроме того, многочисленные параметры могут значительно замедлить запрос. мы сделали собственный хакер nhibernate для отправки элементов в виде списка с разделителями в виде одного параметра. список был разделен в sql server функцией табличных значений, которую наш хак автоматически вставил в предложение in запроса. могут быть и другие наземные мины в зависимости от вашего применения. sql profiler - лучший способ их найти.</p>

<p>sessionfactory nhibernate является дорогостоящей операцией, поэтому хорошей стратегией является создание singleton, который гарантирует, что в памяти есть только один экземпляр sessionfactory:</p><pre><code> 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(); } } </code></pre><p>затем в вашем global.asax application\_startup вы можете инициализировать его:</p><pre><code>protected void application\_start() { nhibernatesessionmanager.instance.initialize(); } </code></pre>

<p>избегайте и/или минимизируйте <a href="http://ayende.com/blog/archive/2008/12/01/solving-the-select-n1-problem.aspx">выберите задачу n + 1</a> , распознавая, когда переключаться с отложенной загрузки на активную выборку для медленно выполняющихся запросов.</p>

<p>нет рекомендации, но есть инструмент, который поможет вам: nh prof ( <a href="http://nhprof.com/">http://nhprof.com/</a> ), кажется, многообещающим, он может оценить ваше использование платформы orm. это может быть хорошей отправной точкой для настройки nhibernate.</p>

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

<p>только "одна рекомендация за ответ"? тогда я бы пошел на это:</p><p>избегайте дубликатов объединений (декартовых продуктов aka) из-за объединений по двум или более параллельным многим ассоциациям; используйте взамен exists-subqueries, multiqueries или fetchmode "subselect".</p><p>взято из: <a href="http://arnosoftwaredev.blogspot.com/2011/01/hibernate-performance-tips.html">советы по настройке производительности hibernate</a> </p>

<p>nhibernate генерирует довольно быстрый sql прямо из коробки. я использую его в течение года, и мне еще предстоит написать голый sql с ним. все мои проблемы с производительностью были связаны с <a href="http://www.codinghorror.com/blog/archives/001152.html">нормализация</a> и отсутствием индексов.</p><p>самое простое решение - проверить планы выполнения ваших запросов и создать правильные индексы, особенно для столбцов внешнего ключа. если вы используете microsoft sql server, "помощник по настройке ядра субд" очень поможет в этом.</p>

<p>мне разрешено ограничить свой ответ одним вариантом? в таком случае я бы выбрал, чтобы вы реализовали механизм кэширования второго уровня nhibernate.</p><p>таким образом, для каждого объекта в вашем файле сопоставления вы можете определить стратегию кэширования. кэш второго уровня сохранит уже извлеченные объекты в памяти и, следовательно, не сделает еще одного обращения к базе данных. это огромный усилитель производительности.</p><p>ваша цель - определить объекты, к которым ваше приложение постоянно обращается. среди них будут общие настройки и тому подобное.</p><p>для кеша второго уровня nhibernate и о том, как его реализовать, нужно найти много информации.</p><p>удачи :)</p>

<p>профилирование - это первый шаг - даже простые синхронизированные модульные тесты - чтобы определить, где можно получить наибольшую прибыль</p><p>для коллекций рассмотрите возможность установки размера пакета, чтобы уменьшить количество выпущенных операторов выбора - смотрите раздел <a href="http://nhibernate.info/doc/nhibernate-reference/performance.html">повышение производительности</a> для деталей</p>

<p>если вы еще не используете отложенную загрузку (соответственно), начните. извлечение коллекций, когда они вам не нужны, - пустая трата всего.</p><p> <a href="http://nhibernate.info/doc/nhibernate-reference/performance.html">глава повышение производительности</a> описывает этот и другие способы повышения производительности.</p>

<p>кэширование, кеширование, кеширование - правильно ли вы используете кеширование первого уровня [преждевременное закрытие сеансов или использование statelesssession для обхода кеширования первого уровня]? вам нужно настроить простой кэш второго уровня для значений, которые меняются редко? можете ли вы кэшировать наборы результатов запросов, чтобы ускорить запросы, которые меняются редко?</p><p>[также конфигурация - вы можете установить элементы как неизменяемые? можете ли вы реструктурировать запросы, чтобы вернуть только необходимую вам информацию и преобразовать их в исходную сущность? сможет ли бэтмен остановить риддлера до того, как он доберется до плотины? ... о, извини, увлекся.]</p>

<p>что говорили много свободного времени.</p><p>прочтите главу 19 документации "повышение производительности".<br> nhibernate: <a href="http://nhibernate.info/doc/nhibernate-reference/performance.html">http://nhibernate.info/doc/nhibernate-reference/performance.html</a> <br> hibernate: <a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html">http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html</a> </p><p>используйте sql profiler (или эквивалент для базы данных, которую вы используете), чтобы найти длительные запросы. оптимизируйте эти запросы с соответствующими индексами.</p><p>для вызовов базы данных, используемых почти на каждой странице приложения, используйте createmultiquery для возврата нескольких наборов результатов из одного запроса к базе данных.</p><p>ну и конечно же кеш. директива outputcache для страниц/элементов управления. nhibernate кеширование данных.</p>