Найти в Дзене
Уйти в АйТи

Зачем функции (хранимые процедуры) в PostgreSQL? Практики, опыт

Оглавление

Здравствуйте, уважаемые подписчики и гости канала!

Зачем это все?

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

Сразу скажу, что у меня есть еще одна статья на тему функций, но там про триггерные процедуры в БД, т.е. типа хуков на INSERT, UPDATE и пр. Если ваш вопрос скорее про них, то вам надо перейти по этой ссылке.

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

Почему же так важно бывает обрабатывать данные именно в БД? Тут простой ответ, возможно, вас огорчит - просто для производительности. Возьмем обычное не супер энтерпраиз приложение без 1TB данных (хотя и на нем все будет норм). Не круто, когда у вас приложение сперва выбирает 100 строк кода из БД, а потом через вашу любимую ORM отправляет это обратно в БД для другой выборки. Хорошо, если БД все это сделает одним запросом так как накладных расходов просто будет сильно меньше.

А функции нужны как обычно для инкапсуляции логики, когда вам надо использовать одно и тоже во многих запросах. Например какая-нить функция, которая возвращает доступных клиентов для указанного id пользователя. Вместо того, чтобы кидать базе огромный запрос, возможно с join-ами и union-ами (как только менеджеры войдут во вкус с ACL так оно и будет), вы можете просто убрать запрос в хранимую процедуру (функцию) и в дальнейших запросах в БД использовать ее.

Функции можно делать:

- просто из SQL запроса, но на практике это редко надо

- что-то изотерическое и у меня из опыта не очень стабильно работающее типа plpythonu, plv8 . Стоит отметить, что эти расширения во всяком случае раньше считались unsafe и приводили к крашу БД в случае не очень достойной обработки исключений в коде функции. При этом plpythonu меня во многом спас в свое время. На нем даже в API ходили и потом в таблицу сразу сохраняли, но в целом это продержалось 1-2 года. Не рекомендую так делать, если есть другие варианты.

  • и, наконец, всеми любимый plpgsql. Вот тут хайли рекомменд 🤌 Есть нормальные условия, переменные и пр. В купе с работой с json-ом, вообще оч круто можно завертеть.

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

Подборка видео всех видео по PG - https://dzen.ru/suite/37b67ffa-176d-493a-b1a8-4762f79e3753

Пример использования

Пример покажу попроще с SQL. Про plpgsql стоит почитать самому тут.

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

Пример функции с SQL синтаксисом
Пример функции с SQL синтаксисом

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

Пример вызова функции с SQL синтаксисом
Пример вызова функции с SQL синтаксисом

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

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

Транзакции в хранимых процедурах

Функции всегда работают в транзакции, запущенного запроса! Однако есть варианты с блоком EXCEPTION. Подробнее можно почитать тут.

Кстати, в PostgreSQL есть много прикольных фишек и кроме json, например у меня есть статейка про триггерные функции.

Минусы

Как обычно, куда же без них )

1. Добавление, удаление, изменение функции (CREATE, ALTER) делает с блокировкой и, если функция очень часто используется в нагруженной БД то у вас будут проблемки с изменением функции.

2. Вам нужен какой-то отдельный механизм патчей, так как классические будут неудобными потому, что в git вы будете постоянно видеть новый патч со свежей функцией, а хотелось бы видеть diff.

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

4. Не все принимают такую парадигму, поэтому я и писал, что с этим делом надо очень очень аккуратно.

Заключение

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

---

А на этом всё, спасибо за внимание!

Подписывайтесь на канал, ставьте лайки, оставляйте комментарии - это помогает продвижению в Дзене.

Кроме этого:

Подписывайтесь в Telegram: https://t.me/lets_goto_it

#postgresql #functions #pg #plpgsql #бд #функциибд