Нужно ли хранить хранимые процедуры при использовании скомпилированных запросов?
При использовании скомпилированных запросов в инфраструктуре сущностей (или linq-to-sql) в сочетании с SQL Server, действительно ли есть какое-либо преимущество в производительности при использовании хранимых процедур?
Скомпилированные запросы будут кэшироваться в качестве параметризованных запросов, поэтому производительность должна быть примерно равной хранимым процедурам. Есть ли ситуация, когда хранимые процедуры будут работать значительно лучше?
- EDIT -
В ответ на ответ Якимыча ниже я не имел в виду, что скомпилированные запросы совпадают с хранимыми процедурами. Я пытаюсь выяснить, нужны ли sprocs, если вы сделали все возможные оптимизации на стороне приложения (в этом случае скомпилированные запросы). Поэтому я предполагаю, что я ищу причины, по которым хранимая процедура будет лучше, чем комбинация оптимизаций на стороне приложения и параметризованных запросов (что эффективно компилирует запросы).
Одна из причин, почему я спрашиваю об этом, состоит в том, что многие люди, похоже, думают, что хранимые процедуры больше не нужны по разным причинам (т.е. этот пост).
Ответы
Ответ 1
"Есть ли ситуация, когда хранимые процедуры будут работать значительно лучше?"
Учитывая сопоставимую часть параметризованного SQL, сгенерированную в EF или сохраненном proc, они будут работать одинаково.
Однако у администратора базы данных всегда есть возможность дополнительно оптимизировать запрос на основе их опыта с схемой БД и его шаблонами использования. Хранимая процедура позволяет им делать это легко, в отличие от приложений, использующих его, тогда как ORM не делает.
У нас есть чрезвычайно сложная база данных SQL Server, в которой есть множество внешних систем, которые реплицируют данные через триггеры. Проблема для нас с EF заключается в том, что ответственность за SQL, которая запускается в БД, станет ответственностью разработчиков приложений при использовании любой ORM, а не администраторов баз данных.
Ответ 2
Прежде всего, компиляция запросов 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 и максимально приблизить его к вашей цели, что дает возможность получить максимальную производительность на уровне базы данных.
Ни один из методов не может заменить другой.
Ответ 3
Несколько консервированных ответов от известных экспертов: Пол Нильсен Зачем использовать хранимые процедуры?
Adam Machanic: Нет, хранимые процедуры НЕ НЕИСПРАВНОСТИ