Является ли использование хранимых процедур плохой практикой? - PullRequest
9 голосов
/ 19 ноября 2009

У нас есть приложение, написанное на C #, которое подключено к серверу ms sql. Мы используем для создания хранимых процедур для каждого вызова базы данных, но затем мы заметили, что использование хранимых процедур дает нам очень большой недостаток, мы не знаем, какие хранимые процедуры нам нужно обновить, если мы изменим нашу базу данных.

Теперь мне стало интересно, является ли использование хранимых процедур плохой или хорошей вещью?

Ответы [ 12 ]

26 голосов
/ 28 февраля 2012

Хранимые процедуры уже несколько лет не пользуются популярностью. В наши дни предпочтительным подходом для доступа к реляционной базе данных является использование O / R-сопоставителя, такого как NHibernate или Entity Framework.

  1. Хранимые процедуры требуют много больше работы для разработки и поддержки. Для каждой таблицы вы должны написать отдельные хранимые процедуры для создания, извлечения, обновления и удаления строки, а также отдельную хранимую процедуру для каждого отдельного запроса, который вы хотите сделать. Кроме того, вы должны написать классы и / или методы в вашем коде для вызова каждой хранимой процедуры. Сравните это с O / R Mapper: все, что вам нужно написать, это ваши определения классов, таблица базы данных и файл отображения. Фактически, современные ORM используют подход, основанный на соглашениях, который устраняет необходимость в отдельном определении отображения.

  2. Хранимые процедуры способствуют плохим практикам разработки, в частности, они требуют, чтобы вы нарушали DRY (не повторяйте себя), поскольку вы должны напечатать список полей в вашей таблице базы данных полдюжины раз или больше минимум . Это большая проблема, если вам нужно добавить один столбец в таблицу базы данных. Невозможно передать объект в качестве параметра хранимой процедуре, только простые типы (строка, целое число, дата / время и т. Д.), Что делает практически невозможным избежать огромных списков параметров (дюжина или более).

  3. Хранимые процедуры способствуют неправильной практике управления конфигурацией. Это вытекает из аргумента, что администраторы баз данных должны иметь возможность изменять их независимо от самого кода. Это приводит к тому, что версия вашего кода, поступающая в производство, которая никогда не была протестирована на интеграцию, не соответствует ни одной конкретной ревизии в управлении исходным кодом и может фактически даже не соответствовать любой ревизии в управлении исходным кодом совсем. По сути, если у вас нет проверяемой записи о том, какая именно редакция вашего кода находится в производстве, у вас возникнут проблемы.

  4. Хранимые процедуры должны развертываться отдельно от основной части вашего кода. Если у вас нет полностью автоматизированного процесса их обновления, существует значительный риск того, что они могут не синхронизироваться с вашей основной кодовой базой в одной или нескольких средах, что приведет к ошибкам. Это особенно проблематично, если вам нужно использовать инструмент деления пополам для контроля версий, в которых произошла ошибка.

  5. Хранимые процедуры негибки. Если вы хотите запросить ваши данные несколькими различными способами (разные порядки сортировки, отложенная загрузка по сравнению с активной загрузкой, разбиение по страницам и т. Д.), Вам потребуется написать множество отдельных хранимых процедур для всех разных вариантов использования, тогда как ORM предоставляют вам гибкие мощный язык запросов (например, Linq to NHibernate).

  6. Хранимые процедуры требуют повторного изобретения колес. Если вам нужен оптимистичный параллелизм, или шаблон единицы работы, или ленивая загрузка, или карта удостоверений, или обработка родительских / дочерних коллекций, или кэширование, или отображения иерархии классов, или почти любые другие шаблоны проектирования, о которых вы читали в книге Мартина Фаулера Шаблоны архитектуры корпоративных приложений вам необходимо самостоятельно перестроить эту функциональность, в то время как O / R mapper дает вам все это, и даже больше, прямо из коробки. Очень часто вам придётся заново изобретать эти колеса, используя код для копирования и вставки, что опять же является плохой практикой.

  7. Хранимые процедуры сложны для модульного тестирования. С помощью ORM вы можете смоделировать код своей базы данных, чтобы иметь возможность быстро протестировать свою бизнес-логику. С помощью хранимых процедур вы должны перестроить всю тестовую базу данных с нуля.

  8. Хранимые процедуры не дают никакого преимущества в производительности. (Крошечные) выгоды, которые вы получаете, передавая по проводу только имя sproc, а не строку SQL, легко компенсируются тем фактом, что слишком велика вероятность того, что вы вызовете одну и ту же процедуру два или три раза с одним и тем же параметров в том же запросе, в то время как ORM смотрел бы в своей карте идентичности и говорил: «Эй, я уже получил этот, нет необходимости делать еще один обход». Более того, утверждение о том, что хранимые процедуры кэшируются на сервере, в то время как специальный SQL не используется, является мифом, который был опровергнут Франсом Боумой в своем посте в блоге: « Хранимые процедуры плохие, хорошо?» 1042 * "

  9. Хранимые процедуры предлагают мало или вообще не дают никаких преимуществ с точки зрения безопасности и не защищают вас от уязвимостей SQL-инъекций. Показательный пример:


create procedure GetUsers(@SortOrder nvarchar(50))
as
begin
    declare @sql nvarchar(100)
    set @sql = 'SELECT * FROM Users ORDER BY ' + @SortOrder
    exec @sql
end

Конечно, вы можете писать хранимые процедуры, в которых нет уязвимостей для SQL-инъекций, но вы также можете написать специальный SQL-код на вашем бизнес-уровне, который не имеет уязвимостей для SQL-инъекций, с помощью параметризованных запросов. Присвоение защиты от внедрения SQL-кода хранимым процедурам вместо того, чтобы не разбивать строки SQL вместе, является красной сельдью и полностью вводит в заблуждение.

6 голосов
/ 19 ноября 2009

Это не проблема SP, это проблема вашего процесса разработки. Если у вас нет нужной информации - просто получите ее.

Вы можете создать простую визуальную карту, которая показывает схему вашей таблицы и зависимые SP. Если ваша БД слишком велика для визуального отображения, добавьте общий текстовый файл, который состоит из ваших SP и имен таблиц, от которых он зависит.

В любом случае, чем больше ваша БД, тем хуже будет ваша работа при встраивании деталей вашей схемы в код вашего приложения. При использовании SP вы гарантируете, что эта функциональность не будет удвоена и что большинство изменений произойдет на стороне БД без приложения перекомпиляция и перераспределение .

Upd

Я забыл упомянуть еще одну вещь. Хорошие инструменты БД позволяют легко находить зависимые таблицы для каждого SP. Например, в контекстном меню SP в Microsoft SQL Management Studio есть пункт «Просмотр зависимостей».

5 голосов
/ 19 ноября 2009

Я считаю, что SP хороши для расчетов / манипулирования данными / источников данных отчетов в БД.

При использовании его исключительно для извлечения данных / обновления строк таблицы вы столкнетесь с целым миром боли.

Это подход, которому следуют некоторые слои доступа к данным, и операции извлечения данных для отдельной строки могут стать проблемой.

Так что нет, я бы не рекомендовал это как лучший путь.

2 голосов
/ 19 ноября 2009

Есть два взгляда на это: одни говорят, что они злые, другие клянутся ими. Я беру середину дорожного обзора на этом.

Плюсы
Поддержка, если вам нужно немного изменить запрос, не влияя на другой код, вы можете сделать это без необходимости развертывания новых сборок. Безопасность, без SQL-инъекций, если вы не нарушаете передовой опыт и не строите динамические запросы в proc

Против
Без документации и стандартов все может быстро выйти из-под контроля и сделать обслуживание базы данных настоящим кошмаром.

Предложения
Используйте их для составления отчетов и для более сложных операций с базами данных, но старайтесь держаться подальше от простых операций CRUD.
Храните свою бизнес-логику вне базы данных, которая должна быть на отдельном слое ИМХО.

1 голос
/ 19 ноября 2009

Вы не хотите знать, влияют ли изменения схемы БД на SP. Это означает, что команда, которая изменяет DB, не пишет SP. В этом контексте переход от SP к встроенному SQL или ORM вам не поможет. Вместо проверки SP вам придется проверять свой код. Я предлагаю вам купить хорошие инструменты, которые показывают вам зависимости между вашими таблицами и SP.

1 голос
/ 19 ноября 2009

Я работал над проектами, которые часто использовали хранимые процедуры. По сути, бизнес-уровень был перенесен в базу данных, потому что на руководителя группы произвел впечатление некий гуру оракула, которого он встретил на своей предыдущей работе.

Код хранимой процедуры сложнее поддерживать, чем C # (в Visual Studio), поскольку инструменты хуже, отладка сложнее и т. Д.

В то же время, имея четкие интерфейсы к вашим правилам данных. Думать о том, какие запросы будут выполняться в базе данных, может быть хорошей вещью.

Постарайтесь сохранить код создания и переноса (обновления) базы данных в системе контроля версий. Включите хранимые процедуры там, если вы действительно хотите их. Сохраняйте логику хранимых процедур как можно более простой (не делайте никакой бизнес-логики, просто работайте в стиле согласованности). Может быть, даже сгенерировать их из более абстрактного представления (вместе с кодом C # для их вызова).

1 голос
/ 19 ноября 2009

Нельзя сказать, что это хорошо или плохо. У них есть свои преимущества и недостатки, и в зависимости от проекта их вес может отличаться.

Некоторые преимущества:

  • Они выполняются непосредственно СУБД, поэтому нет необходимости в промежуточной передаче данных на средний уровень, если задействовано несколько запросов (сложная логика).
  • Позволяет использовать один слой для изменения данных в дБ.

Некоторые недостатки:

  • У вас есть логическое разделение между средним уровнем (C # в вашем случае) и постоянным уровнем (DB), что может определять проблемы с точки зрения обслуживания.
1 голос
/ 19 ноября 2009

Хранимые процедуры полезны для применения ограничений на уровне базы данных. Проще проверить несколько хранимых процедур, ограничивающих доступ к базе данных, чем проверить каждый бит клиентского кода. Так что это делает их хорошими.

Кроме этого, я скептик. Мне нравится, когда все в одном месте, на языке, который я могу тестировать.

0 голосов
/ 19 ноября 2009

Еще одним большим преимуществом хранимых процедур является то, что вы можете вносить изменения в бэкэнд на лету, не требуя повторного развертывания приложения (если прототип не изменяется).

В крупной компании, в которой я работаю, развертывание кода является ОСНОВНЫМ упражнением, требующим не менее 30 дней и многократных согласований. Изменение в БД может быть сделано почти сразу.

Наконец, помните, что хранимые процедуры также могут обеспечить защиту от плохих программистов. У вас есть отличный администратор баз данных, но команда подрядчиков, предлагающих самые дешевые предложения, пишет ваш код? Администратор базы данных может писать хранимые процедуры, а затем удалять разрешения DML из таблиц, заставляя код проходить через хранимую процедуру для внесения любых изменений. Таким образом, вам не нужно беспокоиться о том, что какой-то парень вставит в код код SQL, который случайно уничтожит половину БД.

0 голосов
/ 19 ноября 2009

Хранимые процедуры действительно хороши для очень распространенных запросов, которые не будут часто меняться. Если у вас есть SP для «getname», который всегда извлекает имя и фамилию из таблицы, это будет хорошо для сохранения в долгосрочной перспективе. Кроме того, если у вас очень сложный запрос, который может потребовать много ресурсов на стороне клиента, хранимая процедура может помочь.

Любой запрос, который может быть динамическим, не должен быть SP. Если это что-то, что часто меняется, или что-то, к чему вам нужен быстрый доступ, плохая идея сделать SP. Вот почему. Допустим, вы создали хороший SP, который получает данные определенного типа. У вас есть 3 разных проекта, которые используют его. Но вам нужно что-то немного другое, поэтому ваш выбор:

  1. Изменение хранимой процедуры и риск взлома всех зависимых приложений
  2. Создание новой хранимой процедуры, которая очень похожа на вашу функцию.

В целом хранимые процедуры отлично подходят для одних нужд, но не для других. Оцените, насколько ваши потребности могут измениться, или каковы недостатки использования стандартного запроса.

...