Автор принял для себя решение
Автор принял для себя решение

В этой статье я не намерен обидеть DBA-разработчиков. Однако, я пришел к выводу, что в большинстве случаев написание хранимых процедур стало нецелесообразным. В современных реалиях взаимодействие с ними вызывает невообразимую боль и нежелание когда-либо снова с ними работать. Это связано с тем, что требования к качеству работы приложений возросли, а новых инструментов в SQL для решения этой проблемы так и не появилось, что не позволило повысить качество.

Основной причиной, почему хранимые процедуры стали рудиментом, является изменение подходов в разработке. Большинство систем разрабатывается с расчетом на микросервисную архитектуру и горизонтальное масштабирование сервисов, а не на написание монолитов.

Но это если вкратце, давайте разберем по подробнее.

Размазанность бизнес логики

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

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

Возможное обращение к отцам основателям хранимых процедур
Возможное обращение к отцам основателям хранимых процедур

В своей работе я довольно часто сталкивался с подобным. Главная проблема заключается в том, что, собирая информацию по крупицам, приходится вносить изменения в код без полного понимания, надеясь, что всё заработает. Если не заработает, приходится пробовать менять что-то ещё, и так цикл повторяется до тех пор, пока ошибка не будет исправлена.

Сложность в тестировании

Начнем с самого популярного вида тестирования – ручного, и, возможно, единственного при использовании хранимых процедур. Часто при ручном тестировании нет возможности поднять локально мега-мастер базу данных со всеми необходимыми данными для тестирования, и приходится обращаться к тестовому стенду, который часто работает нестабильно.

Работает он нестабильно потому, что параллельно свои изменения могут вносить ещё множество людей, что приводит к тому, что возникающая ошибка при проверке может не иметь отношения к вашей задаче. В худшем случае тестовый стенд вообще не работает, потому что кто-то его сломал.

Умные мысли не покидали его...
Умные мысли не покидали его...

Бывает, что при неработающем стенде от аналитиков и заказчиков поступают предложения протестировать на продакшене, потому что нужно как можно скорее исправить проблему. Они аргументируют это тем, что на продакшене всё равно уже не работает, но вся полнота ответственности за это ложиться на вас за это действие.

Поэтому приходится заниматься обратным делегированием: если аналитик и тестировщик не знают, как и что проверить, мы, как разработчики, просто делегируем эту задачу им, говоря, что всё исправили и теперь они могут проверить.

Но неработающий тестовый стенд — это ещё не самая худшая ситуация. Гораздо хуже, когда просто непонятно, как протестировать. Например, если хранимая процедура принимает входным параметром XML с динамическим количеством свойств, и вам нужно собрать нужную комбинацию этих свойств, чтобы добраться до вашего участка кода. Очевидно, что никто не осведомлён о необходимой комбинации. Сложность сбора этой комбинации свойств сродни сбору флеш-рояля в покере, когда вы играете на свой последний доллар.

Примерно так ощущаешь себя во время попытки протестировать
Примерно так ощущаешь себя во время попытки протестировать

Автоматическое тестирование или unit-тесты

Сколько работал с хранимыми процедурами, ни разу за свою жизнь не встречал адекватных автотестов в CI, которые могли бы что-то проверять. Видел лишь попытки создания параллельных проектов, которые через некоторое время переставали поддерживать. А без тестов не будет качества, ведь вся разработка будет производиться наугад.

Хотелось бы, чтобы при закрытии бага можно было просто написать на него тест, который запустится в CI и сообщит нам, что всё отработало корректно и ваши изменения ничего не сломали. Но работа с хранимыми процедурами исключает данный подход.

Ответ дан после тестирования хранимок.
Ответ дан после тестирования хранимок.

Отсутствие современных фишечек и фреймворков и соединение жизненного пути с БД.

Например, от бизнес-партнеров поступило требование собирать метрики по определённым участкам бизнес-процесса для их оценки. И как мы будем это делать? Правильно, реализовывать ещё больше костылей, потому что SQL — это язык для агрегации данных, а не язык для описания бизнес-логики приложения. В любом современном языке программирования достаточно подключить какую-либо библиотеку и настроить URL /metrics для сбора необходимых метрик и отправляться снова смотреть видосики на Youtube VK video.

Также, описывая бизнес-логику нашего приложения с помощью SQL, мы перекладываем все вычисления на сервер базы данных, что лишает нас возможности легко горизонтально масштабировать приложение с помощью увеличения числа инстансов в Kubernetes.

И вообще современных приложениях стараются отвязаться от конкретного источника данных, ведь кроме конкретной SQL БД существуют и другие. При использовании хранимых процедур наша БД становится конечной остановкой. Нужен более гибкий и быстрый поиск, где можно было бы использовать Elasticsearch? Требуется быстрая NoSQL для какой-либо части нашего приложения, например Redis? Извините, но у нас так не принято.

Хранимка извиняется и выносит предупреждение
Хранимка извиняется и выносит предупреждение

А работая на .NET часто бизнес-логика выноситься в домен и покрываться сразу Unit-тестами не опираясь на используемую базу данных, ведь есть такие прекрасные вещи, как ORM (Entity Framework), которая позволяет выбрать любую базу данных в моменте и наслаждаться жизнью. То-есть мы уже вольны использовать, что нам нужно.

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

Проблемы с переездом на другую БД

Раньше этот пункт казался чем-то невозможным: если понадобится, выделим пару десятков лет на переезд. Но после известных событий и наложенных санкций компании столкнулись с требованием перейти с MS SQL на другие СУБД. И тут начались проблемы: Postgresql имеет другой синтаксис и не обладает теми же функциональными возможностями. Поэтому в кратчайшие сроки нужно всё переписывать и переносить бизнес-логику обратно в приложение.

Из-за разницы в функциональности это даже сложно назвать переносом — нужно всё разбирать и переписывать с нуля. Но как переписать всё с нуля, если половина людей не понимает, как это работает, а у второй половины разная степень экспертизы в SQL? Для backend-разработчика глубокие знания всех версий и вариаций SQL не являются обязательными, ведь у них есть свой основной язык программирования.

Пример разного уровня экспертизы...
Пример разного уровня экспертизы...

Заключение

В заключение хочу подвести итоги и перечислить все минусы, которые я обозначил в статье и к которым пришёл.

  • Сложность в поддержке и тестировании.

  • Проблемы при параллельной разработке

  • Ограничение функциональности, функциональностью БД

  • Отсутствие горизонтального масштабирования

  • Отсутствие гибкости в выборе необходимого хранилища данных

  • Проблемы с переносимостью бизнес-логики

  • Backend разработчики должны обладать знаниями DBA

  • Сложность порождает низкое качество и большое количество ошибок.

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

Комментарии (98)


  1. rinace
    06.08.2024 10:23
    +1

    Обсуждалось 4 года назад

    «В карантин нагрузка выросла в 5 раз, но мы были готовы». Как Lingualeo переехал на PostgreSQL с 23 млн юзеров https://habr.com/p/515530/


  1. rinace
    06.08.2024 10:23
    +1

    SQL — это язык для агрегации данных, а не язык для описания бизнес-логики приложения

    Дальше читать не имеет смысла


    1. michael_v89
      06.08.2024 10:23
      +4

      https://en.wikipedia.org/wiki/SQL
      "The scope of SQL includes data query, data manipulation, data definition, and data access control."


      1. orefkov
        06.08.2024 10:23
        +5

        Но хранимки пишут не на sql. В каждой СУБД обычно какой-то свой, и часто даже не один, язык для написания хранимых процедур.


        1. michael_v89
          06.08.2024 10:23

          Но процитировано-то утверждение со словом SQL.


    1. Orcdelux
      06.08.2024 10:23

      Это точно.


  1. TMTH
    06.08.2024 10:23
    +8

    Насчёт тестирования. Автор наверное забыл упомянуть про возможность тестов на реальной СУБД? Я не то, чтобы фанат хранимок, но надо как-то реальные недостатки обсуждать, а не проблемы возникающие от незнания/неумения.

    Проблемы, описанные в разделах "Сложность в тестировании" и "Автоматическое тестирование или unit-тесты" в значительно мере могут решены связкой test-containers + [ваш любимый инструмент миграции] (для распространённых СУБД всю конструкцию можно запустить за день с нуля). В этом случае, интеграционный тест на хранимку собственно и будет её актуальной документацией.


    1. michael_v89
      06.08.2024 10:23

      Автор наверное забыл упомянуть про возможность тестов на реальной СУБД?

      Это интеграционные тесты, а он говорит про юнит-тесты.

      могут быть решены связкой test-containers + [ваш любимый инструмент миграции]

      Он же не сказал, что они не могут быть решены, он говорит, что это сложнее. В этом я с ним согласен.


      1. dph
        06.08.2024 10:23

        Хм, а в чем проблема в unit-тестах для хранимых процедур?
        Открываем транзакцию, заполняем фикстурой (тривиальный insert из таблицы с тестовыми данными), вызываем процедуру, проверяем утверждения, откатываем транзакцию.
        Это довольно просто пишется, быстро работает, легко модифицируется.


        1. michael_v89
          06.08.2024 10:23

          В том, что это не юнит-тест. Это интеграционный тест с вводом-выводом по сети и на диск. Юнит-тест в классическом понимании так не делает.

          С транзакцией тоже есть вопросы. Вот допустим у меня есть бизнес-требования "Сохранить объект в базу с одним статусом, отправить по сети в другую систему, при успешной отправке ставить другой статус, при ошибке ставить третий". Здесь должно быть 2 транзакции, до и после отправки по сети. Как написать тест на эту логику? В приложении я могу замокать базу и клиент к другой системе, и проверить, какие данные будут через них отправляться, без фактической отправки.

          Да, дальше появляются советы сделать таблицу-очередь, читать из нее в приложении, отправлять и обновлять статус из приложения, потом другой программист не может найти, где реализована эта часть бизнес-требований. Это как раз к вопросу "собирать информацию по крупицам".


          1. dph
            06.08.2024 10:23
            +1

            Во-первых, откуда в указанном примере сеть и диск? Сам тест пишется на sql, выполняется внутри БД и на диск ничего не пишет.
            Во-вторых, что за "классическое понимание"? Единица тестирования - хранимая процедура, ее и тестируем, в чем проблема?
            В-третьих, то, что описано как "бизнес-требование" - таковым не является, описана техническая реализация. Нужно ли именно такое - не понятно, тем более в системе уровня "логика в БД".
            Ну и так далее....


            1. michael_v89
              06.08.2024 10:23

              Во-первых, откуда в указанном примере сеть и диск?

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

              Во-вторых, что за "классическое понимание"?

              https://en.wikipedia.org/wiki/Unit_testing
              Unit testing, a.k.a. component or module testing, is a form of software testing by which isolated source code is tested to validate expected behavior.
              One goal of unit testing is to isolate each part of the program and show that the individual parts are correct. A unit test provides a strict, written contract that the piece of code must satisfy.

              https://www.baeldung.com/cs/unit-testing-vs-tdd
              Isolated. A unit test shouldn’t modify or depend on any external state.

              В-третьих, то, что описано как "бизнес-требование" - таковым не является

              Именно является. Аналитики от бизнеса знают, что такое БД и сохранение данных. И хотят сначала сохранить в нашу базу, а потом отправлять в другую систему. Иначе может быть так, что в другой системе запись создалась, а в нашей после этого произошла ошибка транзакции, и данные не сохранились. Это именно бизнес-логика, такая же как "После создания заказа отправить email пользователю".


              1. TMTH
                06.08.2024 10:23
                +1

                [о да, религиозные фанатики в интернете...]

                В сторону от темы: Вы же понимаете, что все эти требования, про то, что юнит-тест должен, а чего не должен, не обоснованы ничем (я, естественно, читал все эти теоретические обоснования, и говорю это на основе прочитанного), кто-то верит, что оно должно быть так, как в википедии написано, кто-то нет. Это не особо важно - разработка это ремесло, а не теория. Есть распространённые примеры других подходов, например в Рельсах тесты на реальной БД идут из коробки, и называются юнит-тестами (работает в точности по описанной выше схеме).

                По теме: Мы говорим не об абстрактном коде, а именно о коде взаимодействующем с базой данных. Этот код почти всегда включает запросы к БД (ORM тоже, просто вы их не видите). Т.е. у нас есть, как-бы isolated source code, который включает инструкции к внешней системе, которые только эта внешняя система и может интерпретировать. Это точно isolated? Печальный факт состоит в том, что на моках базы данных вы никак не проверите, что внутри этих запросов написано (нестрого говоря, тесты репозитория на моках - это погружение в мир иллюзий, у вас как-бы 100% покрытие, но при этом всё равно deploy-and-pray стиль интеграции). И если раньше (давно) тестирования кода на реальной базе данных было сопряжено с некоторыми техническим трудностями, то сейчас контейнеризация решила большую часть этих проблем. Технически, у вас всё равно есть какой-то setup метод, который выполняется до тестов, и большая ли разница, общие моки там настраиваются, или контейнер в память поднимается.

                Тут, конечно, может быть терминологический вопрос, он же вопрос про скоуп интеграционного теста. В нашей практике, интеграционный тест - это тест который который поднимет все микросервисы, участвующие в каком-то воркфлоу. Юнит-тест, понятно, изолированный кусок кода на моках. Но между этими вариантами есть целый спектр других уровней автоматизированных тестов, и где там ставить границу интеграционного теста это, по большому счёту, вопрос соглашения.

                И по основному тезису - если у вас есть тесты на реальной БД (называйте их как угодно), то тестирование хранимок ничем не отличается от тестирования запросов. Если таких тестов у вас нет... ну, не знаю, наверное есть отрасли где данные ничего не стоят, сам не видел, врать не буду.


                1. michael_v89
                  06.08.2024 10:23
                  +1

                  Вы же понимаете, что все эти требования, про то, что юнит-тест должен, а чего не должен, не обоснованы ничем

                  Был вопрос "Что за классическое понимание?", я привел ответ с пруфами. Неважно, чем они обоснованы, это все равно является ответом на этот вопрос.

                  Т.е. у нас есть, как-бы isolated source code, который включает инструкции к внешней системе, которые только эта внешняя система и может интерпретировать. Это точно isolated?

                  Source code сам по себе не является isolated, он явлется isolated только в тестах. Тесты настраиваются таким образом, чтобы сделать код юнита isolated. Это написано в приведенном тексте: "goal of unit testing is to isolate".

                  Печальный факт состоит в том, что на моках базы данных вы никак не проверите, что внутри этих запросов написано

                  Вот разговор как раз о том, что для теста юнита это совершенно неважно. В юнит-тесте мы проверяем только поведение самого юнита на заданных данных, а не всех его нижележащих компонентов. На эти компоненты есть свои юнит-тесты.


              1. dph
                06.08.2024 10:23

                Ну, таблица для тестов может и в памяти жить, в чем проблема? Если для тестирования используются искусственные данные (а в юнит-тестах обычно так и есть), то все данные будут в памяти и так. Транзакция до завершения может и пишет в журнал, но его тоже можно развернуть в памяти, делов-то.
                Все это достаточно просто решаемые вопросы, причем решать их умели еще лет 20 назад.

                И нет, если у вас бизнес (не аналитики, а именно бизнес) знает про БД, то тут какие-то проблемы. Впрочем, в указанном примере вообще нет (и не может быть) решения, только eventually consistency, саги и так далее. Где и как будет реализована сага - бизнесу вообще без разницы (


                1. michael_v89
                  06.08.2024 10:23

                  Ну, таблица для тестов может и в памяти жить, в чем проблема?

                  Ну а как тестовые данные туда попадают? Какая-то программа подключается по сети, читает их откуда-то с диска и добавляет.

                  Все это достаточно просто решаемые вопросы

                  Ну а с юнит-тестами в приложении их вообще решать не надо. Это и показывает, что такие тесты в базе отличаются от юнит-тестов в приложении.
                  Смысл вообще не в том, что данные должны быть в памяти, а в том, чтобы тест не взаимодействовал с внешним для него состоянием или системами.

                  И нет, если у вас бизнес знает про БД, то тут какие-то проблемы.

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

                  Где и как будет реализована сага - бизнесу вообще без разницы

                  Я не сказал, что бизнесу есть разница, где и как реализована сага. У бизнеса есть требование "Сначала сохранить в нашей базе с этим статусом, потом отправлять в другую систему, по результату отправки обновлять статус". Тут нет требований где и как это реализовывать.


                1. TMTH
                  06.08.2024 10:23

                  только eventually consistency, саги и так далее

                  Мне кажется, что в этом примере, сага будет некоторым перебором. Здесь, как мне кажется, вполне хватит обычного transactional outbox, если мы можем гарантировать идемпотентность по сообщениями на стороне системы получателя.


  1. oldlama
    06.08.2024 10:23
    +14

    Совершенно правильные замечания с точки зрения казуального юзера, взаимодействующего только с верхними слоями БД. Конечно в отношении "сервис - база данных" не должны участвовать хранимки.
    Однако не стоит забывать, что то, что вы видите от БД это лишь верхушка айсберга. Как известно на поверхности находится лишь 1/10 часть.
    Само формирование базы не представимо и полностью невозможно без использования хранимок.
    Если переводить в метафору - вы, в данном случае, владелец кредитного китайце в пробке, рассуждающий о том, что механическая коробка передач более не нужна и вообще морально устарела. А теперь представьте лицо профессионального гонщика (или Вин Дизеля), который бы это услышал. И вас понять можно, но и глупость, которую вы морозите, сложно оправдать. Не стоит обобщать весь мир АйТи под ваш опыт.

    *Смайлик клоуна*


    1. michael_v89
      06.08.2024 10:23
      +3

      Встречал много проектов с базой без каких-либо хранимок. Так что представимо и возможно.


      1. GlukKazan
        06.08.2024 10:23

        Встречал много проектов с хранимками, так что и это возможно тоже.


        1. michael_v89
          06.08.2024 10:23

          Я и не говорил, что проекты с хранимками невозможны.


  1. merkel
    06.08.2024 10:23
    +4

    мне, как .net разработчику, перешедшему в команду с достаточно большим количеством данных, прекрасно понятны мотивы, побудившие автара на написание сего опуса. Было бы все так просто, работоли бы все на одном "самом лучшем языке программирования". Если в приложении есть нормальный бэкэнд, очевидно - не стоит размазывать логику между ним и БД. Но в реальной жизни, не все ПО строится по трехзвенной архитектуре - есть целый пласт задач, где BLL на уровне СУБД суть рациональное решение.


  1. Arm79
    06.08.2024 10:23
    +4

    Любой инструмент должен быть применен по назначению. В том числе и хранимые процедуры.

    Текст процедур вообще ничем не отличается от текста на, к примеру, Java. Его можно прекрасно положить в GIT и так же версионировать. И точно так же документировать, точно так же тестировать на тестовой бд.

    Единственный значимый аргумент - это привязка к конкретной СУБД. И то каждый сам для себя определяет допустимую степень риска. Кому было нужно - потратили время и деньги и перешли с oracle/mssql. Значит, задача не является нерешаемой.

    Паническое нежелание работать с ХП иногда приводит к маразму. Настолько разработчики боятся малейшей логики в бд, что вместо select max(...), загружают список записей на клиента и уже там находят максимальное значение нужного поля (сам видел)


    1. rinace
      06.08.2024 10:23
      +2

      Настолько разработчики боятся малейшей логики в бд

      Я видеть такой кейс(регулярно повторяемый)- backend выгружает весь набор строк и фильтрует на стороне приложения.

      Закономерный итог -"а почему в psql запрос отработал миллисекунды а форма открывается минуту ?"


    1. Free_ze
      06.08.2024 10:23
      +2

      Настолько разработчики боятся малейшей логики в бд, что вместо select max(...), загружают список записей на клиента и уже там находят максимальное значение нужного поля

      Будь так, слали бы запрос с select max(...) и ХП не понадобилась бы. А тут больше похоже на то, что банально не подружились с генератором запросов в ORM.


      1. Arm79
        06.08.2024 10:23

        Задача была именно такая: найти запись по сотруднику с максимальным score

        Решение изумило: скачивали на клиента при каждом запросе (нагрузка была примерно 200 tps) около 20 строк, руками пробегали этот список и находили строку с максимальным значением, и брали все атрибуты именно с неё.


        1. Proscrito
          06.08.2024 10:23
          +2

          Это аргумент ни за, ни против хранимок. Чтобы отправить в базу max(..) хранимки не нужны. Да это и современные орм умеют делать полностью прозрачно. Некоторые даже могут обновлять данные не выбирая их на клиента, там где сценарий позволяет.

          Бизнес-логика в базе это однозначно плохо. Банально затрудняет отладку и читаемость кода. Но иногда это вполне приемлемая цена за производительность. От задачи зависит.

          Вытаскивать N записей из базы чтобы найти среди них одну по банальному условию это профнепригодность разработчика. Если эти N записей не используются потом где-то еще, конечно. Таких абсурдных косяков можно наделать где угодно, не только при работе с базой. Если разработчик шлепает код на отвали, он найдет где накосячить.


          1. rinace
            06.08.2024 10:23

            Бизнес-логика в базе это однозначно плохо. Банально затрудняет отладку и читаемость кода.

            Данное утверждение будет верно только при одном важном уточнении - читатель и отладчик не обладает знаниями Database Development .

            Что и подтверждается следующим утверждением

            Если разработчик шлепает код на отвали, он найдет где накосячить.


            1. Proscrito
              06.08.2024 10:23
              +1

              Данное утверждение будет верно всегда. Читать код, который собран в одном проекте все равно проще, чем переключаться из проекта в проект. То же самое и с отладкой. Даже если читатель и отладчик обладает божественными знаниями во всех возможных сферах, это утвреждение неверным не становится. Что чем у вас подтверждается - решительно непонятно. А главное зачем.


    1. michael_v89
      06.08.2024 10:23
      +1

      Настолько разработчики боятся малейшей логики в бд, что вместо select max(...), загружают список записей на клиента

      Ну это конечно неправильно в определенных ситуациях, но в других ситуациях это может быть более подходящим решением. Без контекста нельзя точно сказать. Кроме неумения использовать ORM, как сказали выше, могут быть например такие причины:
      - Список записей потом используется для чего-то еще.
      - Для произвольного запроса надо писать 20 строк, а для вычисления в приложении 1. Тот, кто советует отправлять max() в базу, поддерживать их конечно не собирается. При этом записей в этой выборке не больше 10.
      - В коде проще отслеживать и менять логику средствами IDE, чем в строковых константах с SQL. Если разработчик приложения пропустит это место при изменениях требований, вы (DBA) будете ответственный или он? Вы будете исправлять этот баг в строковой константе? Зато 10 микросекунд сэкономили.


    1. NIKEtoS1989
      06.08.2024 10:23

      У нас архитектор вообще запрещает хранимки, триггеры и прочую логику в БД


    1. dedmagic
      06.08.2024 10:23
      +3

      Текст процедур вообще ничем не отличается от текста на, к примеру, Java.

      Ну нет.

      Во-первых, выразительность современных бекенд-языков (того же Java) на порядки лучше, чем у процедурных расширений SQL, используемых в современных СУБД. Попробуйте для сравнения написать более-менее крупную систему на Java и на PL/pgSQL, потом нам расскажите, что разницы никакой нет.

      Во-вторых, инструментарий тоже очень разный. Например, для бекенда есть целая пачка крутых IDE, для СУБД я как не искал, не нашёл ничего похожего (чтобы и работа с Git, и тесты гонять, и отладка нормальная и т.д.). А ведь разработка не только в IDE упирается, и с экосистемой в СУБД всё значительно хуже.


  1. sinelnikof88
    06.08.2024 10:23

    За большей частью текста полностью за !!! Работал 5 лет назад с оракловской бд, это дикая боль. За исключением как у них реализован рекурсивный обход, все остальное, жесть. Бизнес логика написана хранимками, и упиханна в пакеджи. Которые нужно ещё компилировать . Собирается все херово . Инстансы ещё нужно определенной версии. Но самая жопа это логика в базе!!!! База должна уметь репликации, дампить нормально, а не валится или битые с ходу делать. Я не хочу разбираться в сиквенсах, мне нужно надёжно данные сохранить . Уметь в кластер и давать АДЕКВАТНЫЕ ответы на ошибки. А не засирать диск тупыми логами , с нулевой информативностью . (Может в настройках дело, но это говно даже перезапустить боялись ) потому что она поднималась раза с 5 го. Логика - в код, данные в бд

    При каждой пересборке пакетов, отлетают клиенты. И есть шанс уронить вообще все.

    Согласен с автором логика в бд - за такое четвертовать !


  1. CrazyElf
    06.08.2024 10:23
    +9

    Прочитав статью можно подумать, что хранимые процедуры были придуманы какими-то идиотами, у которых просто нормального ORM-а не было. И что у хранимок нет никаких плюсов, а сугубо одни минусы. А между тем плюсы всё-таки есть.

    • Хранимые процедуры заранее компилируются и оптимизируются движком SQL. И поэтому теоретически работают быстрее, чем просто запросы к базе, делающие ту же работу, что и процедуры. Хотя этот плюс несколько нивелирован современными движками БД, которые кэшируют SQL запросы и их результаты, в том числе параметризуемые запросы.

    • Лучший контроль за транзакциями и исключениями на низком уровне.

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

    Хотя я лично и сам ненавижу, когда логика размазана по слоям, и что там не очень то ООП получается на уровне БД когда программируешь. Но не упоминать, что у процедур есть и плюсы - это странно.


  1. Shura_m
    06.08.2024 10:23
    +6

    Как вы так оптом, легко и просто, умножаете на ноль целую технологию.

    У любой технологии есть свои «+» и «-», и для разных задач используют разные методики.

    Способ хранения данных, доступ к ним определяется на этапе проектирования системы.  Даже типы серверов (MS SQL,  Oracle, MySQL, ..) отличаются по функционалу, и все это нужно учитывать.

    Мне кажется, Ваше отношение к данной технологии вызвано неграмотно спроектированной системой на этапе бизнес логики, вызывающей такие проблемы. Должен быть уровень данных, предоставляющий данные в верхний уровень, и программист, пишущий, к примеру, на .NET, может совсем не знать что там внутри- SQL, XML или что-то совсем другое.

     

    Тут, как в анекдоте:

    -Вы не любите кошек? Да вы просто не умеете их готовить!


    1. michael_v89
      06.08.2024 10:23

      и программист, пишущий, к примеру, на .NET, может совсем не знать что там внутри- SQL, XML или что-то совсем другое.

      Одни говорят, что автор не знает и не разобрался, другие, что он и знать не должен)
      Кто будет писать в приложении этот "уровень данных, предоставляющий данные в верхний уровень" и потом поддерживать, вы (DBA) или разработчик приложения? Зачем ему эти сложности?


  1. StanEgo
    06.08.2024 10:23
    +10

    Хранимые процедуры замечательно тестируются, отлично оптимизируются. В задачах, для которых они предназначены, нет ни одного ЯВУ, который был бы более выразителен. Добавляют ещё один уровень безопасности, полностью скрывая реальные структуры данных, полиморфны, можно легко добавить трейсинг, профайлинг и т.п., прекрасно мигрируют на другую СУБД даже без ребилда и деплоя приложений, можно без труда реализовать поддержку множества СУБД, классно помогают в скейлинге/миграции схемы когда нужно осуществить плавную трансформацию в фоне петабайтов данных и временно спрятать её за вызовом хранимки. У нас замечательно и из Linq генерируются хранимки. А вот за что точно надо отрывать руки - это когда противники хранимок гоняют гигабайты данных туда-сюда, пропуская их через лес уродливого кода, для работы в таком ключе вообще не приспособленного))


    1. rinace
      06.08.2024 10:23

      за что точно надо отрывать руки - это когда противники хранимок гоняют гигабайты данных туда-сюда, пропуская их через лес уродливого кода, для работы в таком ключе вообще не приспособленного

      "В детстве , я таких убивал. Из рогатки".(с)


    1. NikolayTheSquid
      06.08.2024 10:23
      +4

      Хотел написать всё тоже самое с примерами с предыдущих мест работы. Но нашёл ваш комментарий, с которым полностью согласен, и меня отпустило. Похоже, автор статьи просто не умеет готовить крокодилов. Хочу только напомнить ему, что каждый инструмент имеет свои границы применимости, и каждый специалист применяет их в меру своей квалификации.


  1. ptr128
    06.08.2024 10:23

    Следующим шагом объявим рудиментом еще и функции. Ведь их отличия от процедур минимальны. Ну а напоследок можно и SQL объявить рудиментом, так как NoSQL СУБД имеют ряд преимуществ.

    Или все же "кесарю кесарево"? Может "золотого молотка" не бывает и любой инструмент имеет свою область применения?


    1. GlukKazan
      06.08.2024 10:23

      Уже. Функции - это тоже хранимки.


      1. ptr128
        06.08.2024 10:23

        Ага, и если нужна кастомная агрегатная функция, то ни-ни - тащи все строки на клиента и там агрегируй?


  1. N4N
    06.08.2024 10:23

    Все описанные минусы следуют из принятой как стандарт архитектуры, подразумевающий разделение приложения на слои. Слой данных в ней рассматривает СУБД как просто место хранения табличных данных. Но даже при таком подходе обычные crud операции можно реализовать как ХП, и вызывать их, просто передавая параметры в ХП и, если нужно, получать результат. Это будет гарантировано быстрее, чём держать SQL код в коде другого языка и который будет компилироваться сервером бд каждый раз при его выполнении. Плюс выглядит это ужасно, каждый раз когда смотрю какой-нибудь @Repository с query native=true, испытываю неприятные ощущения. Какой уж тут clear code, когда на пол экрана висит строка с жутким SQL )

    И аргумент, что SQL код начинает зависеть от конкретной реализации сервера, довольно слабый. Кто-то может привести пример, когда постоянно нужно менять сервер? На моей очень большой практике разработки такое было только два раза. Один раз, когда заказчик сразу сказал, что у него Oracle, и MS SQL ему не нужен, перепишите все. И второй когда вот это вот все началось и все ринулись импортозамещать все что можно, и решение нужно было перевести на postgres. Но оно уже было на orm и переход проходил довольно гладко


    1. michael_v89
      06.08.2024 10:23

      Но даже при таком подходе обычные crud операции можно реализовать как ХП, и вызывать их

      Можно. Только нафига?

      Это будет гарантировано быстрее

      Насколько быстрее? Через сколько часов работы приложения окупится дополнительный час работы программиста?


      1. N4N
        06.08.2024 10:23

        В среднем на 30% быстрее относительно запросов от orm на .NET + кластер MS SQL при нагрузке 120-150к запросов юзеров в минуту. Измерено на реальной банковской системе дбо. За сколько окупится не считали, за пару минут наверное. Для систем с уровнем надёжности mission critical не важно как быстро это окупится, имиджевые потери от падений системы кратко дороже


        1. michael_v89
          06.08.2024 10:23
          +1

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

          за пару минут наверное

          Откуда такая оценка? Если час работы senior-программиста допустим 2000 р, то экономия за минуту работы сервера получается 1000 р. Если это 30%, то работа сервера стоит 3000 р в минуту или 130 млн рублей в месяц. Как-то многовато для сервера.


          1. ptr128
            06.08.2024 10:23

            Откуда предположение, что логика в приложении обязательно означает падение системы?

            Падения системы обязательно будут в любом случае. Это жизнь. Но вероятность их возникновения при наличии транзакций, объединяющих множество запросов к БД, намного выше, когда логика в приложении, а не в СУБД. Просто потому, что сервис приложения может упасть, зависнуть, потерять связь с БД. И транзакция будет удерживать блокировки вплоть до истечения таймаута и закрытия соединения с приложением со стороны СУБД. А за это время может такая очередь выстроится, что запросы уже начнут отстреливаться по таймаутам или дидлокам.

            Ошибкой в хранимой процедуре уложить СУБД - надо очень постараться. А ошибкой в коде сервиса уложить или зациклить этот сервис - легко и просто. У меня, судя по Grafana, таких проблем около десятка ежедневно. Все же система активно развивается и ошибок не избежать. Но рестарт контейнера одного инстанца одного сервиса - это мелочи, по сравнению с остановкой всех инстанцов сотен сервисов, работающих с одной СУБД.


        1. Debrainer
          06.08.2024 10:23
          +1

          Полностью согласен.

          Наконец-то адекватный комментарий от человека с хайлоад нагрузкой и про финансовые данные.

          Отсутствие хранимок при crud операциях это точно не про хайлоад Энтерпрайз.

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


      1. ptr128
        06.08.2024 10:23
        +1

        Только нафига?

        Например, с завидной регулярностью вижу от ORM такие запросы, которые по производительности уступают оптимизированному коду на plpgsql даже не на порядок, а на два-три. Можно, конечно, отложив в сторону ORM, предложить .NET разработчику включить в свой код целый ворох кода на plpgsql. Но тогда не только этот разработчик, но и любой поддерживающий этот код, должен очень хорошо знать не только C#, но и plpgsql. А можно этому разработчику предоставить представления, функции или процедуры, написанные другим разработчиком, специализирующимся на plpgsql.

        Теоретически, когда то в будущем, может и появятся ORM умеющие использовать в CTE INSERT/UPDATE/DELETE RETURNING, применять pg_variables или переменные-массивы композитного типа вместо временных таблиц, понимать когда CTE надо явно материализовать, когда принудительно JOIN надо пребразовать в JOIN LATERAL или подзапрос и т.п. Но пока таких ORM даже не горизонте не видно.

        Через сколько часов работы приложения окупится дополнительный час работы программиста?

        Бывает, что в первые же минуты использования. Например, кто первый ответит на заявку, оперативно и достаточно точно спрогнозировав её доходность и сроки исполнения, тот, с большой вероятностью, и станет подрядчиком. А доходность заявки может составлять десятки тысяч рублей.


        1. michael_v89
          06.08.2024 10:23

          вижу от ORM такие запросы, которые по производительности уступают оптимизированному коду на plpgsql даже не на порядок, а на два-три

          Это не отвечает на заданный вопрос. Вы неявно предполагаете, что увеличить сложность поддержки, чтобы ускорить запросы для CRUD-опреаций на 2-3 порядка, почему-то оправдано. А вопрос был о том, почему.

          Например, кто первый ответит на заявку, оперативно и достаточно точно спрогнозировав её доходность и сроки исполнения

          Непонятно, что это за заявки, и как ответ базы 100ms вместо 10 мешает пользователям вашей системы делать прогнозы.


          1. ptr128
            06.08.2024 10:23

            Вы неявно предполагаете, что увеличить сложность поддержки, чтобы
            ускорить запросы для CRUD-опреаций на 2-3 порядка, почему-то оправдано. А вопрос был о том, почему.

            Потому что для пользователя разница между получением ответа через несколько секунд или несколько десятков минут определяет, захочет ли он вообще этой системой пользоваться.

            Непонятно, что это за заявки

            Да не важно. Любые заявки подразумевающие приоритезацию по очередности отклика на них.

            как ответ базы 100ms вместо 10 мешает пользователям вашей системы делать прогнозы.

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

            Просто представьте себе задачу, где полтерабайта оперативки и 256 ядер для PostgreSQL мало, даже не смотря на то, что запросов (вызовов хранимых процедур) он получает всего десятки в секунду, а целый ряд агрегаций отданы на откуп ClickHouse. Вы всерьёз предлагаете нарастить мощность такого кластера на порядок, чтобы сэкономить несколько часов работы разработчика?


            1. michael_v89
              06.08.2024 10:23

              Потому что для пользователя разница между получением ответа через несколько секунд или несколько десятков минут

              Разговор был про обычные CRUD-операции, обычно это означает, что пользователь делает одну CRUD-операцию за одно взаимодействие с системой (условная кнопка "Сохранить"). Они не занимают десятки минут.

              Если у вас какая-то сложная обработка данных, то не проще ли ее распараллелить в коде приложения на 1000 потоков?
              Если обработка простая, но данных много, то возможно да, тащить их в приложение нецелесообразно, но таких проектов мало, и непонятно, зачем проекты другого рода делать так же. Вы усложняете поддержку, но получаете профит, а в других проектах поддержка усложнится, а такого профита не будет.

              Во-вторых, в реальной жизни за 100 мс оптимизационную задачу не решите

              Было утверждение "Обычные crud операции можно реализовать как ХП", я спросил "Нафига?". При чем тут оптимизационные задачи?

              Вы всерьёз предлагаете нарастить мощность такого кластера на порядок, чтобы сэкономить несколько часов работы разработчика?

              Нет, я задавал вопрос про обычные CRUD-операции.


              1. ptr128
                06.08.2024 10:23

                Разговор был про обычные CRUD-операции, обычно это означает, что пользователь делает одну CRUD-операцию за одно взаимодействие с системой (условная кнопка "Сохранить").

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

                А сохранения заказа на закупку (условная кнопка "Сохранить") с резервированием единиц комплектующих и материалов на складах и расчетом сроков исполнения этого заказа с учетом SCM и загрузки оборудования - тоже содержит только CRUD операции. И если это заказ на закупку, например, шагающего экскаватора, то сохраняться он вполне может минуты.

                Они не занимают десятки минут.

                Какие десятки минут? У меня полный перерасчет прогнозирования занимает свыше 30 часов. Один SQL запрос трансформации истории операций миллиона грузовых вагонов (сейчас около 1.4 миллиона в сети РЖД) за последние пять лет во временные серии выполняется час на 24 ядрах. Больше бессмысленно выделять, так как СХД не справляется.

                Если у вас какая-то сложная обработка данных, то не проще ли ее распараллелить в коде приложения на 1000 потоков?

                Подняв 1000 соединений с СУБД? Или сначала загрузить десяток терабайт из БД в приложение, а потом уже параллелить их обработку? Причем далеко не все запросы вообще-то параллелятся.

                Было утверждение "Обычные crud операции можно реализовать как ХП", я спросил "Нафига?".

                Вы искренне считаете, что хранимая процедура обязательно должна содержать не только десятки или сотни CRUD операций, но еще что-то другое? Или для Вас одна транзакция - это всегда один SQL запрос?

                При чем тут оптимизационные задачи?

                Потому что без них ни один вид бизнеса не обходится. Само название ERP, подразумевает решение оптимизационных задач в целях планирования ресурсов предприятия.


                1. michael_v89
                  06.08.2024 10:23

                  И я об этом же.

                  Нет, не о том же. Объем вычислений за одно действие пользователя в вашем примере не такой, какой происходит при нажатии кнопки "Сохранить" в обычной админке.
                  Почему-то не получается ни у кого обсуждать нормально без подмены понятий.

                  И это всё вполне ограничивается CRUD операциями.

                  А я сказал про одну операцию. Именно потому что в БД вообще всё сводится только к CRUD-операциям со строками в таблицах. Поэтому различие сводится только к количеству таких операций за одно действие пользователя.

                  И если это заказ на закупку, например, шагающего экскаватора, то сохраняться он вполне может минуты.

                  Ну и пусть сохраняется. Это никак не отменяет факта, что в большинстве админок, интернет-магазинов и других аналогичных приложений сохранение данных столько не занимает. Пример - отправление коммента на Хабре.

                  Какие десятки минут?

                  Я повторил ваши слова, не знаю какие десятки минут вы имели в виду.
                  "Потому что для пользователя разница между получением ответа через несколько секунд или несколько десятков минут"

                  Подняв 1000 соединений с СУБД? Или сначала загрузить десяток терабайт из БД в приложение, а потом уже параллелить их обработку?

                  Для разных задач может быть по-разному.

                  Вы искренне считаете, что хранимая процедура обязательно должна содержать не только десятки или сотни CRUD операций, но еще что-то другое? Или для Вас одна транзакция - это всегда один SQL запрос?

                  Ни то, ни другое. Не вижу никакой связи с моими словами.
                  Разговор был о том, что вместо простого INSERT надо делать процедуру, которая будет делать INSERT, и вызывать из приложения ее. Вместо простого DELETE надо делать процедуру, которая будет делать DELETE, и вызывать из приложения ее. И т.д.

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

                  Это ложь, я работал в компаниях, где не было десятков миллионов прогнозов и путей в графе, и большинство запросов к базе занимало меньше 100ms.


                  1. ptr128
                    06.08.2024 10:23

                    Объем вычислений за одно действие пользователя в вашем примере не такой, какой происходит при нажатии кнопки "Сохранить" в обычной админке.

                    Но даже меньше, чем при нажатии кнопки "Сохранить" в обычной ERP, что я специально показал. Сколько пользователей работают с ERP, а сколько с админками?

                    Пример - отправление коммента на Хабре.

                    То есть объединить в одном запросе SELECT и INSERT можно, а больше уже нельзя? )))

                    А любой интернет-магазин, сохраняющий в одной транзакции и заголовок заказа, и его детали - уже обходится без CRUD операций? )))

                    А я сказал про одну операцию. Именно потому что в БД вообще всё сводится только к CRUD-операциям со строками в таблицах.

                    Один SQL запрос, в общем случае, содержит одновременно INSERT, UPDATE, DELETE и SELECT, Вы действительно считаете, что это уже не CRUD операции?

                    Разговор был о том, что вместо простого INSERT надо делать процедуру, которая будет делать INSERT, и вызывать из приложения ее.

                    Нет, разговор был о том, что объединить целый ворох SQL запросов одной транзакции в одну процедуру логичней, чем интегрировать их в код на языке приложения.

                    не знаю какие десятки минут вы имели в виду. "Потому что для пользователя разница между получением ответа через несколько секунд или несколько десятков минут"

                    Которые Вы предложили, согласившись на падение производительности на два-три порядка.

                    "Подняв 1000 соединений с СУБД? Или сначала загрузить десяток терабайт из БД в приложение, а потом уже параллелить их обработку?"

                    Для разных задач может быть по-разному.

                    А вот тут просьба подробней. Как по первому, так и по второму вопросу. С примерами.

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

                    Потрудитесь назвать вид бизнеса, который обходится без оптимизационных задач. Даже в овощном ларьке их приходится решать, пусть даже используя человеческий интеллект, вместо компьютера.


                    1. michael_v89
                      06.08.2024 10:23

                      Hidden text

                      Сколько пользователей работают с ERP, а сколько с админками?

                      Понятия не имею, у нас разговор про архитектуру кода проекта, а код один для всех пользователей сервиса.

                      - Объем вычислений за одно действие пользователя в вашем примере намного больше, чем в обычной crud операции в админке.
                      - Но даже меньше, чем при нажатии кнопки "Сохранить" в обычной ERP.

                      Я не понимаю смысл этих слов.

                      сохраняющий в одной транзакции и заголовок заказа, и его детали - уже обходится без CRUD операций?

                      Нет.

                      Один SQL запрос, в общем случае, содержит одновременно INSERT, UPDATE, DELETE и SELECT

                      Нет, в общем случае он не содержит эти операторы одновременно.

                      Потрудитесь назвать вид бизнеса, который обходится без оптимизационных задач.

                      Не буду, потому что это не относится к вопросу, зачем обычные crud операции реализовывать как ХП.

                      То есть объединить в одном запросе SELECT и INSERT можно, а больше уже нельзя?

                      По условиям утверждения "обычные crud операции можно реализовать как ХП" нельзя. Потому что тогда это будет не обычная crud операция.

                      разговор был о том, что объединить целый ворох SQL запросов одной транзакции в одну процедуру логичней

                      Я не знаю, где вы увидели это разговор. Я спрашивал про утверждение "обычные crud операции можно реализовать как ХП, и вызывать их, просто передавая параметры в ХП". Редактирование полей одного объекта в админке это обычная crud операция. Анализ десятков миллионов прогнозов и путей в графе это не обычная crud операция.

                      - Я повторил ваши слова про десятки минут
                      - Которые Вы предложили

                      Нет, фраза "несколько десятков минут" впервые появляется в вашем комментарии. Похоже, вы не следите за дискуссией и спорите о чем-то своем.

                      На нашем среднем сервере один запрос из приложения к базе занимает порядка 0.4-2 миллисекунды. Разница на 3 порядка это 2 секунды. А не десятки минут.
                      И это я посчитал время целиком с передачей по сети из базы в приложение, а не только сам запрос. А с процедурой время передачи по сети останется таким же, и разница будет еще меньше.

                      А вот тут просьба подробней. Как по первому, так и по второму вопросу. С примерами.

                      Это оффтоп, поэтому подробно останавливаться не буду. Ресайзинг изображений, ссылки на которые находятся в БД. Решение задачи коммивояжера для большого количества небольших наборов координат. Индексация большого количества данных из одного хранилища для полнотекстового поиска, который обеспечивается другим хранилищем, которое принимает данные в stdin.

                      когда утверждение, что "ни один вид бизнеса не обходится без оптимизационных задач", оппонент пытается опровергнуть уже не видами бизнеса, а конкретными компаниями

                      Потому разговор был о том, как организованы конкретные проекты в конкретных компаниях, которые отправляют запросы к конкретным базам. Я спросил, почему их надо делать именно так, как посоветовал автор начального комментария. Если вы поменяли тему разговора, никому не сказав, то не надо удивляться, что вас никто не понимает. Мысли читать никто не умеет.
                      Я не вижу причин, почему мне надо делать хранимые процедуры в БД для моего сервиса с web-API, если где-то в этой же компании используется 1С с хранимыми процедурами в своей БД.


                      1. michael_v89
                        06.08.2024 10:23

                        На нашем среднем сервере один запрос из приложения к базе занимает порядка 0.4-2 миллисекунды. Разница на 3 порядка это 2 секунды.

                        Хм, а ведь это даже неправильно. Это уже запрос из приложения в базу, который якобы должен быть больше на 3 порядка. То есть с процедурой должно быть 2 микросекунды, что явно неправдоподобно. В базе этот запрос выполняется за 0.3 - 1.8 миллисекунды.


              1. ptr128
                06.08.2024 10:23

                Если обработка простая, но данных много, то возможно да, тащить их в приложение нецелесообразно, но таких проектов мало

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

                По моему опыту разработки и внедрения ERP, автоматизации производства, логистики, АСКУЭ, биллинга коммунальных услуг и т.п - с точностью наоборот. Даже такие относительно небольшие предприятия, как Истра-Нутриция, Белая Дача или КамчатскЭнерго без этого не обходятся. Я уж молчу о предприятиях из ТОП-200 в РФ или международных холдингах. А более мелкие предприятия редко могут позволить себе заказные разработки и вынуждены обходиться коробочными решениями.


                1. michael_v89
                  06.08.2024 10:23

                  Я говорил на основании своего опыта и анализа требований в вакансиях при поиске работы.

                  https://www.searchlogistics.com/learn/statistics/ecommerce-statistics/
                  "There are currently over 26 million ecommerce sites and stores worldwide"

                  Можно взять эту статистику. В большинстве интернет-магазинов нет столько данных, чтобы их надо было обрабатывать процедурами на серверах с сотнями ядер. Я сомневаюсь, что предприятий уровня КамчатскЭнерго в мире больше 26 миллионов. А во многих интернет-магазинах есть еще и внутренние проекты, где тоже хранимые процедуры не используются. Еще можно поискать количество вакансий со знанием pl/sql на hh.ru.


                  1. ptr128
                    06.08.2024 10:23

                    Я говорил на основании своего опыта и анализа требований в вакансиях при поиске работы.

                    "There are currently over 26 million ecommerce sites and stores worldwide"

                    Вы сами поняли, что написали? Ecommerce - это как раз классический пример использования тех самых заказов на закупку, о которых я писал выше. Как Вы будете формировать заказ без резервирования товара на складах и прогнозирования времени его исполнения? Это даже не трогая механизмы оплаты, которые никак "простой обработкой небольших массивов данных" не реализуются.

                    Я сомневаюсь, что предприятий уровня КамчатскЭнерго в мире больше 26 миллионов.

                    Если мы оцениваем востребованность разработки, то сравнивать надо количество сотрудников. Например, в РФ в малом и среднем бизнесе занято ~28 млн. человек при общем числе занятых ~73 млн. человек.

                    И это даже не считая, что я указал: "более мелкие предприятия редко могут позволить себе заказные разработки и вынуждены обходиться коробочными решениями"

                    При этом пользователей только 1С в РФ свыше 8 миллионов. То есть, каждый десятый занятый использует "сложные обработки массивов данных" пусть даже и не всегда "больших". А если добавить сюда остальные ERP, то легко выйдем к каждому второму пользователю компьютером на рабочем месте.


                    1. michael_v89
                      06.08.2024 10:23

                      Как Вы будете формировать заказ без резервирования товара на складах и прогнозирования времени его исполнения?

                      Я не сказал, что буду формировать заказ без резервирования товара на складах и прогнозирования времени его исполнения.
                      Я сказал, что есть мало проектов, где обработка данных простая, но данных настолько много, что вытаскивание и обработка их в приложении займет несколько десятков минут.

                      Если мы оцениваем востребованность разработки, то сравнивать надо количество сотрудников.

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

                      То есть, каждый десятый занятый использует "сложные обработки массивов данных"

                      Ну и пусть использует. Как из этого следует, что мне надо писать свои обычные crud операции в хранимых процедурах, если любая их них занимает меньше одной секунды даже с логикой в приложении?


  1. S_gray
    06.08.2024 10:23
    +3

    Да ответ-то на всё простой - дизайнить систему надо правильно: бизнесу - бизнесово, базе - базово. Тогда всё уляжется. Отцы-основатели ООД и ООА свое дело туго знали, не то что нынешнее племя...


  1. Batalmv
    06.08.2024 10:23
    +2

    Я бы сказал так.

    Для юзер-ориентированных приложений, построненный по трех-уровневой архитектуре - хранимки "это рудимент". В новых приложениях использовать такие решения крайне плохо и никакая "лапша на уши" про 2% выигрыша производительности того не стоит.

    Одно размазывание логики чего стоит, плюс полная невозможность переиспользования реализации в разных слоях.

    ------------

    Но есть куча задач в самой БД либо для переливки\подготовки данных. Тут хранимки - это хорошо и правильно.

    ----------

    Немного по пунктам

    Сложность в тестировании

    Для юнит тестов - наверное да, так как надо "готовить" кучу данных, что для логики в приложении как правильно не проблема (ну или как минимум легче подкинуть в тест данные). Для чего-то интеграционного данные так или иначе надо готовить, поэтому тут уже не факт, что хранимки чего-то там усложняют

    Автоматическое тестирование или unit-тесты

    Тут я не понял, в чем сложность. Возможно просто автор чуток не умеет в определенные вещи

    Например, от бизнес-партнеров поступило требование собирать метрики по определённым участкам бизнес-процесса для их оценки. И как мы будем это делать? Правильно, реализовывать ещё больше костылей, потому что SQL — это язык для агрегации данных, а не язык для описания бизнес-логики приложения. В любом современном языке программирования достаточно подключить какую-либо библиотеку и настроить URL /metrics для сбора необходимых метрик

    И да, и нет. Зависит от метрик. Ну и надо понимать, что сбор метрик в интеграционной среде часть это много разных приложений, что уже не так сильно зависит от конкретных технологий реализации


  1. duke_alba
    06.08.2024 10:23

    Любая категоричность а подобных вопросах - вещь сильно спорная. Вот IBM в своё время чуть не разорилась из-за злоупотребления оператором goto, и потом целое поколение программистов шарахалось от этого оператора, как чёрт от ладана. Многие даже и не знали первопричины. Просто - детская травма :-)

    Второй пример из области БД: триггеры - это зло! Теперь - хранимые процедуры, как оказалось, тоже зло.

    Возможно, просто надо разобраться, что для чего использовать, и в каких количествах?