Виконання функції


46

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

Одним із речей, які я хотів би зробити, є переміщення деякої логіки додатків у збережені процедури, тому я тут прошу DO-та і DON'Ts (найкращі практики) щодо використання функцій у PostgreSQL (9.0), зокрема щодо підводних ефектів.


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

Блоги Кріс Траверса багато про переваги використання збережених процедур, наприклад тут: ledgersmbdev.blogspot.de/2012/07/… і тут: ledgersmbdev.blogspot.de/2012/07/… просто прогляньте його блог, є багато цікавих статей на цю тему.
a_horse_with_no_name

Відповіді:


51

Строго кажучи, термін "збережені процедури" вказує на процедури SQL у Postgres, запроваджені разом із Postgres 11.

Є також функції , які роблять майже, але не зовсім те саме, і вони були там з самого початку.

Функції з LANGUAGE sql- це лише пакетні файли з простими командами SQL у обгортці функцій (і, отже, атомні, завжди виконуються всередині однієї транзакції), приймаючи параметри. Усі оператори у функції SQL плануються одразу , що тонко відрізняється від виконання одного оператора за іншим і може впливати на порядок прийняття блокування.

Щодо іншого, найзрілішою мовою є PL / pgSQL ( LANGUAGE plpgsql). Він працює добре і вдосконалювався з кожним випуском за останнє десятиліття, але найкраще служить клеєм для команд SQL. Він не призначений для важких обчислень (окрім команд SQL).

Функції PL / pgSQL виконують запити, як підготовлені оператори . Повторне використання кешованих планів запитів відрізає частину накладних витрат і робить їх трохи швидшими, ніж еквівалентні SQL-заяви, що може мати помітний ефект залежно від обставин. Також можуть виникнути побічні ефекти, як у цьому пов'язаному питанні:

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

Оскільки загальні плани виконання Postgres 9.2 все ще зберігаються в сесії, але, цитуючи посібник :

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

Ми отримуємо найкращі з обох світів більшу частину часу (за винятком деяких доданих накладних витрат) без використання (ab) використання EXECUTE. Докладніше в Що нового в PostgreSQL 9.2 у PostgreSQL Wiki .

Postgres 12 вводить додаткову змінну сервера,plan_cache_mode щоб змусити загальні або власні плани. Для особливих випадків користуйтеся обережно.

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

Уникайте вкладення складних функцій, особливо функцій таблиці ( RETURNING SETOF recordабо TABLE (...)). Функції - це чорні поля, що є бар'єрами оптимізації для планувальника запитів. Вони оптимізовані окремо, не в контексті зовнішнього запиту, що робить планування більш простим, але може призвести до менш, ніж ідеальних планів. Крім того, вартість та результат результатів функцій неможливо надійно прогнозувати.

Виняток з цього правила є прості функції SQL ( LANGUAGE sql), які можуть бути «вбудовуються» - якщо якісь - то попередні умови . Детальніше про те, як працює планувальник запитів, читайте в цій презентації Ніла Конвей (розширені матеріали).

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

Ось чому функції не є точно «збереженими процедурами» (навіть незважаючи на те, що цей термін використовується іноді, оманливо). Деякі команди типу VACUUM, CREATE INDEX CONCURRENTLYабо CREATE DATABASEне може працювати всередині блоку транзакції, тому вони не допускаються до функцій. (Ні в процедурах SQL, поки не в Postgres 11. Це може бути додано пізніше.)

Я написав тисячі функцій plpgsql протягом багатьох років.


2
@nhahtdh: "автоматична транзакція" не є технічним терміном. Це був просто важкий елегантний спосіб сказати .. що це зараз говорить після мого уточнення. Зовсім не автономна угода. "автономний" просто буває подібним словом.
Ервін Брандстеттер

4
Ваші відповіді, зібрані звідси, і тому можуть бути епічним посібником з найкращих практик PostGreSQL.
Давос

10

Деякі DO:

  • Використовуйте SQL як мову функції, коли це можливо, оскільки PG може вбудовувати заяви
  • Використовуйте IMMUTABLE / STABLE / VOLATILE правильно, оскільки PG може кешувати результати, якщо він незмінний або стабільний
  • Використовуйте правильно STRICT, оскільки PG може просто повернути нуль, якщо будь-який вхід є нульовим, а не виконувати функцію
  • Розгляньте PL / V8, коли ви не можете використовувати SQL як мову функції. Це я швидше, ніж PL / pgSQL в деяких ненаукових тестах, які я проводив
  • Використовуйте LISTEN / NOTIFY для більш тривалих процесів, які можуть статися поза трансакцією
  • Розглянемо, як використовувати функції для реалізації сторінки, тому що основана на ключових сторінках сторінка може бути швидшою, ніж на основі обмеження
  • Переконайтесь, що ви перевірили свої функції

Вперше я бачу твердження, що PL / V8 швидше, ніж PL / pgSQL. Чи є у вас якісь (опубліковані) цифри для цього?
a_horse_with_no_name

@a_horse_with_no_name ні, я ні. Як я вже говорив, я зробив кілька ненаукових тестів. Вони здебільшого мали логіку, а не доступ до даних. Я спробую зробити кілька повторюваних тестів на xmas і повторно розмістити тут.
Ніл Макгуйган

@a_horse_with_no_name ось швидкий п-брудний приклад для FizzBuzz plv8 vs plpgsql
Ніл

8

Взагалі кажучи, переміщення логіки програми в базу даних означатиме, що вона швидша - адже вона буде ближче до даних.

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

PL / pgSQL - найзріліший та найповніший з функцій вбудованих мов - але для продуктивності можна використовувати C (хоча це буде корисно лише для обчислювально-інтенсивних функцій)


7

Ви можете зробити дуже цікаві речі, використовуючи визначені користувачем функції (UDF) у postgresql. Наприклад, є десятки можливих мов, якими ви можете користуватися. Вбудовані в pl / sql та pl / pgsql є одночасно спроможними та надійними та використовують метод пісочниці, щоб утримати користувачів від чогось занадто небезпечного. UDF, написані на C, дають вам максимальну потужність та продуктивність, оскільки вони працюють у тому ж контексті, що і сама база даних. Однак, це як грати з вогнем, адже навіть невеликі помилки можуть спричинити величезні проблеми, коли збиваються вакцини або пошкоджуються дані. Обслуговувані мови pl, як-от pl / R, pl / ruby, pl / perl тощо, надають вам можливість писати як шари бази даних, так і програми на одних і тих же мовах. Це може бути зручно, оскільки це означає, що вам не потрібно вчити програміста Perl Java або pl / pgsql тощо, щоб писати UDF.

Нарешті, є мова pl / proxy . Ця мова UDF дозволяє запускати додаток на кількох десятках або більше серверів postgresql з метою масштабування. Він був розроблений добрими людьми в Skype і, в основному, дозволяє вирішити проблему горизонтального масштабування бідної людини. На диво також легко записати.

Тепер, що стосується виступу. Це сіра зона. Ви пишете додаток для однієї людини? Або на 1000? або за 1000000? Спосіб побудови програми та використання UDF буде залежати багато від того, як ви намагаєтеся масштабувати. Якщо ви пишете для тисяч і тисяч користувачів, то головне, що ви хочете зробити, - максимально зменшити навантаження на db. UDF, які зменшують кількість даних, що переміщуються та повертаються в базу даних, допоможуть зменшити навантаження на IO. Однак якщо вони почнуть збільшувати завантаження процесора, то це може бути проблемою. Взагалі, зниження навантаження вводу-виводу є першочерговим завданням, а переконання, що UDF є ефективними, щоб не перевантажувати ваші процесори - наступне.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.