LINUX.ORG.RU

Бизнес логика в хранимых процедурах СУБД. Ваше мнение.

 , ,


0

2

Сейчас в ынтерпрайзе всякая ява с нодой, но многие еще угорают по хранимкам. Вы сталкивались с таким? Какие плюсы, минусы, подводные камни? Кто переделывал проект с одного на другое?
У меня были расчёты чисто на sql (субд - mysql), всё хорошо, если их не трогать. Работают быстро, хотя вынесение всего этого добра на яву не пробовал и не планировал. На новой работе надо поддерживать и то и то.

Ответ на: комментарий от WitcherGeralt

Им мог бы стать ты.

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

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от enthus

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

Ну как тебе сказать. Она укладывается в реляционную, но есть у нас, например, таблица ключ-значение с параметрами всего. Есть у нас ид для всего, таблица и которая хранит тип для такого ид. А еще (не точно) в параметрах они хранят sql, который делает выборку валидных значений параметра (видимо так удобно делать выборку из delphi). Если не брать в расчёт последнее (оно нужно только для валидации), то можно из key-value перегнать в столбцы и заджоинить..

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от enthus

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

Не проблема сделать выборку из 10 таблиц/подзапросов и все это куда-нибудь вставить, но когда меня через месяц попросят что-то там поправить я боюсь внезапно обнаружить себя за злоупотреблением крепкими спиртными напитками прямо на рабочем месте.

crutch_master ★★★★★
() автор топика
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Квартплату за все эти гвс, хвс, вотоотведение, отопление, подогрев, ээ, общедомовые, кап.ремонт и т.д. Всё считается по-разному и часто по-наркомановски. Например раскидывание объемов между лицевыми, с нескольких физ.счётчиков, общедомовых/витруальных (нормативы) на логический через граф, бывает несколько вариантов расчётов для каждой услуги + разные тарифы/параметры тарифа. Плюс оплата (кассы, жильцы, инкассация), гис жкх, платёжные документы и всякие отчёты для бухов.

crutch_master ★★★★★
() автор топика
Последнее исправление: crutch_master (всего исправлений: 3)
Ответ на: комментарий от crutch_master

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

WitcherGeralt ★★
()

В БД вообще не должно быть логики! Долой NOT NULL, первичные и внешние ключи!

anonymous
()
Ответ на: комментарий от crutch_master

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

enthus
()
Ответ на: комментарий от crutch_master

где любой маппер бы всё сделал приходится каждый раз городить запрос с 3-мя join'ами и подзапросом

так а что мешает те же хеши нативно в оракле использовать?

anonymous
()
Ответ на: комментарий от crutch_master

все всё умели

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

У нас даже архитектора бд нет

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

anonymous
()
Ответ на: комментарий от yyk

Как минимум - триггеры.

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

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

mythCreator
()
Ответ на: комментарий от mythCreator

Логика в бд - это не просто тригеры(которых стоит избегать, при неумении с ними общаться). ваш к.о.

anonymous
()
Ответ на: комментарий от mythCreator

а вообще, прочитав последний абзац, я понял, что зря отвечал.

anonymous
()

БЛ в хранимках === говно. Все аргументы уже привели вышеотписавшиеся регистранты.

deep-purple ★★★★★
()

Максимум, на что меня хватило в нашем недо-продакшене — это триггер на INSERT с процедуркой на pl/pgsql, которая передаёт это на обработку дальше

CREATE OR REPLACE FUNCTION cdr_to_json() RETURNS TRIGGER AS $$

    DECLARE 
        data json;

    BEGIN
    

        IF (TG_OP = 'INSERT') THEN
            data = row_to_json(NEW);
            INSERT INTO cdr_to_upload(data) values(data);
        END IF;

        -- Result is ignored since this is an AFTER trigger
        RETURN NULL; 
    END;
    
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION cdr_upload() RETURNS TRIGGER AS $$

    DECLARE 
        url      varchar := 'http://localhost';
        apikey   varchar := '';
        data     varchar;
        result   varchar;

        cdr cdr_to_upload%rowtype;

    BEGIN
    

        IF (TG_OP = 'INSERT') THEN

                    FOR cdr IN SELECT * FROM cdr_to_upload LOOP

                        data = CAST(cdr.data As text);
                        result := (SELECT content FROM http_post(billing_url, data, 'application/x-www-form-urlencoded'));
                        result := SUBSTR(result, 1, 4);

                        IF (result = 'true') THEN
                                        DELETE from cdr_to_upload WHERE id = cdr.id;
                        END IF;

                    END LOOP;

        END IF;

        -- Result is ignored since this is an AFTER trigger
        RETURN NULL; 
    END;
    
$$ LANGUAGE plpgsql;

create trigger voice_cdr_to_json after insert on tm_voice_cdr for each row execute procedure cdr_to_json();
create trigger sms_cdr_to_json after insert on tm_sms_cdr for each row execute procedure cdr_to_json();
create trigger gprs_cdr_to_json after insert on tm_gprs_cdr for each row execute procedure cdr_to_json();
create trigger cdr_upload_trigger after insert on cdr_to_upload for each row execute procedure cdr_upload();


Обрабатывать данные в БД — изврат, хоть иногда и быстрее.

annerleen ★★★★☆
()
Последнее исправление: annerleen (всего исправлений: 2)
Ответ на: комментарий от annerleen

триггер

В чём проблема реализовать «триггер» в бекенде? Всёравно ведь, поди, в транзакцию заворачиваешь эти несколько запросов. А если позднее понадобится дёргать эту херь с другого места без реакции на инсерт? Гибкость где?

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Там логика такая:

1. Апстрим (не подконтрольный нам) записывает в базу данные (тут это CDR — Call Detail Record), других вариантов нет;
1.1. База данных должна быть расположена на виртуальной машине в сети апстрима, по понятной причине (наш) бэкэнд находится совсем в другом месте;
2. Нам нужно отдать эти данные бэкэнду в любом виде на обработку и убедиться, что он успешно их принял (проверка на result == true);
Больше от этих данных нам ничего не нужно.


Для такой схемы есть лучшее решение?

annerleen ★★★★☆
()
Ответ на: комментарий от annerleen

лучшее решение?

Такая база должна быть обёрнута в АПИ из другого бекенда, с которым взаимодейтсвует наш бекенд. Тогда, тот АПИ-бекенд может быть расширен и изменён без изменения самой БД. Это гибко.

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Такая база должна быть обёрнута в АПИ из другого бекенда, с которым взаимодейтсвует наш бекенд

Оно уже.
Так как дёргать бэкэнд при инсерте в БД?
Не poll'ить же.

annerleen ★★★★☆
()
Ответ на: комментарий от annerleen

Так как дёргать бэкэнд при инсерте в БД?

В чём проблема из другого бекенда послать пакет по сети, когда он закончит инсертить?

anonymous
()
Ответ на: комментарий от annerleen

как дёргать бэкэнд при инсерте в БД?

Как обычно:

база <- апи-базы (бекенд бекенда, тут все транзашки и многозапросы за одно обращение) <- бекенд <- клиент

deep-purple ★★★★★
()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Ещё раз: есть база (постгрес), в неё инсертят со стороны.

Какими конкретно средствами ловить момент инсерта?

annerleen ★★★★☆
()
Ответ на: комментарий от annerleen

Какими конкретно средствами ловить момент инсерта?

Средствами драйвера БД, языка, на котором пишется прослоечное АПИ. Там же делается лок и/или критичное место оборачивается в транзакцию.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Так и не получил конкретики, в какую сторону копать.

annerleen ★★★★☆
()
Ответ на: комментарий от deep-purple

Такая база должна быть обёрнута в АПИ из другого бекенда, с которым взаимодейтсвует наш бекенд. Тогда, тот АПИ-бекенд может быть расширен и изменён без изменения самой БД. Это гибко.

В Lexus тоже можно запрягать тройку вороных, а возможность быстро заменить на шестерку вороных называть гибкостью.

Современные СУБД и есть сами себе бэкенд и сами себе API.

Пардон, сильно расстроился.

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

Deleted
()
Ответ на: комментарий от anonymous

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

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от anonymous

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

Но зачем ковырять клятый ракель, когда всё можно сделать проще.

баз должно вполне хватить главного разраба или архитектора, раз у вас даже дба нет.

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

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от Deleted

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

сами себе бэкенд и сами себе API

В том то и касяк, что они сами в себе. Вот где кони-люди смешались.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

случай «б» не использовать триггер, и доп случай «в» использовать, но другой?

Виноват, я кажется не понимаю этого вопроса.

Триггер - всего лишь отлов события. Внутри триггерной функции можно накрутить целый ворох обработок, в том числе условных.
У меня (обычно) первым делом, безусловно вызывается функция логирования события - записываю кто, когда, куда, что вставляет. Дальше, в зависимости от «кто» или «что» или «когда» могу дополнительно обрабатывать данные. Если по каким-то причинам надо сложно обработать данные, то можно для Postgres написать пользовательскую функцию на Си.

Поймали событие - и делаем, что хотим. Уж ради этого целую обёртку накручивать точно смысла не понимаю. Как-то ещё более/менее можно себе представить, что проект создается большой командой, в которой куча людей узкой специализации каждый (и, вполне вероятно, в своей узкой специальности - они все выдающиеся мастера). Так это снова не про плохое/хорошее техническое решение. Это про организационные вопросы реализации. В конце концов если у вас уже есть отличный конюх и замечательные вороные.

Deleted
()
Ответ на: комментарий от Deleted

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

crutch_master ★★★★★
() автор топика
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Надо бы тогда выключалку делать этому тригеру

Разве ALTER TABLE .. DISABLE TRIGGER .. это не оно? У меня это в сценариях backup/restore. Чтобы быстрее без логики сами данные вставлялись.

Ладно. Отстал. Просто мне казалось очевидным что, чем меньше прослоек, тем меньше точек отказа.

Deleted
()
Ответ на: комментарий от Deleted

Разве ALTER TABLE .. DISABLE TRIGGER .. это не оно?

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

Ладно. Отстал. Просто мне казалось очевидным что, чем меньше прослоек, тем меньше точек отказа.

Да это очевидно, как рулить только всем этим.

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от Deleted

я кажется не понимаю этого вопроса

Случай «а» для пользователя с ролью «А», случай «в» для роли «В». Пусть «А» обычный регистрант, при его действии, повлёкшим инсерт, что-то там делается. Пользователь с ролью «В» — модератор. при его аналогичном действии нужно сделать больше работы, чем для обычного пользака. Глупо просовывать в БД роли регистрантов (для этого примера), чтобы различать какая логика должна отработать.

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

для Postgres написать пользовательскую функцию на Си

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

deep-purple ★★★★★
()
Ответ на: комментарий от Deleted

чем меньше прослоек, тем меньше точек отказа

Это верно. Но только когда без фанатизма.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

Не получилось отстать ) Опять брови лоб скукожили от удивления )

Глупо просовывать в БД роли регистрантов

У меня именно так и есть. То что вы называете «регистрант» - это и есть настоящий пользователь Postgres. Соответственно, он и полномочия имеет только на то, что рулится самим Posgtres. Нет никакого «root»/«passwod» для общения между приложением и БД. Сразу эту дырку закрываем. И почему же это глупо??? Пароли нигде не хранятся - только у самих пользователей, которые они получили в конвертах под роспись в журнале.
Мало того - эта же моя система (под другую задачу) развернутая на AstraLinux, кроме Postgres'овских рулёжек пользователями еще и астровскими мандатными метками присыпана. Что же глупого-то в вынесении еще и механизмов авторизациии из приложения в уже готовые механизмы ниже уровнем?

Уже даже не расстроен. Уже совсем в недоумении.

Deleted
()
Ответ на: комментарий от Deleted

Не получилось отстать

Но зачем? Срач в development это хорошо и здорово.

crutch_master ★★★★★
() автор топика

Работал в шараге, где ВСЯ логика была внутри Oracle db. У них даже был самописный гуй для этого, без ооп и писать его было очень больно. Вообще, работать там было очень больно, ибо делать логику в хранимых это как ходить раком и задом одновременно. К тому же это все было очень медленно. Шарага занималась складами, кодобаза огромна и переписывать это никто не хотел. Так и писали код для новых клиентов на этом говне. Хорошо, что я оттуда сбежал.

Deleted
()
Ответ на: комментарий от Deleted

Гуй на дельфи 7 поди, весь код на колбеках кнопок и названия типа button6, checkbox8.

crutch_master ★★★★★
() автор топика

Вы сталкивались с таким?

Вот прямо сейчас пилим проект на оракловом plsql. Команда джавистов, plsql никто в глаза не видел. А у нас тут разбор xml, html, хитрая логика и всякая лепота. Ну ничо, весело. Когда проект удается сконпелять это уже праздник. С ужасом ждем наступления фазы интеграции.

morse ★★★★★
()
Ответ на: комментарий от yyk

другие пихают в базу разбор html

Я бы поотрывал кое-что тем, кто вообще хранит в базе html. Но к сожалению они от нас далеко.

morse ★★★★★
()
Ответ на: комментарий от morse

Вот прямо сейчас пилим проект на оракловом plsql. Команда джавистов, plsql никто в глаза не видел.

Но зачем?

crutch_master ★★★★★
() автор топика
Ответ на: комментарий от morse

plsql никто в глаза не видел

я представляю эти километровые портянки, где лок на локе и локом погоняет.

anonymous
()
Ответ на: комментарий от anonymous

Кстати, всё можно написать на яве. Оракл такое умеет.

crutch_master ★★★★★
() автор топика
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от anonymous

где лок на локе и локом погоняет.

Ну зачем же. Лок всего один. Глобальный. На входе.

morse ★★★★★
()
Ответ на: комментарий от morse

Требование заказчика. Агильность, девопсность, вот это все.

Дай угадаю. Заказчику 90 лет? Он не русский?

Deleted
()
Ответ на: комментарий от Deleted

Нет, не русский. На счет 90 лет сомневаюсь. По крайней мере все с кем я встречался были сильно моложе, лет 40.

morse ★★★★★
()
Ответ на: комментарий от yyk

одни ACID тащут в клиента

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

mythCreator
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.