Комментарии 18
Low-Code? Вроде бы описание как "много кода".
Low-Code преподносится обычно как "программирование без программирования" (в пределе No-code), типа рисуешь квадратики BPMN и оно "работает" (исполняется) в Workflow Engine. Тут другой Low-Code? Тогда VBA - это super Low-Code?
Мы делаем не No-Code, а Low-Code, что допускает программирование, но избавляет от большей части технической рутины. Просто на Workflow Engine-ах, к сожалению, не создать сложных систем для финтех, и обычно встречаются No-Code и Low-Code платформы с уже готовым функционалом (в какой-то области), где ты можешь поменять некоторые бизнес процессы workflow в одной конкретной инсталляции, но не можешь сделать свой новый продукт для продажи и лицензирования. Иначе говоря, это просто возможности для кастомизации готовых продуктов. Наша задача была сделать полноценный инструмент для создания новых продуктов, и сделать его максимально простым и освобожденным от технической рутины поставок, обновлений базы данных, API, верстки экранов и прочего. Да, конечно программировать на минимальном уровне "школьной программы" нужно уметь, но все остальное берет на себя платформа и если сравнить с полноценной разработкой с нуля (из разных библиотек), то уж это точно всем лоу-кодам лоу код).
Мы думали о создании редактора процессов, но решили пока не ходить в эту сторону. По нашим наблюдениям workflow больше "для продажи" работает и создает иллюзию, что с помощью мышки можно навозить квадратиков и создать новый продукт. Все-таки это больше для настройки под себя уже существующих решений.
Для индексных полей создаются дополнительные таблицы, но все основные таблицы практически состоят из одного запакованного поля.
Вот тут не понял. То есть все данные в виде bytea, которые считываются и "расшифровываются" на application server ? А как, например, посчитать сумму всех заказов по какому-то условию ? Это сначала должно считаться на томкат, где будет идти расчет ? То есть будет главная проблема ORM ?
У нас не ORM, мы не классы описываем, а "честные" таблицы, поля, связи, индексы. Запросы к базе через идут через наш API (where условия, как в sql, но одно-табличные), дальше система ищет сначала по индексам через стандартный sql к БД, потом данные поступают на application server (tomcat) и там происходит "дофильтрация" из начального where условия. При "дофильтрации" происходит распаковка на системном уровне (все верно), время распаковки просто мизерное, это очень быстро работает. Если правильно сделаны индексы, то вообще ничего не стоит, а если fullscan то и так и так плохо. Для больших отчетов правильно все выгружать в Data Mart какой-нибудь. Для нас безумно важно сохранить минимальное время простоя при upgrade системы и быть готовым к поддержке нереляционных баз данных.
дальше система ищет сначала по индексам через стандартный sql к БД, потом данные поступают на application server (tomcat) и там происходит "дофильтрация" из начального where условия. При "дофильтрации" происходит распаковка на системном уровне (все верно), время распаковки просто мизерное, это очень быстро работает.
Ну смотрите, давайте на конкретном примере. Например, при вводе заказа на закупку товаров вам нужно показать продажи определенных товаров, которые вы заказываете. Вот пример интерфейса из реального приложения (выделена колонка с продажами, а вводится количество к закупке на основании разной информации) :
Чтобы ее посчитать нужно условно сделать SELECT SUM(<продажа>) FROM <таблица с продажами> GROUP BY <товар> WHERE <фильтр по товарам>. В базовом случае это посчитается на самом сервере БД очень быстро, и на application server улетят уже конкретное количество продаж по каждому товару. Если я правильно понял про то, что Вы пишете, то у вас полетят целиком строки из таблицы с продажами, там они "разархивируются" и дальше идет непосредственно расчет на сервере приложений, группируя уже там по каждому товару.
Да, может это будут несколько миллисекунд, но это будет дополнительная нагрузка и на сеть и на CPU, которая будет в РАЗЫ больше, чем если считать это не выходя за пределы БД.
Понятно, что это не критичная нагрузка, если там десятки пользователей. Но, если несколько тысяч работает одновременно, то это просто кратный waste ресурсов. И так получается везде.
Собственно это и есть одна из основных проблем падения производительности в ORM (что приходится данные таскать на application server) из-за чего многим приходится делать винегрет из ORM и plain-SQL.
Прежде всего, спасибо за подробный комментарий.
На базе данных "SELECT SUM(<продажа>) FROM ... " рассчитается точно быстрее, чем на сервере приложений после распаковки. Вы абсолютно правы. Дополню только, что если поля входят в индекс (который Вы сами проектируете), то sum переложится на базу, но, все равно, все в индекс не положить и можно легко придумать запрос, который на базе будет выполнен быстрее.
Однако, чтобы затормозить сервер приложений, нужно реально очень много одновременных операций (что люди-клиенты или ежемесячные отчеты обычно не делают). В любом случае, у нас может быть много серверов приложений на одну БД, они stateless и легко параллелятся.
Жертва с хранением "запакованных данных" была принесена, чтобы максимально избежать простоя на апгрейде при изменении структуры данных, снять ограничения на изменение структуры таблиц и быть по-настоящему независимым от типа БД.
Куски системы, в которых нужна высокопроизводительная параллельная работа (онлайн транзакции, например) обычно проектируются индивидуально, и, скорее всего потребуют еще специальной системы хранения + что-нибудь типа Kafka впереди и так далее. Создать универсальный конструктор для таких задач невозможно, и это точно будет не low-code, а много-код, как писали выше. Для нашей платформы любые такие внешние системы вписываются органично, мы закрываем через API из абстрактными таблицами и дальше получаем единообразное описание бизнес логики + редактор экранов, что тоже экономит много ресурсов.
Надеюсь, я смог ответить на Ваш вопрос.
Выше я показывал пример createClientLoan, где создавалась новая ссуда у клиента, если Loan - абстрактная таблица и хранится где-то в "высоко-производительном" месте, то createClientLoan никак не поменяется. Для разработчика "бизнес-логики" все будет абсолютно прозрачно.
то sum переложится на базу, но, все равно, все в индекс не положить и можно легко придумать запрос, который на базе будет выполнен быстрее.
Не очень понимаю, как он переложится на базу. Например, у вас есть таблица с 2мя колонками - товар и количество. Нужно посчитать SELECT SUM(количество) GROUP BY товар. По количеству понятно, что нет никакого смысла строить индекс. То есть она будет заархивирована, так ? Но, если колонка будет "заархивирована", то вся таблица будет целиком на сервер приложений перегоняться, так ?
Жертва с хранением "запакованных данных" была принесена, чтобы максимально избежать простоя на апгрейде при изменении структуры данных,
Не очень понял. Например, вдруг понадобился какой-то индекс по какому-то полю. Чтобы мигрировать данные, то надо будет сначала достать из "заархивированных" данных колонку (причем это придется делать на сервере приложений ?). Потом записать ее в таблицу (а возможно и в старую, а это UPDATE с полной копией таблицы в PostgreSQL). И после этого еще достроить индекс. То есть, если ошибиться сначала со структурой базы, то потом будет очень больно ее изменять. И downtime будет еще выше.
Для нашей платформы любые такие внешние системы вписываются органично, мы закрываем через API из абстрактными таблицами и дальше получаем единообразное описание бизнес логики + редактор экранов, что тоже экономит много ресурсов.
Да, я понимаю, зачем нужен low-code. Просто в вашем подходе понятны минусы, а плюсы не очень очевидны. Если речь идет о масштабируемости, то она важна ну на очень больших объемах и загрузке. И там overhead за счет ORM и распаковки будет важен. А на относительно небольших объемах и масштабируемость не нужна.
У нас на открытой и бесплатной платформе lsFusion тоже low-code и тоже единообразное описание логики, редакторы экранов и прочее. Но там классическая база данных, где все выполняется на сервере БД. Да, есть вопросы с масштабированием, но мы делаем решения для розничной торговли с некоторыми таблицами более миллиарда записей, несколькими тысячами одновременно работающих пользователей и даже там пока не требуется масштабирования и все работает на одном сервере.
Уверен, что в 95% задач в том же финтехе также не требует масштабирования (достаточно асинхронной реплики для надежности). Плюс масштабирование не бесплатно (CAP-теорему никто не отменял). Соответственно, не очень понятно зачем жертвовать производительностью и мощью SQL-запросов, все перекладывая на сервер приложений и java-код.
Не очень понимаю, как он переложится на базу.
Поскольку мы сначала сами разбираем SQL и транслируем его на базу, а по полям, которые входят в индекс у нас создается специальная таблица (чтобы использовать механизм индексирования на базы данных), то мы и некоторые запросы мы вычисляем без распаковки, на обычном SQL. Поэтому, я и пишу, что если вдруг все поля входят в индекс, то распаковки не требуется вовсе.
Далее, Вы меня цитируете
Жертва с хранением "запакованных данных" была принесена, чтобы максимально избежать простоя на апгрейде при изменении структуры данных, ....
а, далее говорите, что индекс долго перестраивать, про индексы чуть позже, а тут имеется же виду добавление/изменение полей которые не входят в индекс, которых подавляющее большинство. К примеру есть карточки каких-то документов, продуктов, (на сотни полей) которые постоянно шевелятся, меняются задачи и постоянно нужны новые поля, справочники и прочее... Так вот при описанном подходе время обновление будет равно нулю. Вообще никаких изменений в базе данных при ЛЮБЫХ размерах таблиц.
Теперь про индексы. На маленьких таблицах (до миллиона строк), вообще никто не заметит разницы. На гипер-больших таблицах, индексы всегда долго перестраиваются, кстати, насколько я помню, это время не входит в downtime и база уже работает. Я имею в виду, что распаковка не вносит существенный вклад. Дальше Вы говорите, что если ошибаться, то больно менять, здесь я согласен, только мне кажется это при любом подходе так.
Да, я понимаю, зачем нужен low-code.
Большее спасибо, надеюсь кол-во единомышленников будет еще больше)
Просто в вашем подходе понятны минусы, а плюсы не очень очевидны.
Соберу плюсы/минусы нашего способа хранения в БД.
Минусы:
1) Дополнительное время на распаковку. Мы используем специальный алгоритм, который делает это максимально быстро. Мы, естественно взвешивали это решение и проверяли насколько замедляется. В обычной жизни - это миллисекунды, не замечает никто. Для высоконагруженных кусков нужно все равно специальное решение и часто не реляционнка, а что-то еще и/или еще что-то впереди ставить, и это уже точно не low-code.
2) Нет многотабличных запросов. Да, это следствие независимости от базы данных.
Плюсы:
1) Максимально уменьшаем время простоя на апгрейде при изменении структуры. Вообще нет ограничений на изменение структуры. Почти schemaless.
2) Независимость от типа БД
В этом смысле, PostgreSQL это "репетиция", перед NoSQL, посмотрим куда двинется рынок.
И там overhead за счет ORM и распаковки будет важен.
У нас не ORM. Я уже писал про это в начале. Мы не генерим "дикую" структуру таблиц по классам и свойствам. У нас способ хранения данных в запакованном виде, специальным алгоритмом.
Если речь идет о масштабируемости, то она важна ну на очень больших объемах и загрузке
А на относительно небольших объемах и масштабируемость не нужна.
уверен, что в 95% задач в том же финтехе также не требует масштабирования
Если про аппликационный сервер, то смотря чем он занимается, если он документы распознает и обрабатывает, то может достаточно скоро потребуется масштабирование. В любом случае, stateless сервер это почти must have сейчас, особенно если в контейнерах поднимать.
Если про базу данных, то когда оно понадобится, будет уже совсем поздно, поскольку архитектуру уже не поменять.
Соответственно, не очень понятно зачем жертвовать производительностью и мощью SQL-запросов, все перекладывая на сервер приложений и java-код.
Шаг осознанный, мы 15 лет писали под Oracle, для банков, большие решения. Все "посчитали" и пришли к этому. А еще нереляционнка, а еще обычных продуктов вообще нет разницы для пользователей, поскольку и так запросы выполняются за десятки миллисекунд. Тут больше борьба за тонкого клиента, как быстрее сделать.
Спасибо!
Поскольку мы сначала сами разбираем SQL и транслируем его на базу, а по полям, которые входят в индекс у нас создается специальная таблица (чтобы использовать механизм индексирования на базы данных), то мы и некоторые запросы мы вычисляем без распаковки, на обычном SQL. Поэтому, я и пишу, что если вдруг все поля входят в индекс, то распаковки не требуется вовсе.
Смотрите. Если таблица, где есть, например, поле клиента и суммы заказа. Вы предлагаете сумму заказа в индекс запихивать ? То есть вообще все числовые поля, ко которым идет SUM с GROUP BY запихивать в индексы ? Это же будет офигенный overhead.
Да, возможно для информационных полей и не так важно. Но опять же, для любой фильтрации с WHERE все должно лететь на сервер приложений, где фильтроваться ? Это же огромная дополнительная нагрузка и на сеть, и на CPU.
1) Максимально уменьшаем время простоя на апгрейде при изменении структуры. Вообще нет ограничений на изменение структуры. Почти schemaless.
Ну давайте только учтем, что в PostgreSQL ALTER TABLE ADD COLUMN и DROP COLUMN работает мгновенно на любом размере таблицы. Не вижу особых проблем с таким изменением таблиц (у нас, по крайней мере никогда не было).
2) Независимость от типа БД
В этом смысле, PostgreSQL это "репетиция", перед NoSQL, посмотрим куда двинется рынок.
Никуда он не двинется. Тут или ACID или NoSQL. Чудес не будет. CAP-теорему никто не отменял. Если вам важна транзакционность и целостность данных, то NoSQL в классическом понимании - это точно не вариант.
У нас не ORM. Я уже писал про это в начале. Мы не генерим "дикую" структуру таблиц по классам и свойствам. У нас способ хранения данных в запакованном виде, специальным алгоритмом.
Про генерацию структуры - это уже детали. ORM у вас в том плане, что вы имеете главный минус ORM. Это когда для любых вычислений надо данные доставлять на сервер приложений, что создает огромный overhead. Да, можно с этим жить, но я говорил об ORM именно в этом контексте. Вот, например, в lsFusion такой проблемы нет. Там практически все вычисляется на сервере БД за счет того, что вся логика "конвертируется" в SQL-запросы.
Если про аппликационный сервер, то смотря чем он занимается, если он документы распознает и обрабатывает, то может достаточно скоро потребуется масштабирование.
Ускоспециализированные задачи по распознаванию документов через tesseract всегда можно выделить в отдельную масштабируемую службу. В 95% случае речь идет об обычной OLTP нагрузке.
Шаг осознанный, мы 15 лет писали под Oracle, для банков, большие решения. Все "посчитали" и пришли к этому.
Но как я понимаю, главный вопрос был не в масштабировании, а в устранении semantic gap. Тут я понимаю, мы тоже в lsFusion сделали единый язык и для логики, и для построения интерфейса и для всего прочего, чтобы для разработчика вообще все было "скрыто", и он вообще не задумывался о базах данных, тонких клиентах и прочем. Просто в вашем случае выбор схемы реализации дает слишком большой overhead, что несколько ограничивает варианты использования.
Впрочем, не суть, такой подход тоже имеет право на жизнь и имеет свои преимущества (в частности масштабирование). Удачи Вам.
Но опять же, для любой фильтрации с WHERE все должно лететь на сервер приложений, где фильтроваться ? Это же огромная дополнительная нагрузка и на сеть, и на CPU.
Мы не предполагаем, что будут постоянные запросы пользователей, в нормальном режиме, с агрегациями по сотням тысяч записей для подсчета sum или чего-то еще. В этом случае, удобней вести счетчики.
Ну давайте только учтем, что в PostgreSQL ALTER TABLE ADD COLUMN и DROP COLUMN работает мгновенно на любом размере таблицы. Не вижу особых проблем с таким изменением таблиц (у нас, по крайней мере никогда не было).
Вернусь попозже, мне кажется есть много нюансов.
Никуда он не двинется. Тут или ACID или NoSQL. Чудес не будет. CAP-теорему никто не отменял. Если вам важна транзакционность и целостность данных, то NoSQL в классическом понимании - это точно не вариант.
Вот смотрите, https://www.foundationdb.org/, к примеру. Пишут про себя: "FoundationDB gives you the power of ACID transactions in a distributed database."
Про генерацию структуры - это уже детали. ORM у вас в том плане, что вы имеете главный минус ORM. Это когда для любых вычислений надо данные доставлять на сервер приложений, что создает огромный overhead.
По нашим подсчетам - не создает, а в случае постоянных агрегационных запросов пользователей на больших объемах данных, мы считаем правильно перегружать такие данные в дополнительную систему Data Mart, которая специально под это заточена. Иначе говоря, не стараться в одной структуре держать и работу с операционными данными и отчетами тяжелыми ее грузить. А уже к этой Data Mart системе делать обертки из абстрактных таблиц и получать единообразный доступ и тонкого клиента.
Впрочем, не суть, такой подход тоже имеет право на жизнь и имеет свои преимущества (в частности масштабирование). Удачи Вам.
Уверен, что у Вас хорошая система и на ней точно удобно и быстро разрабатывать, но у всех свой подход.
Вот смотрите, https://www.foundationdb.org/, к примеру. Пишут про себя: "FoundationDB gives you the power of ACID transactions in a distributed database."
Тут как в том анекдоте - "так и Вы говорите". Интересно, когда люди утверждают то, что они опровергли CAP-теорему (которая, на самом деле гипотеза :) ).
Мне приходилось пытаться реализовывать "распределенные транзакции" между разными системами. Так вот чисто их никогда не удавалось реализовать (да и по-моему чисто это сделать вообще невозможно). Как только вы зафиксировали транзакцию в одном месте, то нет никакой гарантии, что она завершится в другом месте. В частности, вот послали вы команду на фиксацию транзакции в удаленной системе, а вам не пришел ответ. Как узнать, в той системе транзакция зафиксировалась, или вам надо откатывать свою транзакцию, если нет ? Ответ же не пришел (например, из-за потери связи).
Насколько я понял, они сделали аналог map reduce кодом на курсорах. Если нет строгих требования по времени ответа такого АПИ, то почему нет.
Правильно ли я понял, что у вас экраны однотипны, как в ERP - гриды и формы. Поэтому могут декларативно описаны в JSON?
Да, если чуть подробней, есть набор компонентов для экрана - таблицы, формы, табы, графики, тестовый редактор, кастомная вставка на js, и т.д., в экране описываются их взаимоотношения, CRUD операции (стандартные по таблицам, в том числе, абстрактным или совсем кастомные), расположение и доп. акции. Для экрана есть редактор. В следующей статье распишу подробней, как устроено.
Спасибо за ответ. Много лет назад мы с командой похожим образом морду ERP делали, на базе ExtJs. Называли это скаффолдом. Сейчас термин low code значительно более предпочтителен, ибо маркетинг в ИТ никто не отменял. В общем, на ранних этапах разработка идёт влёт. Запара начинается как только появляются требования по кастомизации и оптимизации UX. Паретто как он есть - быстро показываем прогресс вначале, получаем одобрение и дополнительные ресурсы, и потом ими заканчиваем медленную кастомизацию.
Как мы делали Low-Code конструктор для Back Office. Часть 2 (Back-End и база данных)