В чем достоинства и недостатки процедурного подхода в базах данных по сравнению с запросами из кода
Что проверяют
Понимаете ли вы, где в системе должна жить бизнес-логика и чем платят за перенос её в базу. Следом часто спрашивают, как вы вызывали процедуры из Java и как их версионировать и тестировать.
Как отвечать
Сильные стороны процедур:
- меньше сетевых обходов: обработка набора строк идёт рядом с данными. Цикл «прочитать тысячу строк, посчитать, записать обратно» становится одним вызовом;
- атомарность: несколько операций в одной транзакции без участия приложения;
- права: приложению выдают только
EXECUTEна процедуру без доступа к таблицам; - общая логика: если в базу ходят несколько систем на разных языках.
Слабые стороны:
- привязка к СУБД: PL/pgSQL, PL/SQL и T-SQL несовместимы, смена базы превращается в переписывание;
- выкладка и версии: процедуры выкатывают миграциями Flyway или Liquibase синхронно с кодом;
- тесты и отладка: нужна настоящая база, например в Testcontainers, а отладчик и логирование беднее, чем в IDE;
- масштабирование: приложение легко размножить, базу нет, и её CPU самый дорогой ресурс системы.
Из Java процедуры вызывают через CallableStatement с синтаксисом {call name(?, ?)}, в Spring через SimpleJdbcCall, в JPA через StoredProcedureQuery или @Procedure в Spring Data. На практике чаще выбирают середину: логика в сервисе, а в базе остаются тяжёлые пакетные операции.
Где спотыкаются
Утверждают, что запросы из кода уязвимее к SQL-инъекциям. Защищает PreparedStatement с параметрами, а процедура с динамическим SQL через EXECUTE уязвима точно так же.
Повторяют, что процедуры быстрее, потому что «прекомпилированы». Современные СУБД кешируют планы и для параметризованных запросов, реальный выигрыш даёт сокращение обходов по сети.
Не отличают функцию от процедуры в PostgreSQL: CREATE PROCEDURE появился в версии 11 и, в отличие от функции, может делать COMMIT внутри.