Нужны ли нам хранимые процедуры при использовании скомпилированных запросов?
При использовании скомпилированных запросов в структуре сущностей (или linq-to-sql) в сочетании с SQL Server, есть ли еще какое-то преимущество в производительности при использовании хранимых процедур?
Скомпилированные запросы будут кэшироваться как параметризованные запросы, поэтому производительность должна быть почти равна хранимым процедурам. Есть ли ситуации, когда хранимые процедуры будут работать значительно лучше?
-- РЕДАКТИРОВАТЬ --
В ответ на ответ Якимыча ниже я не имел в виду, что скомпилированные запросы - это то же самое, что хранимые процедуры. Я пытаюсь выяснить, необходимы ли sprocs, если вы выполнили все возможные оптимизации на стороне приложения (в данном случае скомпилированные запросы). Поэтому я думаю, что я ищу причины, по которым хранимая процедура была бы лучше, чем комбинация оптимизаций на стороне приложения и параметризованных запросов (то, чем эффективно являются скомпилированные запросы).
Одна из причин, по которой я спрашиваю об этом, заключается в том, что многие люди считают, что хранимые процедуры больше не нужны по разным причинам (например, этот пост).
3 ответа
"Есть ли ситуация, когда хранимые процедуры будут работать значительно лучше?"
При наличии сопоставимого фрагмента параметризованного SQL, сгенерированного либо в EF, либо в хранимом процессе, они будут работать одинаково.
Однако администратор базы данных всегда имеет возможность дополнительно оптимизировать запрос, основываясь на своем опыте работы со схемой базы данных и ее шаблонами использования. Хранимая процедура позволяет им легко делать это изолированно от приложений, использующих ее, а ORM - нет.
У нас есть чрезвычайно сложная БД SQL Server, в которой есть много внешних систем, реплицирующих и выводящих данные через триггеры. Для нас проблема с EF заключается в том, что ответственность за SQL, который запускается в БД, станет ответственностью разработчиков приложений при использовании любого ORM, а не администраторов баз данных.
Прежде всего, компиляция запросов EF не имеет ничего общего с преимуществами производительности, которые могут быть достигнуты с помощью хранимых процедур.
Согласно http://msdn.microsoft.com/en-us/library/cc853327.aspx - при выполнении запроса по концептуальной модели выполняются следующие операции:
- Загрузка метаданных
- Открытие соединения с базой данных
- Генерация просмотров
- Подготовка запроса
- Выполнение запроса
- Загрузка и проверка типов
- отслеживание
- Материализация объектов
И объяснение относительно Preparing the query
:
Включает затраты на составление команды запроса, создание дерева команд на основе метаданных модели и сопоставления и определение формы возвращаемых данных. Поскольку команды запроса Entity SQL кэшируются, последующее выполнение того же запроса занимает еще меньше времени. Вы также можете использовать скомпилированные запросы LINQ, чтобы уменьшить эту стоимость в последующих выполнениях.
Таким образом, если вы скомпилируете запрос и будете использовать его позже, то вы сэкономите время на этой операции в приложении во время каждого последующего выполнения запроса. Однако чего вы не делаете, так это того, что вы не влияете на сгенерированный код SQL, который выполняется в базе данных. Преимущества производительности, которые вы получаете при компиляции запросов, находятся на уровне приложения.
С другой стороны, вы обычно используете хранимые процедуры, если вы не удовлетворены сгенерированным кодом SQL и хотите оптимизировать производительность на уровне базы данных.
РЕДАКТИРОВАТЬ в ответ на ваш комментарий и редактировать.
Мне кажется, что у вас сложилось впечатление, что компиляция EF-запроса каким-то образом изменит сгенерированный SQL-код, который будет выполняться в базе данных (вы упоминаете, что скомпилированные запросы приводят к параметризованным SQL-запросам?). Это не относится к делу. Независимо от того, выполняете ли вы запрос напрямую или используете compiledQuery.Invoke
, тот же код SQL будет запущен против БД. Более того, вы не имеете полного контроля над ним, вы скорее полагаетесь на ORM, чтобы сгенерировать его наилучшим образом. В некоторых случаях это не оптимально, и именно здесь приходят SP.
Итак, подведем итог:
- Компиляция запросов - это просто оптимизация на стороне приложения. Это экономит время на компиляцию запроса, который снова используется в коде.
- Хранимые процедуры могут использоваться для настройки вашего кода SQL и обеспечения его максимально точного соответствия вашей цели, что дает возможность добиться максимальной производительности на уровне базы данных.
Ни в коем случае одна техника не может заменить другую.
Несколько консервированных ответов от известных экспертов: Пол Нильсен Зачем использовать хранимые процедуры?
Адам Мачаник: Нет, хранимые процедуры НЕ плохие