Коли я повинен використовувати збережені процедури?


19

Якщо я маю всю свою бізнес-логіку в коді і використовую Entity Framework, то в яких ситуаціях (якщо такі є) я б краще перенести якусь бізнес-логіку на збережену процедуру, а не зберігати її в коді?

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

Якщо це має значення, я використовую MSSQL та Entity Framework.


Це ситуації, коли я раніше використовував збережені процедури:

  • Складний звіт, який запускав кілька хвилин (це була сторінка у веб-додатку). Я виявив, що можу написати SQL, який був набагато ефективнішим (запускаючи лише секунди), ніж те, що LINQ надав.
  • Веб-додаток, необхідний для читання та запису до кількох таблиць окремої бази даних, що містив безліч іншої, конфіденційної інформації, яка не стосується програми. Замість того, щоб надати їй доступ до всього, я використав збережену процедуру, яка виконує лише те, що потрібно, і повертає лише обмежену інформацію. Потім веб-додаток може отримати доступ лише до цієї збереженої процедури, без доступу до таблиць тощо.

Інші повідомлення, які я переглянув, перш ніж задавати це питання:


4
Обидві ваші ситуації є цілком законними причинами написання збережених процедур. Ви запитуєте, чому вони законні?
Роберт Харві

@RobertHarvey Я переконався, що вони є законними, і шукав інші сценарії чи причини, чому ви можете зробити виняток і написати збережену процедуру, а не зберігати її в коді.
Емі Барретт

Ви зробите виняток і напишіть збережену процедуру, коли визначите, що вона вирішує проблему краще, ніж інші методи, доступні вам, саме це ви зробили.
Роберт Харві

Відповіді:


10

У вас вже є пара ідеально хороших сценаріїв.

Є й багато інших причин. EF дійсно хороший у CRUD та у досить прямому звіті. Однак іноді EF не є ідеальним інструментом. Деякі інші причини (сценарії) для розгляду використання збережених процедур у поєднанні з Entity Framework включають:

  • У вас є складні одиниці роботи, можливо, що включають багато таблиць, які неможливо легко зафіксувати в транзакції, використовуючи функції EF.
  • Ваша база даних не грає добре з EF, оскільки вона не може скористатися деклараційною референтною цілісністю (обмеження зовнішніх ключів). Зазвичай це поганий сценарій, коли можна опинитися, але іноді є відповідні сценарії, наприклад, бази даних, що використовуються для процесів ETL.
  • Вам потрібно працювати з даними, які перетинають межі сервера з пов'язаними серверами.
  • У вас дуже складні сценарії пошуку даних, де SQL для "голого металу" потрібен для забезпечення достатньої продуктивності. Наприклад, у вас є складні приєднання, для яких потрібні підказки для запитів, щоб добре працювати у вашій конкретній ситуації.
  • У вашій програмі немає повних дозволів CRUD на столі, але вашій програмі можна дозволити працювати в контексті безпеки, якому довіряє ваш сервер (наприклад, ідентифікація програми, а не ідентифікація користувача). Це може виникнути в ситуаціях, коли DBA обмежують доступ таблиці до збережених програм лише тому, що це дає їм більш детальний контроль над тим, хто що може робити.

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


Дякую, Джоел, ти згадав кілька інших сценаріїв, про які я не думав.
Емі Барретт

Приємна відповідь. Однак мені цікаво, якщо у вас багато користувачів підключені до бази даних і виконують складні запити чи зберігаються процедури, чи не закінчите ви навантажувати багато серверів бази даних?
Ріпал Баро

1
@RipalBarot Немає сумніву, що чим більше відбувається робота з навантаженням (більше користувачів, складніші запити), тим більше буде вимог до вашого сервера баз даних. Однак слід пам’ятати, що використання збережених процедур, а не ORM, таких як Entity Framework, часто може зменшити навантаження (порівняно), оскільки збережені процедури можуть мати попередньо складені плани запитів. Коли запит надходить від ORM, СУБД часто доводиться починати з розробки способу обробки запиту. Коли ви викликаєте еквівалентну збережену процедуру, база даних вже знає, як її ефективно виконати.
Джоел Браун

2

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

Якщо це має значення, я використовую MSSQL та Entity Framework.

Мої знання з EF є обмеженими, але, наскільки я бачу, EF є ( просто ) ORM, як і будь-який інший; і на щастя здатний використовувати необроблений SQL .

Якщо я візьму ваші два основні моменти:

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

Під час складання звіту LINQ / EF не вистачало. І як ви помітили, це було SQLнабагато швидше, ніж використання ORM. Але чи говорить це на користь збережених процедур або лише проти використання ORM для всього?

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

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

Тут те ж саме: простий рядок з'єднання, і UPDATE і ваша проблема. Цю проблему можна вирішити навіть за допомогою ORM : просто скористайтеся веб-сервісом напроти інших БД, і буде досягнута така ж компартементалізація / ізоляція .

Тож тут нічого не бачити.

Дивлячись на деякі моменти:

У вас є складні одиниці роботи, можливо, що включають багато таблиць, які неможливо легко зафіксувати в транзакції, використовуючи функції EF.

Але SQLможе це зробити. Тут немає жодної магії .

Ваша база даних не грає добре з EF

Знову ж таки: використовуйте EF, коли це доречно

Вам потрібно працювати з даними, які перетинають межі сервера з пов'язаними серверами

Я не бачу, як допомагають збережені процедури. Тому я не бачу переваги збережених процедур; але, можливо, хтось проливає на це трохи світла.

У вас дуже складні сценарії пошуку даних, де SQL для "голого металу" потрібен для забезпечення достатньої продуктивності

Знову ж таки: "Межі EF ".

У вашій програмі немає повних дозволів CRUD на столі, але вашій програмі можна дозволити запускатись у контексті безпеки, якому довіряє ваш сервер.

Добре. Я йду з можливо .

Поки що лише половина балів була зроблена на користь збережених процедур.


Можливо, є міркування щодо ефективності, які говорять на користь збережених процедур.

1) Зберігання запитів має перевагу від простого виклику до збереженої процедури, що інкапсулює складність. Оскільки планувальник запитів знає запит, оптимізувати його "простіше". Але заощадження виконуються за допомогою поточного складного планувальника запитів _minimal.

Крім того, навіть якщо є невелика вартість використання спеціальних запитів, якщо ваші дані добре структуровані та ретельно індексовані, база даних є лише вузьким місцем вашої програми. Тож навіть якщо є невелика дельта, це нехтувати врахуванням інших факторів.

2) Тим не менш, це було аргументовано для зберігання складних запитів у БД. Слід розглянути дві речі:

а) складні запити масово використовують інфраструктуру БД, що збільшує час отримання нових запитів. Не можна паралельно запускати багато дорогих запитів . Це не говорить ні про, ні протипоказані процедури, але проти складних запитів.

б) Якщо запит у будь-який час займає час, чому б турбуватися з невеликою швидкістю, виграє збережена процедура.

тл; д-р

Ніщо не говорить прямо проти збережених процедур. Тому використовувати збережені процедури нормально - якщо це робить вас щасливими.

Але з іншого боку: я не міг уявити собі належний випадок використання, який однозначно говорить про.

Коли я повинен використовувати збережені процедури?

Правильна відповідь: Коли завгодно . Але є й інші варіанти.


0

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

Суб'єктні рамки виконують гідну роботу, а результативність буде близькою або рівною використанню збережених процедур. Ви вибрали структуру сутності, тому що не хотіли стосуватися SQL і дозволили фреймворку генерувати SQL для вас.

Але може бути певний випадок, коли рамки сутності недостатні і не можуть задовольнити ваші потреби. У цьому випадку можна написати SQL вручну, використовуючи збережену процедуру або параметризований запит, а потім використовувати структуру сутності, щоб безпосередньо викликати цю збережену процедуру / оператор SQL.

Отже, я б нічого не переміщував до збереженої процедури, якщо рамки, які використовуються, не можуть відповідати вимозі.

Я думаю, що найгірше, що може трапитися, - це те, що можна скористатися рамкою сутності, а потім записати всі збережені процедури. Тепер у кожного є додатковий шар, який не додає значення.


100% згоден з останнім абзацом
Еван

0

Наявність технічної потреби - це не найімовірніший вибір. Програмісти віддають перевагу своїм інструментам і зазвичай більше адаптуються у вирішенні своїх проблем. Виключення стане логікою в проростку. Слід враховувати технічну заборгованість та майбутні диски, які потребують часу для роботи за винятком. У вашому конкретному RDBMS може бути підвищення продуктивності, який просто простіше реалізувати в паростці або, можливо, навіть інший db-об'єкт, як індексований вигляд.

Будуть випадки, коли вам потрібні дані з бази даних, і ви просто не можете їх отримати з коду програми. У багатьох великих ситуаціях з компанією та підприємством бізнес-потреби можуть перевищувати розуміння відділу ІТ. Компанії купують і продають, і їх заявки приходять і їдуть разом з ними. Регулюючі агенції та банки не хвилюються, якщо ви не зможете створити свій високомасштабний і красиво кодований додаток. Вони можуть ускладнити життя бізнесу, тому вам доведеться це зробити.

Я зіткнувся з ситуаціями, коли сторонні програми чи інструменти для написання звітів не дозволяють вам отримати свій код. Немає відкритого коду, немає API, немає веб-інтерфейсу та жодних послуг. Єдине, що вони мають - це власний спеціальний інструмент для написання звітів, який працює лише з об'єктами бази даних: таблицями, представленнями, відростками, визначеними користувачем функціями тощо.

Якщо у вас є DBA, який дуже добре пише написані процедури, ви можете використовувати цей талант у деяких ситуаціях. Можливо, ви захочете створити резервну копію свого додатка, оскільки ви збираєтеся зробити істотну зміну даних, то чому б не використовувати те, що використовує ваш dba?

Деякі спеціальні запити просто простіше написати програму, поки ви не отримаєте всю функціональність у вашому додатку. Ми ненавидимо це. Ми відштовхуємось, але шоу має продовжуватися.


0

Я б настійно радив не розміщувати будь-яку ділову логіку у збереженій процедурі. Однак може виникнути випадок (ви перерахували два прекрасних приклади), коли бажано розмістити там логіку доступу до даних .

Взагалі кажучи, якщо ви відчуваєте спокусу використовувати SP, це знак (запах коду), який натякає на те, що ваша модель даних недостатньо відповідає її потребам.

Редагувати: Коли розробники запитують мене про логіку доступу до бізнесу / даних, я кажу, що бізнес-логіка полягає в тому, як дані поводяться та взаємодіють, а логіка доступу до даних - це спосіб зберігання та отримання даних.

Для прикладу: у вашій моделі домену у вас можуть бути об'єкти "Студент" і "Вчитель", обидва походять від "Особи". (Не кажучи, що це є кращим, лише приклад). Це може зберігатися у реляційних базах даних у вигляді однієї, двох або трьох таблиць. Вибір залежить від кількості властивостей, якими вони поділяються, та вимог щодо продуктивності читання / запису.

У бізнес-логіці не має значення, як вони зберігаються. (або взагалі вони проживають в RDB). Логіка доступу до даних полягає в тому, як вони фізично зберігаються.

Отже, стосовно початкового запитання: Якщо збережена процедура робить зберігання та отримання даних більш ефективними (або більш надійними), у вас є випадок. Якщо збережена процедура є лише накладенням правила, яке я дійсне, незалежно від того, як зберігаються дані, уникайте цього. Це робить ваш код більш щільно з'єднаним з базою даних.


2
Як би ви визначили бізнес-логіку та логіку доступу до даних ?
Емі Барретт


@RobertHarvey Дякую за посилання. Чи рівень доступу до даних збігається з логікою доступу до даних? Я запитую, оскільки, мабуть, не так багато фактичної логіки, що бере участь у рівні доступу до даних - просто прості операції з CRUD.
Емі Барретт

@AmyBarrett: Ну, іноді ви пишете власні методи у шарі доступу до даних, тому це не завжди CRUD.
Роберт Харві

@RobertHarvey Невже ці користувацькі методи не належать до рівня бізнес-логіки?
Емі Барретт

-4

Я думаю, що тут є три питання.

  1. Логіка бізнесу в SQL погана. Навіть якщо він працює швидше індивідуально, він не масштабує.

  2. Традиційно SPROC завжди слід використовувати для доступу до всіх даних як рівень абстракції. Увімкнення DBA вводити зміни продуктивності або інші зміни рівня даних без впливу на споживачі програми.

  3. EF не грає добре із зірочками. Ви втратите багато "хороших" функцій та підвищення продуктивності, відключившись від динамічної генерації запитів Linq.

Тож моя загальна порада була б

  • Використовуйте SPROC для всіх SQL запитів,

  • Не вкладайте в них ділову логіку чи якісь петлі,

  • Не використовуйте EF.


Оскільки всі SQL запускаються на db-сервері, ви можете масштабувати лише додаткові dbs, а не додаткові вікна обчислення.
Еван

1
Я бачу. Але тоді точка №1 суто стосується компромісу між двома питаннями ефективності. Але будуть випадки, коли рішення SQL - це явна перемога з точки зору продуктивності, тому я не бачу, як це можна вважати категорично "поганим" на цій основі.

1
скажімо, у вас є веб-сервіс, який робить розрахунок. Ви можете це зробити в коді або в sql. скажімо, sql швидше в головному тесті одного обчислення. Але коли сервіс накреслений процесором, його дуже дешево і легко додати друге, третє, четверте .. вікно, на якому працює веб-сервіс, але важко і дорого додати другу реплікувану базу даних
Ewan

1
це приклад одного конкретного сценарію, коли SQL може бути поганим дизайном через масштабованість. Але навіть тоді не зрозуміло: це залежить від очікуваної кількості користувачів, відносної вартості виконання розрахунку в базі даних порівняно з зовнішньою і так далі. Звичайно, у деяких випадках ви праві, я просто не думаю, що це універсальне правило.

3
Це погана порада в цілому. Існує безліч варіантів доступу до даних, які мають переваги перед ручним кодуванням збережених процедур і працюють так само добре. Ви можете запустити проростки безпосередньо з EF; насправді ви можете запустити будь-який запит sql безпосередньо з EF. Деяка бізнес-логіка працює краще на сервері баз даних, тому ви не можете категорично заявити, що це заборонено. Об'єктні реляційні картографи - це 80% інструмент; вони ніколи не мали на меті повністю замінити ваші процеси доступу до даних. Використовуйте збережені процедури для того, для чого вони призначені: 20%, для яких ORM не справляється.
Роберт Харві
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.