metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2012-02-10 08:28 am

Бизнес-логика в хранимых процедурах

Я вот думаю: следует ли избавляться от сабжевых процедур, заменяя их на закат солнца вручную в виде кода на обычных языках программирования?
У меня 99% разнообразных отчетов реализовано на Firebird или в виде sql-запросов на пару страниц или в виде selectable хранимых процедур, тоже на пару страниц.
Все бы это хорошо, но деплоймент этого дела огорчает, язык хранимых процедур - более чем полная убогость, т.е. уровня типа "турбо-паскаль интегрированный с sql".
И главное ж, хрен чем заменишь - все остальное закат солнца вручную. В обычном случае - адовы ORM типа Entity Framework и LINQ поверх них. В условно нормальном - руби и ActiveRecord, с метапрограммированием, но у него адаптер к Firebird, по моему, несуществующий. Возможно, питон еще, у него тоже метапрограммирование имеется и kinterbasedb вроде живой.
Т.е. если по хорошему - то нужно что-то вроде LINQ, но чтобы схему БД видел сам, без импорта схемы в 100500 файлов.

PS: не успел дописать: Одна из нездоровых идей - написать транслятор из гуманного DSL с функциональщиной и школьницами с Ph.D. in CS в язык хранимых процедур.

[identity profile] gds.livejournal.com 2012-02-10 12:01 pm (UTC)(link)
тоже стродаю от подобного дела. Тем не менее,
1. реюзабельные запросы -- это views. (CTE -- это же в пределах одного запроса, не?)
2. для текущей задачи мне нужно минимальное время отклика, а это значит, что логику надо свести до уровня "вызвали хранимку -- получили полный ответ на свой вопрос", поэтому стродания оправданы, будет архитектура, которая не вносит тормозов на этапе "получить от БД что-либо".
3. отдавать всё наружу (в курсорах, например) и обрабатывать client-side -- гарантии лишнего трафика, увеличенного времени отклика и практически гарантия велосипедописательства на тему оптимизации запросов (либо ручное выстраивание планов на каждый сколько-нибудь нетривиальный запрос, что скучно).
4. идея про dsl -- вполне разумная, только сотона в деталях, как обычно. Я бы не смог сдизайнить функциональный dsl, удобный и эффективный для трансляции в plpgsql какой-нибудь.
Да и проверил недавно у постгреса размер стека на рекурсивные вызовы, порядка 1000 для функций, берущих простой int. То есть, компилировать надо во что-то очень императивное.
Ну и конкретно функциональщина там не особо нужна обычно, разве что если поставить цель заменить sql. Но это тоже нехорошо, так как sql весьма таки непростой язык, и есть подозрение, что при обнаружении проблем с эффективностью этих хранимок придётся анализировать сгенерированный код, а то и переписывать его под нужды оптимизатора.
А вот хотя бы нормальная типизация -- уже было бы хорошо.

И ещё вариант, но базоспецифичный: постгрес (и firebird, вроде; и оракл) умеют линковать нативный код, предоставляя ему возможность смотреть в данные, выполнять sql, возвращать результаты. То есть, вполне можно написать библиотеку для любимого языка программирования, которая будет предоставлять хранимые процедуры.

[identity profile] gsbelarus.livejournal.com 2012-02-10 01:02 pm (UTC)(link)
"постгрес (и firebird, вроде; и оракл) умеют линковать нативный код"

firebird только с версии 3.0, которая пока еще только в альфе
Edited 2012-02-10 13:02 (UTC)

[identity profile] gds.livejournal.com 2012-02-10 01:58 pm (UTC)(link)
а я чётко помню другое, и не поленился проверить. http://www.firebirdsql.org/en/writing-udfs-in-delphi-for-interbase-firebird/ -- это ведь оно и есть.

[identity profile] metaclass.livejournal.com 2012-02-10 10:17 pm (UTC)(link)
Эта штука не очень удобна. В них даже курсор толком не передашь.

[identity profile] gds.livejournal.com 2012-02-10 11:49 pm (UTC)(link)
вроде бы, если брать модель "писать хранимые процедуры на внешнем языке и линковать их динамически", то не очень-то и нужно передавать из/в этих штук курсоры. Хотя бы потому, что курсор -- это затык для оптимизатора/планировщика, и курсоры единственно полезны в случае, когда идёт построчная обработка записей, опционально с ранним завершением. Если писать хранимые процедуры на внешнем языке, все запросы, которые нужны, можно включать в эту .dll/.so, без курсоров.

[identity profile] gsbelarus.livejournal.com 2012-02-11 05:02 pm (UTC)(link)
это не то. UDF -- просто функция. получает параметры -- возвращает результат. а для полноценной работы с БД надо из нативного кода:

1) иметь доступ к текущему подключению
2) иметь доступ к текущей транзакции
3) возможность создавать и выполнять запросы
4) для триггеров иметь доступ к старой/новой версиям записи