Являются ли хранимые процедуры в целом более эффективными, чем встроенные инструкции в современных СУБД?[дубликат]

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

  •  09-06-2019
  •  | 
  •  

Вопрос

На этот вопрос уже есть ответ здесь:

Общепринятое мнение гласит, что хранимые процедуры всегда быстрее.Итак, поскольку они всегда быстрее, используйте их ВСЕ ВРЕМЯ.

Я почти уверен, что это основано на каком-то историческом контексте, где это когда-то имело место.Я не утверждаю, что хранимые процедуры не нужны, но я хочу знать, в каких случаях хранимые процедуры необходимы в современных базах данных, таких как MySQL, SQL Server, Oracle или <Вставьте_вашу_БД_здесь>.Является ли излишним иметь ВСЕ доступ через хранимые процедуры?

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

Решение

ПРИМЕЧАНИЕ что это общий взгляд на сохраненные процедуры, не регулируемые для определенного СУБД.Некоторые СУБД (и даже разные версии одинаковых СУБД!) Могут действовать противоречат этому, поэтому вам захочется дважды проверить с помощью вашего целевого СУБД, прежде чем предположить, что все это все еще сохранится.

Я работаю администратором баз данных Sybase ASE, MySQL и SQL Server уже почти десять лет (а также занимаюсь разработкой приложений на C, PHP, PL/SQL, C#.NET и Ruby).Итак, у меня нет особых интересов в этой (иногда) священной войне.

Исторический выигрыш в производительности хранимых процедур обычно заключался в следующем (в произвольном порядке):

  • Предварительно проанализированный SQL
  • Предварительно созданный план выполнения запроса
  • Снижение задержки в сети
  • Потенциальные преимущества кэша

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

Все еще преимущество? Совсем не заметно на современном процессоре, но если вы отправляете один SQL-оператор ОЧЕНЬ большого размера одиннадцать миллиардов раз в секунду, накладные расходы на синтаксический анализ могут увеличиться.

Предварительно созданный план выполнения запроса.Если у вас много JOIN, перестановки могут стать совершенно неуправляемыми (современные оптимизаторы имеют ограничения и ограничения по соображениям производительности).Нередко очень сложный SQL имеет четкие, измеримые (я видел, как сложный запрос занимал более 10 секунд только для создания плана, прежде чем мы настроили СУБД) задержки из-за того, что оптимизатор пытается определить «ближайший лучший» «План выполнения.Хранимые процедуры, как правило, сохраняют это в памяти, чтобы вы могли избежать этих накладных расходов.

Все еще преимущество? Большинство СУБД (последние выпуски) кэшируют планы запросов для ИНДИВИДУАЛЬНЫХ операторов SQL, что значительно снижает разницу в производительности между хранимыми процессами и специальным SQL-запросом.Есть некоторые предостережения и случаи, когда это не так, поэтому вам необходимо протестировать вашу целевую СУБД.

Кроме того, все больше и больше СУБД позволяют предоставлять планы путей оптимизатора (абстрактные планы запросов), чтобы значительно сократить время оптимизации (как для специального SQL, так и для хранимой процедуры!!).

ПРЕДУПРЕЖДЕНИЕ Кэшированные планы запросов не являются панацеей производительности.Иногда создаваемый план запроса оказывается неоптимальным.Например, если вы отправите SELECT * FROM table WHERE id BETWEEN 1 AND 99999999, СУБД может выбрать полное сканирование вместо индексного сканирования, потому что вы захватываете каждую строку в таблице (так что скажи по статистике).Если это кэшированная версия, то вы можете получить плохую производительность, когда позже отправите SELECT * FROM table WHERE id BETWEEN 1 AND 2.Причина, лежащая в основе этого, выходит за рамки этой публикации, но для дальнейшего чтения смотрите: http://www.microsoft.com/technet/prodtechnol/sql/2005/frcqupln.mspxи http://msdn.microsoft.com/en-us/library/ms181055.aspxи http://www.simple-talk.com/sql/ Performance/execution-plan-basics/

«Таким образом, они определили, что предоставление чего -либо, кроме общих значений, когда выполнялось компиляция или перекомпиляция, приводило к составлению оптимизатора и кэшированию плана запроса для этого конкретного значения.Тем не менее, когда этот план запроса был повторно использован для последующих выполнений того же запроса для общих значений («M», «r» или «t»), он привел к неоптимальной производительности.Эта неоптимальная проблема производительности существовала до тех пор, пока запрос не был перекомпилирован.На этом этапе, основываясь на предоставленном значении параметра @P1, запрос может или не может иметь проблему производительности ».

Снижение задержки в сетиА) Если вы запускаете один и тот же SQL снова и снова - и SQL занимает много КБ кода - замена его простым "exec foobar" может действительно привести к увеличению суммы.Б) Сохраненные процедуры можно использовать для перемещения процедурного кода в СУБД.Это позволяет избежать пересылки больших объемов данных клиенту только для того, чтобы он отправил обратно небольшую часть информации (или вообще ничего!).Аналогично выполнению JOIN в СУБД vs.в вашем коде (всеми любимый WTF!)

Все еще преимущество?А) Современный Ethernet 1 Гб (и 10 Гб и выше!) действительно делает это незначительным.Б) Зависит от того, насколько загружена ваша сеть — зачем без веской причины перебрасывать туда-сюда несколько мегабайт данных?

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

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

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

Параметризованный/подготовленный SQL
Это своего рода нечто среднее между хранимыми процедурами и специальным SQL. Они представляют собой встроенные операторы SQL на основном языке, который использует «параметры» для значений запроса, например:

SELECT .. FROM yourtable WHERE foo = ? AND bar = ?

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

Специальный SQLПросто откройте окно консоли вашей СУБД и введите оператор SQL.В прошлом это были «наихудшие» результаты (в среднем), поскольку в СУБД не было возможности предварительно оптимизировать запросы, как в методе параметризованной/хранимой процедуры.

Все еще недостаток?Не обязательно.Большинство СУБД имеют возможность «абстрагировать» специальный SQL в параметризованные версии, тем самым более или менее сводя на нет разницу между ними.Некоторые делают это неявно или должны быть включены с помощью настройки команды (сервер SQL: http://msdn.microsoft.com/en-us/library/ms175037.aspx , Оракул: http://www.praetoriate.com/oracle_tips_cursor_sharing.htm).

Уроки выучены?Закон Мура продолжает действовать, и оптимизаторы СУБД с каждым выпуском становятся все более совершенными.Конечно, вы можете поместить любую глупую инструкцию SQL в хранимую процедуру, но знайте, что программисты, работающие над оптимизаторами, очень умны и постоянно ищут способы повышения производительности.В конце концов (если это еще не произошло) производительность специального SQL станет неотличима (в среднем!) от производительности хранимых процедур, поэтому любой вид массивный Использование хранимой процедуры ** исключительно из соображений производительности** для меня звучит как преждевременная оптимизация.

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

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

Причины использования хранимых процедур:

  • Уменьшите сетевой трафик -- вам нужно отправить оператор SQL по сети.С помощью процедур SQL вы можете выполнять SQL в пакетном режиме, что также более эффективно.
  • План запроса кеширования -- при первом выполнении процедуры SQL Server создает план выполнения, который кэшируется для повторного использования.Это особенно эффективно для часто выполняемых небольших запросов.
  • Возможность использования выходных параметров -- если вы отправляете встроенный SQL, который возвращает одну строку, вы можете получить обратно только набор записей.С помощью процедур вы можете получить их обратно в качестве выходных параметров, что значительно быстрее.
  • Разрешения -- когда вы отправляете встроенный SQL, вы должны предоставить пользователю разрешения на доступ к таблицам (таблицам), что предоставляет гораздо больший доступ, чем просто разрешение на выполнение процедуры.
  • Разделение логики -- удалить код, генерирующий SQL, и разделить его в базе данных.
  • Возможность редактирования без перекомпиляции. - это может быть спорным.Вы можете редактировать SQL в процедуре без необходимости перекомпиляции приложения.
  • Найдите, где используется таблица -- с помощью процедур, если вы хотите найти все операторы SQL, ссылающиеся на определенную таблицу, вы можете экспортировать код процедуры и выполнить поиск по ней.Это гораздо проще, чем пытаться найти его в коде.
  • Оптимизация -- Администратору базы данных легче оптимизировать SQL и настраивать базу данных при использовании процедур.Легче найти недостающие индексы и тому подобное.
  • Атаки с использованием SQL-инъекций -- правильно написанный встроенный SQL может защитить от атак, но процедуры лучше подходят для этой защиты.

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

Это дебаты, которые продолжаются и продолжаются (например, здесь).

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

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

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

Однако чистая производительность — не единственный критерий.Такие аспекты, как безопасность и управление конфигурацией, обычно не менее важны.

Редактировать:Хотя статья Франса Боумы действительно многословна, она совершенно упускает суть вопроса безопасности.Тот факт, что ему 5 лет, также не повышает его актуальности.

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

Обратите внимание, что параметризованный запрос — это не то же самое, что специальный sql.

Основная причина, по которой я по-прежнему отдаю предпочтение хранимым процедурам сегодня, больше связана с безопасностью.Если вы используете хранимые процедуры исключительно, вы можете отключить разрешения INSERT, SELECT, UPDATE, DELETE, ALTER, DROP, CREATE и т. д. для пользователя вашего приложения, оставив ему только EXECUTE.

Это обеспечивает небольшую дополнительную защиту от 2-й порядок SQL-инъекция.Параметризованные запросы защищают только от 1-й заказ инъекция.

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

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

  2. Хранимые процедуры автоматически используют переменные связывания.Разработчики приложений часто избегают связывания переменных, поскольку они кажутся ненужным кодом и не приносят особой пользы в небольших тестовых системах.В дальнейшем отказ от использования переменных связывания может снизить производительность РСУБД.

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

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

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

Единственная тема, о которой еще никто не упомянул в качестве преимущества хранимых процедур, — это безопасность.Если вы создаете приложение исключительно с доступом к данным через хранимые процедуры, вы можете заблокировать базу данных, чтобы ЕДИНСТВЕННЫЙ доступ осуществлялся через эти хранимые процедуры.Таким образом, даже если кто-то получит идентификатор и пароль базы данных, он будет ограничен в том, что он может видеть или делать с этой базой данных.

В 2007 году я участвовал в проекте, где мы использовали MS SQL Server через ORM.У нас было две большие, постоянно растущие таблицы, загрузка которых на SQL Server занимала до 7–8 секунд.После создания двух больших хранимых процедур SQL и их оптимизации с помощью планировщика запросов время загрузки каждой БД сократилось до менее 20 миллисекунд, поэтому очевидно, что использование хранимых процедур SQL по-прежнему остается эффективным.

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

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

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

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

Я предпочитаю использовать SP, когда это имеет смысл.В любом случае в SQL Server SP не имеет преимущества в производительности по сравнению с параметризованным запросом.

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

Так что чувства клиента в данном случае превосходят все остальные аргументы.

Для меня одним из преимуществ хранимых процедур является независимость от основного языка:вы можете переключиться с C, Python, PHP или любого другого приложения на другой язык программирования, не переписывая свой код.Кроме того, некоторые функции, такие как массовые операции, действительно повышают производительность и недоступны (совсем?) на основных языках.

Прочтите Франса Боума. отличный пост (если немного предвзято) по этому поводу.

Все, о чем я могу говорить, это SQL-сервер.На этой платформе хранимые процедуры прекрасны, потому что сервер хранит план выполнения, что в большинстве случаев немного повышает производительность.Я говорю «в большинстве случаев», потому что, если у SP очень разные пути выполнения, вы можете получить неоптимальную производительность.Однако даже в этих случаях разумный рефакторинг SP может ускорить процесс.

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

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

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

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

Я не знаю, что они быстрее.Мне нравится использовать ORM для доступа к данным (чтобы не изобретать велосипед), но я понимаю, что это не всегда жизнеспособный вариант.

У Франса Бумы есть хорошая статья на эту тему: http://weblogs.asp.net/fbouma/archive/2003/11/18/38178.aspx

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

Обычно я часто вызываю код как хранимую процедуру или как объект SqlCommand (.NET) и выполняю столько раз, сколько необходимо.

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

ИМХО...

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

Операции чтения могут быть предоставлены приложению, чтобы они могли объединять только те таблицы/столбцы, которые им нужны.

Хранимые процедуры также можно использовать вместо параметризованных запросов (или специальных запросов) для получения некоторых других преимуществ:

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

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

кэширование - MS-SQL не обрабатывает их по-другому, начиная с MS-SQL 2000, возможно, было 7, но я не помню.

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

Разделение. Люди могут задаться вопросом, почему вы выносите бизнес-логику за пределы среднего уровня.Кроме того, если вы хотите отделить код обработки данных, есть способы сделать это, не помещая его в базу данных.

Возможность редактирования. О чем вам придется беспокоиться без тестирования и контроля версий?Также проблема только с клиентом/сервером, в веб-мире проблем нет.

Найдите таблицу. Только если вы сможете идентифицировать SP, который ее использует, для поиска придется использовать инструменты системы контроля версий, агента Ransack или Visual Studio.

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

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

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