Является ли NHibernate-SQL медленнее, чем рукописные операторы в SP в настоящее время?
Меня интересует общая производительность при вставках / обновлениях / удалениях в sql server 2012 db, при этом объем данных иногда достигает 20 м. строки в таблице.
Могу ли я доверять NHibernate в создании оптимальных запросов?
4 ответа
Простой ответ: нет. NH не может генерировать "оптимальные запросы" так, как вы это делаете с рукописными запросами.
Обычно он получает данные из базы данных для создания объектов в памяти. Так, например, по умолчанию он всегда выбирает все столбцы в таблице. Он также пытается оптимизировать время компиляции SQL, пытаясь всегда генерировать одни и те же запросы с одинаковыми аргументами.
Вы по-прежнему можете писать свои рукописные запросы на HQL, Linq или SQL. Обычно вы теряете преимущества ORM, но это работает отлично, если только несколько случаев в вашем приложении критичны по производительности и не сильно ориентированы на объект.
NHibernate может выполнять другие оптимизации производительности, которых вы вряд ли сможете достичь с помощью написанного от руки SQL. И эти функции прозрачны для бизнес-логики и не требуют особых усилий по разработке.
Эти особенности особенно в области ленивой загрузки и размера партии (предварительная выборка). С рукописным SQL вы должны оптимизировать производительность в вашей бизнес-логике. Если ваша бизнес-логика сложна, просто не хватает места для оптимизации, и ремонтопригодность становится огромной проблемой. Это ситуация, когда производительность и ремонтопригодность рукописного DAL падает, и это вызывает настоящую боль. Это ситуация, когда NHiberate предлагает как лучшую производительность, так и лучшую ремонтопригодность.
Как вы можете догадаться: если ваша бизнес-логика не очень сложна, рукописный DAL может обеспечить наилучшую возможную производительность при не слишком большом компромиссе с удобством обслуживания.
Поэтому всегда выбирайте правильный инструмент для решения проблемы.
Пример дела
В приложении есть функция для обработки заказов. Он получает первичный ключ в качестве аргумента. Он загружает заказ с элементами заказа из базы данных, ему нужна информация о пользователях и продуктах, местах, налогах, почтовых расценках, специальных предложениях и тому подобном. Так что это очень сложная вещь. Оптимизация запросов не является большой проблемой, потому что большинство запросов тривиально по своей природе.
Четыре года спустя ваш начальник хочет "пакетного процесса", при котором вы можете обрабатывать сотни заказов. Поэтому вы должны вызывать свою функцию в цикле. Первая проблема: вы получаете заказы для обработки по оптимизированному запросу. Но ваша функция принимает первичный ключ в качестве аргумента и загружает заказы снова. Следующая проблема: все связанные данные о продуктах, местах и т. Д. Необходимо загружать для каждого заказа снова, хотя они в большинстве случаев одинаковы (но не всегда). Так что начинает работать очень плохо. Вы пытаетесь реализовать несколько кешей для вещей, которые вы уже загрузили из базы данных. Управлять изменениями этих данных становится сложно, потому что у вас есть версия в базе данных и версия в кеше. Таким образом, вы делаете все возможное, пока он не заработает достаточно хорошо, в то время как вы потеряли контроль над своим кодом, который был так хорош до того, как появился "пакетный процесс". И какая бы функция ни шла дальше, она убьет вас.
С NHibernate это выглядит совсем иначе. Вам не нужно передавать первичные ключи никогда. У вас есть объекты (которые могут быть прокси и содержат только первичный ключ), которые загружаются из базы данных ровно один раз. При переходе (в отличие от использования дополнительных запросов) от заказа к продуктам, местоположениям и прочему объекты загружаются только один раз при первом использовании. Из-за настраиваемого размера партии NH предварительно выбирает продукты, местоположения и т. Д. Для некоторых заказов, которые будут обработаны позже, поэтому он избегает дополнительных запросов. Ваш код в основном содержит только те вычисления, которые вам нужны, и не содержит сложных вещей, которые необходимы для повышения производительности. (Хорошо, так будет в идеальном мире, но на самом деле это очень хорошо).
Использование NHibernate или любого ORM является выбором, в основном выбираемым для того, чтобы иметь более поддерживаемый код по сравнению с кодом с SQL и SP.
В некоторых случаях он может генерировать запрос недостаточно быстро по сравнению с SP, и все же во многих из этих случаев могут не быть заметных проблем с производительностью. Однако, если это не так, вы всегда можете использовать SP и использовать NHibernate для вызова SP.
Это зависит от того, что вы бы назвали оптимальными запросами, и от того, насколько ваша модель данных соответствует вашей модели базы данных (таблицы).
Вы можете регистрировать все операторы, чтобы было понятно, что делает NHibernate и какие операторы SQL он использует для запроса или обновления базы данных.
NHibernate дает вам много возможностей для настройки ваших запросов. Некоторые возможности: сеансы без сохранения состояния, сеансы без транзакций, HQL, фьючерсы.
Если это все еще не работает, как вы намеревались, вы можете вызывать операторы SQL непосредственно из NHibernate. Недостатком этого является то, что вы теряете возможность переносить свой код довольно легко в другую базу данных, если это важно для вас.
Вы не должны слепо доверять этому. Существует множество способов оптимизации запросов в NHibernate, таких как множественные API для запросов, включая возможность генерировать запросы HQL или SQL.
Существуют различные инструменты профилирования, в том числе NHibernate Profiler, которые можно использовать для мониторинга запросов и общей производительности.
Также есть IStatelessSession
предназначен для массовых операций.