2009-11-12 2 views
4

Позвольте мне начать с того, что я знаю, что NH не рекомендует использовать массовые операции. Но, как немного интерес, мне было интересно, почему это так дорого. Для 200 объектов в моей системе это занимает 4 минуты, для которых 90%% времени тратится на DefaultAutoFlushEventListener.OnAutoFlush (благодаря RedGate Profiler). Это безумно. Интересно, написал ли кто-нибудь пользовательский DefaultAutoFlushEventListener, который временно работает вокруг этого препятствия для больших повторяющихся обновлений.Неудовлетворительная производительность NHibernate на событиях автоматического сброса?

Обновление: На самом деле это не проблема с массовым обновлением, так как это связано с транзакциями и FlushMode для запросов. Но все же, что, черт возьми, делает NH, когда он вспыхивает?

+0

4 минуты для 200 объектов чрезвычайно медленны. Сколько запросов sql генерируется? У вас ведется журнал отладки в log4net (это медленная часть eventlistener)? – Paco

+0

См. Мой ответ ниже. Я до сих пор не отвечал, почему слияние в сеансе с множеством объектов берет FOREVER, но я нашел немного элемента NHibernate. – Trent

+1

Связанный с этим вопрос: http://stackoverflow.com/questions/1726656/why-is-nhibernate-autoflush-check-so-expensive – zvolkov

ответ

3

Это был хороший вариант. У меня было каждое обновление в транзакции, и внутри этой транзакции был запрос, который был кэширован 2-м уровнем, но вызвал флеш. Если у вас есть запросы в транзакции, а FlushMode = Auto (в основном не выключен), вы получаете флеш. Это очень дорого, особенно если у вас много объектов в кеше сеанса, что мы и делаем. Извлечение этого запроса из транзакции увеличило время запроса в 5 раз. Более того, превращение всего транзакции вместо отдельных транзакций стало еще одним большим импульсом, потому что каждый транзакт.commit вызывает флеш. Обновление 1000 объектов занимает менее 30 секунд, и я слишком смущен, чтобы сказать, сколько времени прошло. Ahh устаревший код.

Обновление: при дальнейшем расследовании я установил FlushMode для фиксации для нашей конкретной модели вложенных транзакций. Не вдаваясь в подробности, у нас есть конкретная модель транзакций, которая учитывает вложенные транзакции при использовании вложенных вызовов «Логика». Для устаревших приложений мы не хотим устанавливать это по всем направлениям. Конкретной проблемой в этом случае является комбинация использования транзакций и установка FlushMode в Auto (или Always).

+1

Для использования в производстве NHibernate я считаю, что стандартное использование - установить FlushMode = Never в вашем приложении и затем создайте свою конструкцию, которая представляет вашу реализацию шаблона UnitOfWork, чтобы явным образом вызвать Flush, когда он сочтет это необходимым. –

+0

Крис, мы на самом деле используем пользовательскую модель транзакций, для которой, я думаю, FlushMode.Commit лучше. Тем не менее, хороший момент. – Trent

+0

Используете ли вы Spring.Data.NHibernate для вложенных транзакций? – zvolkov

1

В то время как стандартное ISession не рекомендуется для массовых операций, вы можете использовать либо stateless session, либо DML.

+0

В ходе дальнейшего обзора это не было проблемой для массовых обновлений. Я должен изменить название. – Trent

Смежные вопросы