Что лучше:Специальные запросы или хранимые процедуры?[закрыто]

StackOverflow https://stackoverflow.com/questions/22907

  •  09-06-2019
  •  | 
  •  

Вопрос

Предполагая, что вы по какой-либо причине не можете использовать LINQ, лучше ли размещать ваши запросы в хранимых процедурах или это такая же хорошая практика для выполнения ad hoc запросы к базе данных (скажем, SQL Server для аргументации)?

Это было полезно?

Решение

Исходя из моего опыта написания в основном клиент-серверных приложений WinForms, я пришел к таким простым выводам:

Использовать Хранимые процедуры:

  1. Для любой сложной работы с данными.Если вы собираетесь делать что-то, действительно требующее использования курсора или временных таблиц, обычно быстрее всего это сделать в SQL Server.
  2. Когда вам нужно заблокировать доступ к данным.Если вы не предоставляете доступ к таблице пользователям (или роли, или чему-то еще), вы можете быть уверены, что единственный способ взаимодействия с данными - это созданные вами SP.

Используйте специальные запросы:

  1. Для CRUD, когда вам не нужно ограничивать доступ к данным (или вы делаете это другим способом).
  2. Для простого поиска.Создание SP для множества критериев поиска является сложной задачей, и ее трудно поддерживать.Если вы можете сгенерировать достаточно быстрый поисковый запрос, используйте это.

В большинстве своих приложений я использовал как SP, так и ad-hoc sql, хотя я обнаружил, что использую SP все реже и реже, поскольку в конечном итоге они представляют собой код, похожий на C #, только сложнее контролировать версии, тестировать и поддерживать.Я бы рекомендовал использовать ad-hoc sql, если только вы не можете найти конкретной причины не делать этого.

Другие советы

Я не могу ссылаться ни на что, кроме SQL Server, но аргументом производительности является нет там это существенно, если только вы не используете версию 6.5 или более раннюю.SQL Server кэширует планы выполнения ad-hoc уже примерно десять лет.

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

Встраивая запросы в свое приложение, вы тесно привязываете себя к своей модели данных.

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

С точки зрения безопасности рекомендуется запретить db_datareader и db_datawriter в вашем приложении и разрешать доступ только к хранимым процедурам.

Я думаю, что это основной конфликт между людьми, которые должны поддерживать базу данных, и людьми, которые разрабатывают пользовательские интерфейсы.

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

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

Наши разработчики говорят нам, что они рады, что весь наш доступ к базе данных осуществляется через процедуры, потому что это позволяет намного быстрее исправить ошибку, связанную с данными, а затем просто запустить процедуру в рабочей среде, а не создавать новую ветвь кода, перекомпилировать и перезагрузить его в рабочую среду.Мы требуем, чтобы все наши процедуры были в subversion, поэтому контроль версий вообще не является проблемой.Если этого нет в Subversion, администраторы баз данных будут периодически удалять его, поэтому нет никаких препятствий для использования системы управления версиями.

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

Я не понимаю всей этой проблемы с управлением версиями в хранимой процедуре.Вы определенно можете управлять их версиями, если только будете немного дисциплинированы.

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

Я хотел бы процитировать Тома Кайта из Oracle здесь ... Вот его правило о том, где писать код ... хотя оно немного не связано, но, думаю, полезно знать.

  1. Начните с хранимых процедур на PL / SQL...
  2. Если вы считаете, что что-то невозможно сделать с помощью хранимой процедуры в PL / SQL, используйте хранимую процедуру Java.
  3. Если вы считаете, что что-то невозможно сделать с помощью хранимой процедуры Java, рассмотрите Pro * c.
  4. Если вы считаете, что не сможете чего-то достичь с помощью Pro * C, возможно, вам захочется переосмыслить то, что вам нужно сделать.

В нашем приложении есть слой кода, который предоставляет содержимое запроса (и иногда является вызовом хранимой процедуры).Это позволяет нам:

  • легко иметь все запросы под контролем версий
  • чтобы внести какие-либо изменения, необходимые для каждого запроса для разных серверов баз данных
  • устраняет повторение одного и того же кода запроса во всем нашем коде

Управление доступом реализовано на среднем уровне, а не в базе данных, поэтому нам не нужны хранимые процедуры там.В некотором смысле это промежуточный путь между специальными запросами и хранимыми процедурами.

Мой ответ из другого Публикация:Хранимые процедуры - это Еще ремонтопригоден, потому что:

  • Вам не нужно перекомпилировать ваше приложение на C # всякий раз, когда вы хотите изменить какой-либо SQL
  • В конечном итоге вы повторно используете SQL-код.

Повторение кода - это худший вот что вы можете сделать, когда пытаетесь создать поддерживаемое приложение!

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

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

Проще перенести в другую базу данных - нет процедур для переноса

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

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

Аргумент о том, что хранимые процедуры более эффективны, больше не выдерживает критики.текст ссылки

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

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

Рассмотрим запрос, который отлично выполняется при средней нагрузке, но как только он переходит в режим полной загрузки, ваш плохо оптимизированный запрос загружает систему и переводит ее в режим обхода.В большинстве SQL-серверов вы не единственное приложение / служба, которое его использует.Ваше заявление привело к тому, что у вашей двери появилась куча разгневанных людей.

Если у вас есть свои запросы в SPROCs, вы также позволяете своему дружественному администратору базы данных управлять ими и оптимизировать, не перекомпилируя и не ломая ваше приложение.Помните, что администраторы баз данных - эксперты в этой области, они знают, что делать, а чего не делать.Имеет смысл использовать их более обширные знания!

Редактировать:кто-то сказал, что перекомпиляция - это ленивая отговорка!давайте посмотрим, насколько ленивым вы себя чувствуете, когда вам приходится перекомпилировать и развернуть свое приложение на 1000 рабочих столов, и все потому, что администратор базы данных сказал вам, что ваш одноранговый запрос отнимает слишком много серверного времени!

кто-то сказал, что перекомпиляция - это ленивая отговорка!давайте посмотрим, насколько ленивым вы себя чувствуете, когда вам приходится перекомпилировать и развернуть свое приложение на 1000 рабочих столов, и все потому, что администратор базы данных сказал вам, что ваш одноранговый запрос отнимает слишком много серверного времени!

хорошая ли это системная архитектура, если вы позволяете подключать 1000 рабочих столов непосредственно к базе данных?

Здесь есть о чем подумать: Кому вообще нужны Хранимые процедуры?

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

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

Я использую ad-hoc только для запросов, которые динамически генерируются на основе пользовательского ввода.

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

Если вы используете специальные запросы, убедитесь, что они параметризованы

Параметризованный SQL или SPROC ... не имеет значения с точки зрения производительности...вы можете оптимизировать запросы к любому из них.

Для меня последним оставшимся преимуществом SPROC является то, что я могу отказаться от большого управления правами SQL, предоставив только свои права входа в систему для выполнения sprocs...если вы используете параметризованный SQL, логин в вашей строке подключения имеет намного больше прав (например, написание ЛЮБОГО оператора select в одной из таблиц, к которым у них тоже есть доступ).

Тем не менее, я по-прежнему предпочитаю Параметризованный SQL...

Я не нашел ни одного убедительного аргумента в пользу использования специальных запросов.Особенно те, которые перепутаны с вашим кодом на C # / Java / PHP.

Аргумент производительности sproc является спорным - 3 лучшие СУБД используют кэширование плана запросов и уже некоторое время используют его.Это было задокументировано...Или все еще 1995 год?

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

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

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

Этот гибридный подход упрощает управление разработчиками (возможно, мы в меньшинстве, поскольку моя команда достаточно умна, чтобы прочитать план запроса), а развертывание - это простая проверка из SVN.Кроме того, это упрощает переключение СУБД - просто замените файл ресурсов SQL (конечно, не так просто, как инструмент ORM, но при подключении к устаревшим системам или неподдерживаемой базе данных это работает)

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

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

@Черепаха:Я думаю, что ваше утверждение о том, что тот факт, что вам не нужно перекомпилировать ваше приложение для внесения изменений, делает хранимые процедуры лучшим вариантом, не имеет смысла.Могут быть причины предпочесть хранимые процедуры нерегламентированным запросам, но в отсутствие чего-либо еще убедительного проблема компиляции кажется скорее ленью, чем реальной причиной.

Мой опыт показывает, что 90% запросов и / или хранимых процедур вообще не следует писать (по крайней мере, вручную).

Доступ к данным должен быть сгенерирован каким-то образом автоматически.Вы можете решить, хотите ли вы статически генерировать процедуры во время компиляции или динамически во время выполнения, но когда вы хотите добавить столбец в таблицу (свойство объекта), вам следует изменить только один файл.

Я предпочитаю хранить все данные доступ логика в программном коде, в котором уровень доступа к данным выполняет прямые SQL-запросы.С другой стороны, данные Руководство логику я помещаю в базу данных в виде триггеров, хранимых процедур, пользовательских функций и еще много чего.Примером чего-то, что я считаю достойным использования в базе данных, является генерация данных - предположим, у нашего клиента есть имя и фамилия.Теперь пользовательскому интерфейсу требуется DisplayName, которое является производным от некоторой нетривиальной логики.Для этого поколения я создаю хранимую процедуру, которая затем выполняется триггером всякий раз, когда обновляется строка (или другие исходные данные).

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

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

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

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

В наши дни я думаю, что вам нужна очень веская причина для написания бизнес-приложения / информационной системы, которая не использует какой-либо картограф OR.

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

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

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

В моем проекте было 420 процедур, и у меня все работает нормально.Я работаю над этим проектом последние 3 года.

Поэтому используйте только процедуры для любой транзакции.

хорошая ли это системная архитектура, если вы разрешаете подключать 1000 рабочих столов напрямую к базе данных?

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top