×Закрыть

На каком уровне нужно знать SQL разработчику .NET?

Так уж посчастливилось, что на предыдущих работах практически не было задач связанных с RDBMS и SQL, либо такими задачами занимался специально выделенный SQL-разраб. В любой вакансии сейчас указано требование практического применения SQL, а у меня можно сказать только теоретические знания. Получается почти 8 лет опыта на платформе .NET и за это время с SQL получилось столкнуться раз 5 в задачах на пару часов. Реально ли так нужны знания RDBMS и SQL?

LinkedIn

Лучшие комментарии пропустить

На каком уровне нужно знать SQL разработчику .NET?

Если кратко, то на высоком. Лично я как .NET разработчик занимаюсь на 70% написанием кучерявых романов на T-SQL. Не вылезаю из Management Studio и профайлеров.

Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

На такому, щоб він був задоволений своєю зарплатою :)

Зависит от проекта. Очень сильно зависит от проекта.

нужно-ненужно это плохо поставленный вопрос, есть вакансии где нужно, есть — где не нужно :)
с моей колокольни — базы разнообразят жизнь, там довольно интересно, особенно после запросов к таблицам на 100+млн записей, и, ну удивление, платят за это больше

Надо или не надо сказать не могу (это очень субъективно), но могу сказать что знания эти полезные.

— Базы данных — это базовые знания, которые важно иметь. Кроме непосредственной работы с базой — это знание о том как эффективно работать с данными и типичные задачи которые так или иначе придётся решать (транзакционность, конкурентный доступ к данным, согласованность данных, и т.д.). Без самого языка SQL их получить не получится, так что он можно сказать что он тоже входит в категорию базовых знаний.
— Даже если придётся работать с Монгой или Кассандрой, знание реляционных баз поможет быстрее разобраться и построить эффективное решение. Наоборот — точно на могу сказать но мне кажется будет работать хуже.
— Даже если есть отдельный специалист, который пишет SQL код, эти знания могут помочь вам эффективнее взаимодествовать с хранилищем, быстрее решать вопросы с SQL разработчиком, дает возможность решить проблему самому или улучшить продукт благодаря оптимизации запроса.

P.S. Саму статистику использования реляционных баз данных вижу так:
1) Большинство проектом имеют хранилище данных
2) Большинство проектов из пункта 1 имеют хранилище сложнее чем просто файлы на диске
3) Большинство проектов из пункта 2 хранят данные в реляционных базах данных.

Даже если придётся работать с Монгой или Кассандрой, знание реляционных баз поможет быстрее разобраться и построить эффективное решение.

Скорее, помешает :)

В моем случае очень даже пригодился опыт исследования плана запросов, понимание индексов и подобных внутренностей. В NoSQL нужно больше задумываться о границах транзакций и атомарности, что приводит к более качественному дизайну или perpetual inconsistency вместо eventual consistency 😜.

часто наблюдаю когда люди строят 3 нормальную форму в монго ;(

Грустяшка, да. Но обновление референсов на другие документы (которые включают не только id, но и некоторые дополнительные данные, чтобы не вытаскивать другие документы без необходимости) тоже нетривиальная штука (казалось сначала), наша команда не сразу пришла к пониманию как это нормально делать. Event-Driven архитектура и eventual consistency очень адекватное решение для этого.

Вообще понятие «широкий кругозор» и «разнообразный опыт» оно не только в жизни помогает видеть лучше картину и принимать более взвешенные решения. В работе это тоже в полной мере, поэтому довольно глупо выглядят люди, которые вместо того, чтобы разобраться в чем-то нужном для своей работы говорят «это не моя зона ответственности! Я бекендщик, нафига мне ваши корсы?»

Я согласен с тем, что

опыт исследования ... внутренностей.

как говорицца «не пропьешь», но вот конкретные знания о том, «как правильно делать» переносятся плохо. Де-факто, проектировать модель данных для nosql отталкиваясь от «я сто раз так в постгресе делал» — это верный способ отстрелить себе все конечности. Самый свежак в моей коллекции такого рода граблей — это пассажир, который пытался прикрутить в кластер кассандры вторичный индекс по уникальному полю потому что он «сто раз так делал [в реляционках] и хуже точно не будет» (и вообще он локально потестил [на одной ноде, разумеется — для дев. окружения больше поднимать накладно очень] и всё отлично работает).

Я ни в коем случае не предлагал опыт реляционок портировать 1:1 на NoSQL 🙂.

а чо такого? тыжпрограммист или как?

Якось я один раз сусідській бабушці підключив Т2 тюнер, і вмить став ТВ експертом на вулиці. Такі діла.

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

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

Реально ли так нужны знания RDBMS и SQL?

Исходя из своего опыта очень редко встречаются разработчики которые хотя бы поверхностно знают базы и могу писать качественный код на SQL. Хотя формально для этого не нужно много учиться. Нужен лишь базовый синтаксис + понимание того как все работает, а это все покрывает одна книга в стиле Pro SQL Server Internals.

много учиться не надо. Всего одна книжка. на 800 страниц.
«генту можно поставить всего одной консольной командой» (ц)

Всего одна книжка. на 800 страниц.

И что? Это много?

Математический анализ. В 2-х томах. Ильин В.А., Садовничий В.А., Сендов Бл.Х.
М.: Изд-во МГУ. Ч.1: 2-е изд., перераб., 1985. — 662с.; Ч.2 — 1987. — 358с.
матанализ всего на 200 страниц больше.

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

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

не нужно много учиться
покрывает одна книга
SQL Server DBA

:)

Вполне достаточно на базовом уровне. Выборки, фильтрации, инсерты, апдейты и все такое. иногда джойны или функции. Для написания реально сложных скриптов с кучей релейшенов ядумаю уже должен быть DBA. Каждый должен заниматься своим делом. Full -Stack кстати это тоже иллюзия. Все равно ты что то будешь знать значительно хуже, а что -то значительно лучше. ИМХО, лучше быть профи в чем то одном: бэк-енд или фронт-енд. Но конечно, бэк-енд разраб все равно будет работать со фронтом и знать JS хотя бы на уровне дебага бэк-енд должен, но фронт-енд разработчика он все равно не переплюнет. И соотвестенно наооброт. (я о фронт-енд разработчике)

Так даже в простом нагнуть могут если не работаешь часто с SQL.
Например — зачем нужен HAVING если есть WHERE?

ответ на этот вопрос человек получит через 10 секунд после попытки использовать функцию..

Знание SQL и знание RDBMS это разные вещи. Натравить presto/bigquery на тонну данных

Я считаю что SQL очень помогает (как и регэксы и базовый pandas/numpy/scipy) для exploratory data analysis. А в работе разработчика необходимость такого анализа всплывает регулярно — перелопатить тонну логов, разобраться с причинами и т.д.

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

join/where/group by/having/аналитические функции (partition by)/подзапросы

8 лет опыта без SQL? Ты стебëшься?

Я таких людей знаю, очень редко, но бывает, буквально один из тысячи

Может ли разработчик считаться фуллстеком, если он не знает SQL?

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

И желательно представлять что происходит при конкурентном доступе в разных кейсах (read/write). Хотя если 100 человек в день пользуются проектом, то и не обязательно.

Индексы не только в RDBMS есть, а в практически любом хранилище :)

я в этом контексте и писал

Ну обычно чисто .Net не часто встречается, обычно помимо .Net еще приходится месить или js или t-sql, а то и все сразу, на чьей стороне будешь ты, выбирать тебе.
Как хорошо? Ну зависит от собеседования, что там тебя спрашивать будут и сколько денег предложат, дальше обычно всем пофиг.

помимо .Net еще приходится месить

CSS, HTML, JavaScript, TypeScript, SQL, T-SQL, PL/SQL, XAML, NoSQL etc

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

Бэкендщик всегда может найти проект по своим предпочтениям: с SQL или без, с JS или без, и т.п.
Без хороших знаний SQL бэкендщика могут не взять на какой-то специфичный проект, но может не очень-то и хотелось.
Доступных проектов море, и в наше время бэкендщику знания SQL нужны в минимальном объеме, потому что на большинстве проектов:
— либо только простейший SQL,
— либо есть выделенный database developer, который пишет весь сложный SQL,
— либо вообще не используется SQL, например потому, что все данные в noSQL или очередях, или в сторонних REST-сервисах.
Есть желание — можно учить глубоко. А нет желания, то и ладно.

Не не согласен, БД знать надо хотя бы на уровне как связать таблицы. Может пригодиться, когда велосипеды пишешь...

бэкендщику знания SQL нужны в минимальном объеме

подразумевает знание джойнов, тем более что любой ORM их тоже подразумевает.

Ну если за 8 лет не пришлось столкнуться то можно ещё 8 лет проработать и не столкнуться :)

На уровне junior database developer:
Джойны
Хранимые процедуры, вьюшки
Основы индексов, какие бывают и зачем
Что такое дедлоки и тд

хм... сразу к дедлокам минуя локи?
или слово страшнее звучит?

Разбираясь что такое дедлоки по пути узнаете что такое транзакции, уровни изоляций, блокировки и тд

блокировки

Это если сервер блокировочник, а если версионник то там совсем другие грабли.

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

Хранимые процедуры

а вот это точно не обязательно — можно знать что есть — но лучше если больше не знаешь — соотвественно не используешь

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

И ещё два плохих примера — агрегаты — ты скорее нуждаешься в olap, тригеры добавляют ещё больше проблем, чем решают — есть может от сил 1-2 юз кейса для них но они обычно крайне редки и там хранимки не нужны

О, да. Триггеры не нужны, консистентность данных для слабаков, для подсчёта рейтинга комментов заводим олап, который считаем приложением. Кто вообще эти бэдэ придумал с кучей явно ненужного функционала?
На самом деле хранимки + триггеры — самый простой и дешёвый способ поддерживать данные в нормальном состоянии (речь не про нормальные формы) и немного обезопасить их от ошибок в логике приложения.
Я не понимаю стремления вынести в код каждый чих просто так, по причине религиозных убеждений.

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

про нормальность я поправился. Я имел ввиду логическую целостность данных. Промежуточные итоги, счётчики, въюхи, валидация — это всё данные, и работать с ними удобно на уровне данных. И если у тебя триггер не даёт выполнить действие, то это действие и не будет выполнено даже если в коде кто-то закомментит (// todo раскомменть в проде!) проверку. И тебя не будут будить в 4 утра.

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

Почему прямо всё? часть проверок вполне может быть актуальна в пределах ноды. Например если данные пользователя у тебя на одной ноде.
Опять же, когда нужно будет масштабироваться горизонтально, то вопрос «надо ли знать эскуэль» отпадёт сам собой — кроме эскуэля и триггеров там будет купа новых модных проблем. И человек, способный нормально организовать работу этой системы, наверняка будет знать и эскуэль, и триггеры, и транзакции и всё вот это вот всё.

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

согласен со всем, кроме использования слова «крайний». Только ситхи возводят всё в абсолют.
Когда сервис строится и активно меняется — обычно используется одна бд, вынести в которую логику, относящуюся к данным, вполне, имхо, логично. Схема данных меняется значительно реже обрабатывающего эти данные кода, потому такой способ позволит полагаться на целостность данных. Да, в будущем возможно понадобится переделать это. А может и не понадобится. Не каждая птица доживёт до момента горизонтального масштабирования.

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

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

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

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

Поправил :)

Реляційна бд маштабована горизонтально ? Не бачив.

Попробуй посмотреть на MySQL или Postgres. Даже Oracle и MS SQL якобы масштабируются горизонтально, но это стоит одуренных денег.

Но я говорил про горизонтальное масштабироваение сервисов, а не бд.

Значит слабо разбираетесь в вопросе. На чтение скейлиться вообще элементарно, на запись сложней — клиентская либа и будет почти тоже самое что монга, но даже здесь уже есть решения поддерживающие multi-master write конфигурацию со стороны сервера, что ушло куда подальше чем многие nosql решения по типу монги редиса и тд.

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

Поэтому сиквел с репликацией и клиентским шардированием будет та же самая монга с шардами только без chunk split и redistirbution.

без chunk split и redistirbution

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

Т.е. придется самому присать?

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

А реляции между таблицами?

Так же как и в монго — решается на этапе дизайна и имеет те же ограничения, монго тут ничего предложить тоже не может. $lookup тоже не работает для шардированных коллекций.
По факту это не есть техническим ограничением для шардирования как такового, единственная разница делается на клиенте и закладывается на этапе дизайна.

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

берется ключ партицированния на самом верхнем уровне иерархии, а реляции на более низком дизайнятся. например country id, а все реляции подчиненные идут — регионы, районы, города, районы, магазины и т.д.

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

Я про добавление нового шарда в кластер.

А что mongo умеет на сервере делать consistent hashing? мне казалось там такой же механизм партицирования как я описал выше — hash/range partitioning. По сути полное репартицирование, что там что там.

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

Это не надо делать самому, как я сказал для этого есть готовый тулинг.
docs.microsoft.com/...​-overview-split-and-merge

Значит я не правильно понял формулировку «шардинг на клиете». Выглядит очень страшно, если честно. Мне бы очень не хотелось в такое ввязываться. И очень дорого. Лучше решать на уровне дизайна приложения и выделения адекватных поддоменов.

Azure SQL кстати очень выгодное по деньгам решение — у них есть такая штука как elastic pool(не уверен но помоему у AWS такого нет). платите деньги за набор баз в различных датацентрах и платите pay as you go полностью под нагрузку на все эти базы сколько вам надо из общего пулла проплаченных ресурсов ресурсов аллоцируется оно(даже на разные регионы). при правильной конфигурации будет максимально экономно и с минимум головняка. попробуйте такое сделать с наборотм датацентров в он-прем и посчитать солько это будет стоить при сопоставимой нагрузке. Мы, правда, не юзаем шардинга для сиквела. нам просто оно без необходимости. но с такими возможностями я уверен что шардинг там с точки зрения денег вообще не проблема(будет гибче и стоить точно меньше чем dynamo, cosmos и тому подобное). С точки зрения заморочек — уже надо смотреть.

При такому сценарії немає різниці взагалі rdbms чи mongo взяти. Розбити одну таблицю по базах і на клієнті вирішувати куди запрос посилати, хоча в mongo це вирішує ніби не клієнт ? Але це дуже обмежений сценарій для sql у порівнянні з тим, що ми звикли з ним робити.

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

Читання-дзеркалювання-репортинг це не те горизонтальне маштабування, яке малось на увазі, як я розумію, не розбивання даних по нодах-шардах.

в сиквеле это делается на стороне клиента спокойно, как я описал выше.

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

не очень понимаю чем тут монго поможет принципиально больше например. Самые «невелосипедные» решения для этого dynamo, cassandra, riak что умеют в multimaster. Беспроблемно будут решаться задачи, что нормально ложатся на использование «типов данных где отсуствуют конфликты» (CRDT), все остальное это либо потеря данных либо ручное разрешение конфликтов даже в multimaster. Подходящего простого решения тут просто не существует, для задач что чуть более сложные чем посчитать общее количетсво лайков.

Мы про multimaster или шардирование на клиенте? А то я, наверное, потерял нить дискуссии.

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

Это два совсем разных подхода. В multimaster я пока не вникал, поэтому не могу ничего умного сказать на этот счет 🙂.

Но ведь реляционные базы данных вы должны были проходить в университете

Теория реляционных баз данных, по моему так называется...

Дуже залежить від проекту, вистачає таких де більша частина логіки з тих чи інших причин винесена в базу даних. Кілька років працював на проекті де 70% часу займався саме SQL.

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

повезет
монга или касандра

це жарти такі?

Не, эт такие базы данных. Некоторым везет с ними работать вместо ковыряний в SQL.

Если схема фиксирована, зачем их использовать.
Да и в том же cosmosdb можно использовать монго как способ хранения, а запросы делать с помощью sql-like синтаксиса, так что ковырять sql нужно будет дальше.

Если схема фиксирована, зачем их использовать.

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

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

кхм-кхм

любой солдат хочет стать -генералом- (архитектором)

Ну вот я моделирую с помощью dsl, думаешь мне не надо знать как написать запрос?

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

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

я нехочу схемы бд

а зря )

я хочу моделировать предметные области.

У нас уже был спор примерно на эту тему :)

Некоторым везет с ними работать вместо ковыряний в SQL.

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

Я иметь в виду схемы. Моделируя предметную область не хочется зависить от ограничений БД или думать по каким табличкам что куда разложить. В этом плане NoSQL или EventStore идеальны.

Моделируя предметную область не хочется зависить от ограничений БД

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

Так я и не завишу, я уже больше двух лет счастливый пользователь MongoDB 😜.

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

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

счастливый пользователь MongoDB

бугагашенька, знал я таких счастливчиков которые после года активного использования монги в проде начинали смотреть на традиционные СУБД
ведь внезапно оказывалось, что данные не только писать нужно, но и читать и тут все становилось печально — в то время у монги даже джоинов не было (хз завезли ли их в монгу сейчас).
ЗЫ в целом против монги я ничего особо не имею — такой себе нишевый продукт, который в своей нише пожалуй неплох.
а вот тех, кто пытается сложные базы запихнуть в монгу мотивируя тем что не надо париться со схемами, простотой масштабирования и т.д. — надо гнать сцаными тряпками.

Бугагашенька 😁. Но опыт у все разный, это да.

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

Кассандра хороша, когда нужен быстрый доступ и масштабирование. Опыт все равно намного интереснее, чем с SQL. Но я с ней так плотно, как с MongoDB или EventStore не работал.

Опыт все равно намного интереснее, чем с SQL

Как и любой новый опыт, полагаю. Просто потом новизна уходит, а проблемы нет :)

Ок, кассандру вычеркиваем за недостатком опыта. MongoDB и EventStore?

Ничего не могу сказать :) Монгу юзаю для пет проектов лет 7 или 8, никаких проблем — как один раз встало из коробки, так и живет (разве что на WiredTiger энжин переехал, как только завезли). Но поскольку нагрузки серьезной нет то и на грабли наступать негде. ИвентСтор — темный лес.

Redis например быстрее Mongo
но это тоже ничего не занчит, зависит от задачи (и бюджета)

Но поскольку нагрузки серьезной нет то и на грабли наступать негде

вот

Редис же не база а ин-мемори стор вроде.

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

Но лично я часто вообще отключаю персистентность и использую как чистый in-memory store для кешей и вспомогательных штук отличных от key-value: lists, sorted sets.

Если же говорить о логике в нём, то да, можно прямо в хранилище выполнять lua скрипты, вроде круто, но, redis однопоточный и пока крутится логика одного соединения — остальные ждут, как в nodejs при cpu bound нагрузке (если без worker’ов).

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

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

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

ну вот.
на синтетическиз тестах и отдельных задачах редис хорош.
но то же может SQL Server
вопрос к задаче, архитектуре и конкретному архитектору

отдельных задачах редис хорош

угу, он хорошо дополняет более традиционные решения.

Как говорил Лесь: «лєбєдь красівий, як лєбєдь, а обізяна, как обізяна» )

как чистый in-memory store для кешей и вспомогательных штук

Так редис в 99% так и юзается.

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

Everything’s a dildo if youre brave enough.

Кассандра — фигня. Аероспайк используйте когда надо быстрый доступ. Кассандра доступ как раз не гарантирует(легко 0.5с может быть).

В этом плане ... EventStore идеальны

«Не-не-не, Дэвид Блейн!» ©

Участвовал я в одном проекте с event sourcing; так вот не было там бОльшей боли, чем изменение схемы event’ов.

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

Думаю, любым интстументом можно выстрелить себе в ногу, если не уметь пользоваться.

миграция уже сохранённых в event store событий
перегенерация кода на основе изменившейся схемы событий

Звучат немного странно, но слышал, что некоторые так делают.

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

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

У меня после того проекта сложилось ощущение, что event sourcing — это не для проектов, где требования меняются и дополняются на ходу.

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

Да ладно. Вы забыли, как у вас от сиквела в универе пригорало? Просто вы к нему привыкли уже.
А так одинаково

Не знаю, как от сиквела может пригорать. Он логичен от и до.
Это же не js чтобы с него пригорать.

Почему от него должно было пригорать?

Да зайдите на основы БД в любой универ и послушайте.
Не должно. Просто необычно. А вы уже забыли как это необычно и вам уже нормально.

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

А мне больше всего не нравится, когда к SQL применяются все эти гибкие технологии разработки софта. В итоге «а давайте добавим это поле», а через неделю, а давайте сделаем его множественным, а потом а давайте добавим возможность иметь множество полей и т.д.
Именно поэтому всякие монги и стали популярны в стартапной среде, потому что SQL хорош только когда заранее четко обозначено ТЗ, которое можно разложить на модель базы, нормализовать ее, оптимизировать, прикинуть нужные индексы и подход к дальнейшему масштабированию.

В итоге «а давайте добавим это поле», а через неделю, а давайте сделаем его множественным, а потом а давайте добавим возможность иметь множество полей и т.д.

за останні роки майже всі СУБД адаптувались до такого і додали тип даних JSON для таких речей

тобто, де треба фіксована структура — робимо таблички, поля, зовн ключі

а всі кастомні поля виносимо в JSON і граємось як хочемо

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

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

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

А коли разом з вимогами, що радикально змінилися, радикально змінюється і об’єкт, який вже збережений в документах mongі, вам, типу, легше ?

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

Это проблемы преподавания, а не сиквела

8 лет уже пишу на C#, изредка на Java, за все время не написал ни одной строчки на SQL по работе.

Так что может быть от моего случая до того, что у вас будет в коде 70% SQL и 30% остального кода (кодокоментарии не считаем).

Думал я один такой. За все время проработал в 3 конторах и нигде не было хотя бы 5% SQL, повезло же..

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

Не .NET + SQL Server в моєму випадку, але був в чомусь аналогічний проект Java + Oracle, на який мене покликали як дб дева. Отже, в двох словах — довелося розгрібати що понаписували джавісти без знання баз даних. На хвильку — логіка «на сторед процедурах в базі плюс простий виклик з джава аплікухи» відпрацьовувало в десятки разів швидше, ніж «все на джаві, тільки кінцевий результат записуємо в базу». Джавісти аргументували підхід тим, що так буде кросплатформенно, тобто встане на будь-яку базу (ну воно-то встане, тільки потім швидко ляже). Понаписували до мене стільки, що для мене вистачало на стабільний підробіток протягом декількох років(offtop_politota_begin), поки СЕО не самозашкварився, коли запросив поїхати в окупований Крим, після чого я припинив співпрацю зі свого боку(offtop_politota_end).

На хвильку — логіка «на сторед процедурах в базі плюс простий виклик з джава аплікухи» відпрацьовувало в десятки разів швидше, ніж "все на джаві, тільки кінцевий результат записуємо в базу«

Ооо, сейчас нам расскажут о том, как правильно писать ентерпрайз.

Вангую, что через пару лет на ДОУ появится комент ноунейма в стиле «...позвали порефакторить старый монолит, потому что архитектура не позволяла развивать продукт дальше. Оказалось, что предыдущая команда написала все нормально, а потом позвали СУБД-джедая, который сломал всю архитектуру, вырубил топором половину бизнес-логики и запихнул ее в хранилки на PL-SQL, похожие на заклинания на древнегномских рунах, читая которые я вызывал сцотону раз в пару минут».

предыдущая команда написала все нормально

Ага, нормально — поки кількість записів в базі вимірювалася десятками. Коли виросла до мільйонів, то користуватися стало неможливо. Тестування з заповненням dummy data, highload? Ні, не чули. Написав процедури, віддав — вирішуйте самі чи їх використовувати, на прод ставити прав не було. В результаті ще через пару років до мене зверталися за допомогою, однак (читати комент вище про політоту) вже більше з ними не хотів працювати.

Ага, нормально — поки кількість записів в базі вимірювалася десятками.

Не утрируй. С десятками миллионов у меня например все ок. Без хранилок. Будут миллиарды — вот тогда приходи :)

Коли виросла до мільйонів...

Если вы «выросли до миллионов» — это не хайлоад. Это просто у вас появились хоть какие-то данные.

...то користуватися стало неможливо.

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

Подход «давайте запихнем логику в хранилки» большинством здравомыслящих людей рассматривается как зло.

Будут миллиарды — вот тогда приходи :)

хилый энтерпрайз

Я честно, хотел сначала написать триллионы, но потом как-то постеснялся :)

Ок, в них були джавісти без якогось поняття в базах, крім елементарного. Прийшов я, 9y+ в базах, але з елементарним поняттям в джаві. Напевно СЕО повинен був шукати щось середнє, джавістів із знанням баз хоча би на рівні middle, а також найняти архітектора для цієї системи.

Подход «давайте запихнем логику в хранилки» большинством здравомыслящих людей рассматривается как зло.

Так як мене покликали пофіксити вузькі місця і я з цим справився, і після цього мені були готові давати замовлення далі, то вважаю що свою роботу я виконав, при тому що не вважаю свою позицію єдино вірною.
+ Так як я крім флуду і тролінгу намагаюся винести раціональне зерно, то поясніть свою позицію детальніше, будь ласка.

то поясніть цю позицію детальніше, будь ласка.

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

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

Вот хороший пост, например
dou.ua/...​ery-mysql-server/#1688338
И вообще тред хороший.

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

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

холивар

Ок, під це визначення підходить ідеально.

Вот хороший пост, например
dou.ua/...​ery-mysql-server/#1688338

Тут єдине раціональне зерно — що в mysql дійсно потрібно дропати і створювати процедуру для її зміни. Нижче солюшн — робити це через лоадбалансер, тобто спрямувати запити на інший сервер з потрібними змінами. Я не дуже вмію в джаву, та здогадуюся, якщо бізнес-вимоги не допускають даунтайм для зміни процедури, то і зміни в коді джави на ходу теж не ок. Тоді справа не в тому, де в нас вся логіка, а у вмінні писати читабельний код, читати чужий код, робити зміни в проді без даунтайму.

Тут єдине раціональне зерно

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

Дальше даже продолжать не хочется. Пишите энтерпрайз внутри баз.

ти образивсі? :)

К меседж брокерам подключайтесь сиквелем

кожен інструмент для свого діла

пишите ДДД абстракции

після цього якось не заходить про «слой техномагии на неведомом языке» і про «нормальні мови»

Создавайте процессы параллельной обработки данных внутри хранилок

вони для цього не призначені
а от зробити так, щоби сервер *сам* організував паралельну обробку даних — вже можливо, якщо конструкція сервера це передбачає взагалі

вебсервером тоже пусть бд будет

вона для цього не призначена, кожен інструмент .... (див вище)
але є, приміром, такі штуки — postgrest.org

ти образивсі? :)

Нэ. Просто не хочу ломать копья.

вона для цього не призначена

База — хранилище.
Она вообще не предназначена для логики. Она предназначена для «сохрани» и «дай».

не хочу ломать копья

Можна зашитися ментально в одному бізнес-кейсі і не хотіти знати інших кейсів. Якщо так спокійніше жити — будь ласка.

База — хранилище.
Она вообще не предназначена для логики. Она предназначена для «сохрани» и «дай».

Подам приклад. Є база даних з банківськими операціями. Всі дані в базі, сторонніх джерел нема. Логи авторизації в інтернет-банкінг також в базі. Є ціль — вичислити спроби фроду. Отже, ми беремо дані з бази, робимо певні обчислення і записуємо результати в цю ж базу. І тут питання: чи потрібні нам для обчислень якісь аплікухи, крім засобів самої бази? Джавіст скаже: обов’язково — бо хоче щоб таски падали на нього. Дб дев скаже: не потрібні — бо також хоче, щоб таски падали на нього.

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

Решение с базой напрашивается как бы само собой, но количество таких фрод проверок растёт, нагрузка на базу по cpu растёт — масштабируем вертикально пока железка позволяет. Всё равно начинаем упираться, ok, давайте slave реплику, потом ещё одну. Если база взрослая то по лицензиям начинаем нормально платить. Для мастера каждая реплика тоже не бесплатно получается.

Имхо, главная проблема с логикой в базе — это масштабирование.

еще всякие инмемори тут всплывут
в сравнении с No-SQL (Mongo / Redis) разница будет в стоимости и предпочтениях разработчика

Разница еще в схемах деплоя. Мы вот взяли хазлкаст. Он может работать без мастер-слейв схемы.

Подам приклад.

Вы не понимаете, о чем вам говорят, и не хотите понимать. Что типично для фанатов логики в базе.

робимо певні обчислення і записуємо результати в цю ж базу.

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

Логи авторизації в інтернет-банкінг також в базі. Є ціль — вичислити спроби фроду.

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

І тут питання: чи потрібні нам для обчислень якісь аплікухи, крім засобів самої бази?

Да, нужны. Просто вы этого не понимаете.

Джавіст скаже: обов’язково — бо хоче щоб таски падали на нього.

Джавист ложил на таски. Джавист знает, что любая интерпрайз система обрастает с течением времени интеграциями. И еще джавист видел адовы поделия ДБА-гуру, которые пытаются имитировать нормальные интеграции какими-то сумасбродными велосипедами. Вместо человеческого меседж брокера начинаются темы «а давайте мы вам в табличку будем кидать, а вы ее читать раз в минуту».

+ 100500
Да и транзакции тоже не нужны. Бо сегодня у нас бд, а завтра сага на кафке, то зачем привязываться гвоздями к этому? Внешние ключи туда же, вдруг у нас сущности в разных шардах когда-то будут. Триггера вообще неконтроллируемое хтоническое нечно. Так что не паримся, берём майисам (скорость!), и реализуем всё нужное нам в коде. Ну, там, дозаполнить 1000 сущностей деталями — всего 1000 запросов в бд, херня для современной техники. Зато в будущем, когда мы поднимем 500 шардов и баллансировщик, все эти запросы выполнятся параллельно.

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

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

Внезапно, даже в этом случае нужны :) только не распределённый two-phase commit, конечно:

microservices.io/...​transactional-outbox.html

transactional outbox это обычная acid транзакция в рсубд, причем оно к кафке или сагам? при моделировании бизнесс операции на кафке вообще нет необходимости делать описанное в этом подходе, да и не сделаешь это никак. Точное так же как и 2PС кафке не нужен.

При том, что эта транзакция по итогу гарантирует гарантированную доставку domain events, даже если микросервис упал после завершения транзакции, но до отправки доменного события в message broker

При подходе, когда кафка хранит события, на которых моделируеться бизнесс операция, события отправленные в кафку и есть базой данный. там никто не пишет в еще одну базу данных что-то что надо писать атомарно вместе с ивентом.
Вот этот подход, transactional outbox используют там, где есть база данных на запись, кроме самих доменных ивентов. Дичь еще та — обычно такого надо поменьше делать. Transaction outbox вообще не для ивент сорсинга был придумал, а как описано что бы в транзакции поменять данные и отпаблишить на брокер событие другим получателям.

Если вы Кафку используете как event store, то да, в этом случае ни ACID, ни transactional outbox, конечно, не нужны.

Только это очень плохая идея. Кафка, например, не умеет в optimistic concurrency. Да и как восстановить текущее состояние сущности по ивентам из Кафки? Или сущность будет eventually-consistent-на? Как тогда она будет гарантировать правильность принятия решений.

Как тогда она будет гарантировать правильность принятия решений.

Если ты делаешь например систему по cqrs то write источник или event store не допустит разрушения агрегата за счет контроля его ревизии, в kafka же гарантии абсолютно аналогичны но подход другой, все конкуретные запросы пойдут в обработку и все эти запросы поступят например на сервис работы со складом — если на складе один айтем, его заберет первый, кто отправил запрос и получит ответ с подтверждением операции, все остальные получат из стрима сообщение о неудачном выполнении операции, если окажется что например payment service не даст тому что забрал со склада последний товар его оплатить из-за нехватки денег, прийдет отказ оплаты на сервис магазина , а он в свою очередь отправит ивент и вернет item на склад — (это и есть саги).
Поскольку в кафке есть транзакции на запись в том числе между стримами и гарантия exact once delivery + однопоточность и порядок доставки на consumers, где и содержится вся бизнес логика валидации — это дает такие же гарантии консистентости данных в distributed среде, как ты бы получил работая с рсубд и acid транзакциями. Единственное отличие асинхронность получения подтверждения, хотя учитывая возможности дизайна таких систем в большинстве случае они куда более realtime и имеют меньшую latency чем залоченные ресурсы в субд особенно под нагрузкой.

Что-то я запутался. Давай сначала определимся откуда мы знаем, что остался один айтем на складе, если у нас нет БД.

А потом как мы обрабатываем два параллельных запроса на резервацию этого айтема.

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

Что-то я запутался. Давай сначала определимся откуда мы знаем, что остался один айтем на складе, если у нас нет БД.

Юзаешь kafka streams, что по id вернут состояние агрегата из соседнего стрима.
kafka.apache.org/...​reams/kstream/KTable.html
KTable is an abstraction of a changelog stream from a primary-keyed table. Each record in this changelog stream is an update on the primary-keyed table with the record key as the primary key.
Должно вызывать правильные ассоциации :)

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

Одним в рамках партиции. В кафке это ключевая концепция дизайна — в рамках consumer group каждая партиция работает однопоточно, но за счет того, что все партиции обрабатываются параллельно система скейлиться горизонтально и там не возникает concurrency.
почитай литературу, где описывают моделирование бизнесс операций на стримах, судя по всему ты не много сталкивался с kafka и делаешь выводы, о том где кафку нельзя юзать из дешевых блог статей на medium’e. Почитай литературу соответвующую, на гитхабе\лабе можно найти примеры систем на стримах. Вот, что стоит почитать по этой части:
Ben Stopford — designing event driven systems concepts and patterns for streaming Services with Apache Kafka

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

Вообще, да KDB рулит. Make distributed monolith great again.

И это должно как-то скейлиться? Или я что-то снова упускаю?

Все реактивные и real-time системы полагаются на аналогичные подходы — акторы, stream processing все real-time предполагает неконкурентную работу с данными в одном потоке :) так что я думаю, что вопрос скорее риторический.

Make distributed monolith great again

www.linkedin.com/...​rchitecture-stefano-rocco

Один из самых правильных примеров микросервисов ‘по эвансу ‘ с инкапсуляцией доменных ивентов внутри микросервиса lose coupling в общении между микросервисами, и бизнесс операциями на конкурентных данных — с объяснением паттернов в статье приложен код. все на Kafka:)

Понятно. Я думал, что я что-то важное пропустил. Актор — это аналог агрегата в DDD, тоже представляет собой границу транзакции, одну сущность. Если в кафке идти этим же путем — получится, что на каждую сущность нужно создавать отдельный топик. ES так умеет by design, в кафка — нет, она не сможет с таким подходом скейлиться достаточно хорошо. Поэтому там обычно пишут в один партишен все события всех агрегатов заданного типа. Но если это использвать как single source of truth и ksql, нужно будет все обрабатывать в одном потоке, что будет неверояно медленно. А параллельно процессить не получится, потому что кафка не умеет в optimistic concurrency. Но я это все на medium прочитал, так что можно серьезно не воспринимать.

Поэтому там обычно пишут в один партишен все события всех агрегатов заданного типа

Это не есть партицирование :) поэтому все выводы заведомо ложные. Если тебе это правда интересно — почитай разберись попробуй прототип сделать и сделай выводы для себя. Партицирование, в том числе в Кафке работает так, что тип агрегата один, весь набор инстансов агрегата сегментируется и каждый сегмент процесится отдельно и параллельно. Веришь или нет, но на Кафке это делают только так и ни как иначе:)

Если в кафке идти этим же путем — получится, что на каждую сущность нужно создавать отдельный топик

Обычно делают один топик на микросервис можно и больше, надо смотреть по ситуации, главное что в Кафке есть транзакции на запись между топиками — так, что если надо записать в более чем один топик консистентно это ничего не мешает сделать и не требует велосипедов типа outbox .

Да, я описывал топики. А сколько партишенов ты делаешь на топик? Какой уровень параллелизмами системе?

Я не юзаю кафку. По аналогии с тем, что мы делаем — если бы была Кафка было бы от 100 до 1к партиций на топик(на машину не больше 200 партиций бы попадало) что бы делать наши типичные задачи(в основном вводы новых компонентов и перепрогонка стрима для просчета read данных).

На всякий случай, если кто-то еще читает, www.linkedin.com/...​eded-maria-hatfield-phd/

For most implementations you want to follow the rule of thumb of 10 partitions per topic, and 10,000 partitions per Kafka cluster. Going beyond that amount can require additional monitoring and optimization.
100 до 1к партиций на топик

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

Это не проблема Кафки в нашему случае это медленные консьюмеры.

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

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

А для построение read-model-ей кафка подходит идеально, да, но саги тут ни при чем.

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

Вот nice use case — под твой случай как раз по поводу ложности таких выводов.
medium.com/...​sing-platform-a3ee651812a

Delivery/Processing semantics: some use case is ok with losing some events in the pipeline, while other ones may require much higher durability guarantees. Some stateful streaming job also expects exactly-once processing guarantee where the computed states should always be consistent.

Job State: ranging from complete stateless parallel processing to jobs requiring 10s of TB large local states.

~500 billion events and ~1.3 PB per day
~8 million events and ~24 GB per second during peak hours

However, our story does not end here. We still have a long journey ahead of us to fulfill our platform vision
Microservices event sourcing architectural pattern

Зы: Но почему-то все читают это бредовую статью что Кафка не для ивент сорсинга вместо почитать тех блог нетфлткса.

Ок, почитаю, на досуге. Ты говоришь делал какой-то PoC, есть где посмотреть?
Я бы с тобой порисовал у доски, мне лениво сейчас писать простыню разбора сейсов с concurrency. Как гарантировать, что сага не будет выполняться параллельно, если сообщения от сервисов ей будут приходить из разных партиций разных топиков с разными ключами. Пусть даже кафка гарантирует exactly once processing (не delivery).
Да и тот факт, что все внутренности всех сервисов будет доступны всем остальным сервиса, а не только публичные контракты. Это превратиться в месс очень бытро. Будет чудовищный распределенный монолит. Хз как такое можно рекомендовать в качестве хорошего архитектурного решения.

Хз как такое можно рекомендовать в качесве хорошего архитектурного решения.

Просто ты видать не внимательно выше читал, вот отсыл к примеру с пояснением паттернов, когда доменные ивенты инкапсулированы внутри микросервиса, пример к тому же саги требущей строгой консистености — со схемами, кодом на кафке
dou.ua/...​rums/topic/28953/#1729402
Я тебе также выше сбросил литературу по поводу волнующих тебя вопросов консистентности.
По поводу событий кокурентности разной природы:
— списание товара на складе
— отгрузка пользователю
если они идут потоком в одном топике с партицированием по productid то конкуретности нет. Сама сага работает с набором топиков — например из payment топика она может получить reject оплаты и сгенерировать событие в топик с которым работает склад. Консистентность достигаеться тем путем, что запись об ошибке в топик откуда получит ответ пользователь и роллебек в топик склада пишется в одной транзакции(что кафка умеет делать).

По поводу консистентности — предлагай сложные use cases, посмотрим насколько их сложно смоделировать с кафкой.

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

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

Ты конечно извини, но я отвечу тебе твоей же цитатой

судя по всему ты не много сталкивался с kafka и делаешь выводы, о том где кафку нельзя юзать из дешевых блог статей на medium’e

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

Ты конечно извини, но я отвечу тебе твоей же цитатой

ооок.., больше линки на документацию/литературу от вендора и отсылы к use cases типа нетфликс использовать не будут в дискуссия с тобой, правда думал это представляет для тебя какой-то авторитет.

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

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

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

у тебя слабая аргументация, если бы я согласился с ней — я бы слышал, а так я не слышу выходит?

Вот аргументы что обсуждались:
— kafka не имеет optmistic concurrency; как оказалось он и не нужен, что бы работать с консистентыми данными;
— как подтверждать бизнесс операции — однопоточная обработка данных + транзакции на запись между стримами, смотри Ben Stopford
— кафка экспоузит доменные ивенты ддругим сервисам, смотри пример с линкедина — integration events + snapshot propagation + event command mapping = loose coupling между сервисами, который к тому же на другом сервис брокере хрен сделаешь, где нет ордеринга.
— партицированная однопоточная обработка не скейлится — см use case netflix;
— kafka не может получить состояние агрегата по id, cм официальную доку;
— кафку будет сложно развертывать, сопровождать, если применить партицирование — читай официальную доку это единственно рекоммендуемым способ организовать скейлинг консьюмеров в кафке;

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

kafka не имеет optmistic concurrency; как оказалось он и не нужен, что бы работать с консистентыми данными;

Приходит несколько http запросов на выполнение операции над сущностью, как ты будешь хендлить concurrency c kafka? Тебе придется все команды присать в какой-то топик и хендлить асинхронно. Можно, но зачем?

партицированная однопоточная обработка не скейлится — см use case netflix;

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

kafka не может получить состояние агрегата по id, cм официальную доку;

Для этого нужно использовать ksql, а не вычитвать события из стрима агрегата, как это делается в нормальных ES системах. Хз какие это проблемы добавляет, не работал с ksql.

кафку будет сложно развертывать сопровождать если применить партицирование — читай официальную доку это единственно рекоммендуемым способ организовать скейлинг консьюмеров в кафке;

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

я допускаю что в чем-то заблуждаюсь

ok

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

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

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

насколько я знаю партиции плодить обязательно. в kafka можно сделать 1 партицию и добавить больше одной консьюмер группы — но тогда каждая такая группа подписчиков будет читать весь стрим по порядку. Балансировка и скейлинг в кафке делаеться только через партицирование.
То что ты предлагаешь по аналогии с ребитом — сделать exchange на него queue, а на очередь повесить кластер для балансировки обработки сообщений — нельзя, да и как ты себе это представляешь в системе, где каждый консьюмер коммитит offset прочтенных сообщений.

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

Я тебе говорю, что ты не можешь распаралелить чтение сообщений в кафке, если не отпартицируешь топик.

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

так нельзя. где это прочитал?

Похоже, ты сам уже запутался. Ладно давай сворачивать дискуссиию. Я соглашусь, кафку можно использовать как single source of truth, только нужно задумываться и понимать подводные камни. Так же понимать челленджи и альтернативы.

Да не запутался я, просто ты пишешь то чего нет на самом деле.

svn.apache.org/...​ite/082/introduction.html
Note however that there cannot be more consumer instances than partitions.

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

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

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

Не, стоп, нифига, как на счет consumer groups?

Не, стоп, нифига, как на счет consumer groups?

а что с ними? каждая группа читает топик от начала до конца, консьюмеров столько сколько партиций и каждый читает в одном потоке свою партицию — все. Добавишь консюмер группу, еще раз перечитаешь все сообщений от начала до конца. Consumer group — аналог queue в rabbit.

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

Добавление consumer group это просто введение нового подписчика. он читает стрим от начала до конца и не ускоряет работу уже существующей consumer группы :)
если у тебя есть 1 млн сообщений и тебе надо их отпроцессить каждая consumer group процесит их от начала до конца(в целом пр очитаешь 2 млн сообщений), а не параллелит между собой получение сообщений(то что ты ожидаешь что каждая прочитает по 0,5 млн.

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

А если возвращаться к масштабированию, дабавление новой партиции тоже нетривиальная задача. Короче, для чего мы это обсуждаем? Если хочется жевать кактус с kafka как single source of truth — by all means. Туда же транзакции и exactly once delivery.

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

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

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

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

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

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

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

Давай на пальцах и закончим на этом. Есть один топик и один партишен. Нужно два параллельных консьюмера. Запускаем два консьюмера в разных группах.
В первом делаем if (message.key) % 2 == 0 process(message) else return.
Во втором делаем if (message.key) % 2 == 1 process(message) else return.

я понял твой подход меня только удивляет, что ты споришь со мной и противоставляешь его партицированию топика :) что это как не партицирование? :)

Я писал о том, что множество физический партиций заметляют recovery, добавляют latency в репликацию и усложняют поддержку этого всего.

что это как не партицирование?

Я наивно полагал, что под партиционированием мы оба понимаем физицеское партиционирование внутри топика.
Фсе, больше на этот тред отвечать не буду. Спасибо за интересную дискуссию и сслыку на блог нетфликса — почитаю на досуге.

я допускаю что в чем-то заблуждаюсь

Все таки решил продумать юз-кейс с concurrency и partition key, потому как изначально показалось разумным вариантом.

Представь, что есть сага. Она отпраляет команды с partition key id аггрегата. Те, кому она команды отправляет обрабатывают их без проблем и отправляют ей назад ивенты. Что использовать в качестве partition key для ивентов в этом случае? Если id аггрегата, как это обычно делают, то разные ивенты к одной саге будут обрабатываться ранзными консьюмерами. Будет проблема.

Выходом может быть указание partition key ивента id саги, но тогда по ивентам нельзя будет все ивенты агрегата обрабатывать в хронологическом порядке в рамках одного подписчика, так как они будут попадать в разные партиции. Понятна проблема?

Другим решением может быть подписка на ивенты агрегата и генерация на их основании других ивентов с partition id саги, но нужно будет добавлять еще одного consumer-а и дублирвать эти ивенты. И протягивать id саги через всю эту логику. Тоже неидеально, но может быть рабочим вариантом.

При этом, в отличии от Actor Model, consumer будет обрабатывать сообщение группы аггрегатов внутри партиции по-очереди, что может вызывать дополнительную latency.

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

Представь, что есть сага. Она отпраляет команды с partition key id аггрегата. Те, кому она команды отправляет обрабатывают их без проблем и отправляют ей назад ивенты. Что использовать в качестве partition key для ивентов в этом случае? Если id аггрегата, как это обычно делают, то разные ивенты к одной саге будут обрабатываться ранзными консьюмерами. Будет проблема.

проблемы не будет потому, что используеться не orchestration based, a choreography based saga.
Пример моделируем 3 компонента процесят ивенты —

Payment topic (partition by account id) в него пишет OrderService, когда оплаичиваем заказы
Order topic (partition order id) в него пишет PaymentService, StockService, когда меняем статус заказа.
Stock topic (partition by product id) в него пишет Order Service когда резервируем товар

конкуренция возникает в следующих ситуация соотвественно —
Payment service — пытаемся оплатить два и больше ордера с одного аккаунта(поскольку партицирование по account id с одним аккаунтом работает только один consumer)
Order service — юзер пытается с разных девайсов один и тот же ордер оплатить и отредактировать или разные сервиса меняют статус заказа (поскольку партицирование по order id с одним заказом работает только один consumer)
Stock service — разные ордеры пытаються забрать один и тот же товар
(поскольку партицирование по product id с одним товаром на складе работает только один consumer)

Во всех случаях с одним и тем же Account/Order/Stock Item работает всего один поток. и запросы на их модификацию процесятся последовательно. если на каком-то из этапов тебе упадет ошибка максимум, что тебе надо будет, послать событие отмены на 1 или больше получателей(в разные топики), что бы была консистентность событие на обработку во все топики запишется транзакционно, если консьюмер упал, зайдет ретрай(все или ничего с первого или второго раза).

Вот как это выглядит схематически — может поможет визуализация.
imgur.com/a/rpWLbO3

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

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

Ох, ежик, попробуй на листике нарисуй что там будет происходить. Ладно, я попыталася.

судя по кол-ву вакансий даже тут в разделе работа, где надо работать с data pipelines и Kafka(что в общем-то и есть то о чем мы дискутируем) то это не rocket science. Даже у нас не много менее востребовано чем весь дотнет со своим Энтерпрайзом и ‘романами на сиквеле’:)

ДБА же хочет программировать ...

ДБА — це не про «программировать».
ДБА — це «знов сіньори понаписували джойни та фільтри на стороні бекенду, замість SQL, валідують дані у себе в коді, замість впровадити констрейнти, а ти їм винь да положь адекватний перформанс та консистетність даних». Сам таке бачив.

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

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

Але ту ж саму унікальність будь-якого name може перевірити лише констрейнт unique в реляційній бд. В момент запису. Інші варианти — не варианти з rdbms.

Але ту ж саму унікальність

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

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

В общем, Димон был прав коментом выше — у DBA часто sql головного мозга.

карочі ясно. замість констрейнту ми напишемо селект (фор апдейт, звісно, щоб ніхто не вліз поперед нас), зробимо це максимально читаємим, покриємо все це тестами, матимемо на увазі в процесі розробки що унікальність тут може бути не унікальна, бо тести застарівають.
В общєм ясно — для погромістів люба дічь, достатньо покрита тестами, перетворюється в крутон.

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

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

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

Есть метод который валидирует, а есть метод которых сохраняет уже отвалидированные данные. Как видишь мухи от колет отделены, открыл код и сразу ясно что и зачем.

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

для погромістів люба дічь, достатньо покрита тестами, перетворюється в крутон

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

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

Ну а про зашквары я не копенгаген, сорян. Програміровать по-понятіям нє умєю

Об этом ты только сейчас написал, выше ты писал про крутоны. Перечитай свой меседж выше.

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

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

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

Це типу васян і колян наповнюють (наприклад) довідник товарів. Васян в своїй сесії перевірив що товару «хрін» нема, і колян теж, обидва додають кожен по хріну. Десь так, да?

При спробі валідації даних за допомогою констрейнтів «as is» юзер отримає не юзер-френдлі помилку. Звісно, можна перехоплювати помилки і видавати замість них більш зрозумілий текст.

Зачем ловить ошибки из сиквела если эти ошибки можно валидировать еще на уровне UI?

Наприклад, якщо база наповнюється не лише з UI.

А это вы уже заложили себе проблему в архитектуру. Сели на порохвую бочку и покуриваете сигару.

Наповнення бази з інших джерел, окрім UI — це порохова діжка, я правильно зрозумів вашу тезу?

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

Это еще в универе показывали такую картинку — UI, логика и данные. Не надо скрещивать бульдога с носорогом.

Типа такой.
bourabai.kz/dbt/client/6_100000.gif

Тобто варіанти з наповнення бази одночасно через UI i API — це некошерно. Ну ок.

Если схема такая:
UI —> DB <— API
То да, некошерно.

А должно быть:
UI —> API —> DB <— API

UI —> DB <— API

а как ето?

а как ето?
наповнення бази одночасно через UI i API

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

В данном случае у оратора есть два процесса:
UI —> DB, т.е. любая мордочка, которая пишет сразу прямо в базу, и
API —> DB, т.е. какоето рестоподобное апи, которое тоже пишет сразу прямо в базу.

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

Дополню мыслю. Если вы пошарите базу между разными приложениями — вы рискуете расстрелять себе ноги из пулемета, потому что разные приложения это как разные домены логики. Даже если их сначала начинала писать ваша команда, и все было заебок, завтра одно из приложений может уехать другим разрабам, и у вас пойдет конкуренция за базу — вы ВНЕЗАПНО увидите констрейнт там, где он не нужен, или узнаете, что ваша новая структура данных на «той» стороне вычитывается не так, как было вами задумано.

Начнется взаимоотношения между командами типа:
Пидарасы <—> база <—> Пидарасы

Пидарасы <—> база <—> Пидарасы

Лол 😂

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

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

вы ВНЕЗАПНО увидите констрейнт
несколько человек все выходные быстро вкручивали

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

Нет, просто один человек решил, что часть ребят решили что нужно вкрутить. Сам то он всегда всё делает как надо.

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

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

если вместо «база» поставить «API слой» то схема отношений изменится не очень сильно

тем не менее, проблема «больше одного API» существует — но на уровне конситентности данных. когда казалось бы одну и ту же сущность две команды создают и обновляют по разному

если вместо «база» поставить «API слой» то схема отношений изменится не очень сильно

Но приниципиально, потому что владельцем этого API будет только одна из команд.

если вместо «база» поставить «API слой» то схема отношений изменится не очень сильно

Изменится, причем принципиально.

Апи не является хранилищем. Поэтому в случае
пидарасы <—> апи <—> пидарасы
База остается недоступной напрямую, и нету конкуренции разных логик за структуры данных.

тем не менее, проблема «больше одного API» существует — но на уровне конситентности данных. когда казалось бы одну и ту же сущность две команды создают и обновляют по разному

Так я тут как бы о том и речь веду, что так делать не надо.

валідують дані у себе в коді

Все, что не относится к юник констрейнтам — и нужно валидировать в коде.

замість впровадити констрейнти

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

а ти їм винь да положь адекватний перформанс

У адекватных синьоров — адекватный перформанс.
А если перформанс неадекватный — то это такой синьор.

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

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

Или проверка что одно из необязательных полей должно быть заполнено, иначе эти данные не имеют смысла?

Вот это щас внезапно было.

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

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

Чо? Не только лишь все могут понять это вчера так же как сегодня.

вот она, нищета природничо-математичної освіти.

Ага. У вас она на высоком уровне, моделируете разрывы пространственно-временного континуума. Валидируете факт что прошлое не началось в будущем.

внезапно кодеры кодят код. А юзеры заполняют поля. И в бд, внезапно, может прилететь всякое, не отфильтрованное. Это бывает, поверь.

И в бд, внезапно, может прилететь всякое, не отфильтрованное.

Если архитектура через жопу, то конечно бывает.
Ну так не пишите архитектуру через жопу.

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

Это бывает, поверь.

Да зачем верить, я по вашим комментам и так понимаю, что у вас это норма :)

вай вай вай, ідєальная машишева в тредє.

Из того, с чем столкнулся я: — на фронте юзается календарик (сторонний), позволяющий мышкой выбрать временно́й промежуток. Всё красиво, всё сохраняется и работает, битые даты валидируются и не сохраняются. А вот если мышкой выделить промежуток в обратном направлении (от конца до начала), то в одном из мест новое событие не отображается.
Конечно можно много «фу» сказать — как тестили, зачем сторонний календарь пользовали, почему интервал в разных местах кода проверятеся по разному и т.д. Но факт остаётся фактом — по недосмотру/тупости/етц. кодера и фантазии пользователя в бд записался временно́й парадокс. Которого можно было бы избежать, настроив констрейнт (на тот момент используемая версия мускуля не умела в констрейнты).
Вот про такое я и говорю — если зафиксировать схему данных, обмазать её проверками, то можно в некоторой степени обезопаситься от ошибок в коде. И эти проверки — не бизнес логика, а логика самих данных.

записался временно́й парадокс.

Нет. Данная ошибка не по

недосмотру/тупости/етц. кодера и фантазии пользователя в бд

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

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

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

ще раз — данные были провалидированы. Даты — действительно даты, duration в разрешённых пределах, дата начала — в будущем.
Всё как положено. Кроме отсутствия проверки на инверсию.
НУ и да, мы скатились с обсуждения факта существования независимых от кода свойств данных в обсуждение крворукости/ссаных тряпок. Я это продолжать не буду.

ще раз — данные были провалидированы.

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

Ну так расскажи нам болезным, как правильно сохранить две даты? Если последовательность валидация — сохранение это косячная архитектура, то что тогда не косячная?

А что удивительного в ошибочном вводе даты конца события?

Удивительна сама постановка вопроса.

Хотя тут пожалуй, нужно уточнить. В моем понимании событие — это технологические данные, которые порождаются , а не юзер.

Например.

createEvent(userData) {
    Event e = new Event();
    e.created(now());
    e.setData(userData);
    ...processing...
    e.finished(now());
}
В таком случае event.created и event.finished не нуждаются в какой-то особенной валидации, поскольку не доступны для заполнения разным кожанным мешкам.

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

Юнік констрейнти вже таки в базі? Це прогрес.
Якщо подумати, то може й референси теж в БД переїдуть, і NOT NULL може?
От у нас колеги теж вважають, що NOT NULL не потрібен, а ми повинні підчищити за ними записи, що ламають їх бекенд.

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

Например, что кило гвоздей получает скидку в 10% если отдел продаж сократили на 10%.

Це пишеться окремим слоєм у будь-якому випадку, і це очевидно всім.

Навіть, якщо хранімками — окремий набір хранімок з правилами, може навіть запхані в окрему схему, щоби не мішались під ногами

Подход «давайте запихнем логику в хранилки» большинством здравомыслящих людей рассматривается как зло.

ачо?

ачо?

Та пацаны в падике на кортах так сказали.

подъезд на пацанском наречии.

На уровне знать что это такое. Любой навык в SQL получается с опытом, а без него учить бессмысленно в принципе.
Давай вопрос для самопроверки: Что не так в запросе? Не подсказывать!

update people set people.race = races.politcorrect_name from people inner join races on races.id=’nigga’

Что не так в запросе?

политкорректность

Я б не жартував тепер так. Ще якісь феменістки оштрафують потім компанію на 5 мільярдів доларів за НЕполіткоректний код.

Правильно казати фемісткині

Что не так в запросе?

races.id інт а шукають по стрінгу ніга? Чи може забуто додавання WHERE в кінці щоб оновити лише потрібний рядок з people а не всю таблицю?

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

это ты сам додумал

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

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

Я просто хотів самоствердитися, показати що я от, не зовсім тупий.

Крім того по конвенції завжди треба мати аутоінкремент інт айді

По женевской?)

Насчет «учить бессмыленно» это точно: пытался делать пэт-проекты — все очень быстро забывается да не доходит до нужной сложности SQL-запросов :)

Если ты видишь сложный SQL запрос — в 99% случаев что-то пошло не так.

Например вместо базы данных подсобачили Microsoft SQL server

Запрос может быть громоздким, но не сложным. То ты просто ещё Drupal не видел чё генерит — вот уж где йад :)

Ну, может на пет-проектах оно и так, но на боевых обычно только со сложными работаешь, т.к. простые генерятся ОРМ-кой.

Жил-да-был «боевой» проект, да не просто «боевой», а прямо воинствующе боевой. Была в том проекте ОРМ, которую всякие плебеи хейтили и при любой возможности пытались показать свое невежество выраженное в SQL, и писали они значит «сложные» SQL запросы налево и направо, но с каждым запросом оказывалось, что грызть кактус более неприятно, чем работать с ОРМ. В итоге позвали DBA, он базу поправил, пендалей «знатокам» SQL надавал и стали все опять писать запросы при помощи ОРМ. Конец.

А яка це для дотнетчика зараз ОРМ хайпова ? Від EF всі втомились, EF Core молодий-незрілий, Dapper запроси за вас не напише. Все по спіралі, писали SQL, тулили EF навіть на оракл, знов пишем SQL.

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

Говорят OrmLite от ServiceStack норм, но я не пробовать. Да и не новая она.

return products.Skip((currentPage — 1) * pageSize).Take(pageSize).ToList();

Дай угадаю, это превращается в offset fetch?
Вообще когда уже закончится мода натягивать linq на sql. Оно настолько непохоже, что выбивает стул из под ног.


create table races (id varchar(12), politcorrect_name varchar(60));
create table people (id integer auto_increment, race varchar(60));

insert into races values ('nigga', 'African');
insert into people values(NULL, 'unknown');

mysql> update people set people.race = races.politcorrect_name from people inner join races on races.id=’nigga’;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'from people inner join races on races.id=’nigga’' at line 1

не, я теоретически допускаю, что в других СУБД может работать, но наличие FROM в UPDATE выглядит как-то сомнительно

не, я теоретически допускаю, что в других СУБД может работать, но наличие FROM в UPDATE выглядит как-то сомнительно

www.sqlservertutorial.net/...​s/sql-server-update-join

Это синтаксис общий для древних баз типа MS SQL Server.
Для mysql и ему подобных синтаксис был бы сильно короче, без from

В твоём случае ты забыл убрать INTEGER из ID — уверен ругается на это.

но people.id в запросе всё равно нигде не используется :P все люди станут неграми

Это и была задача для ТС, которую я просил не подсказывать.
Типичнейшие грабли для джуна — забыть WHERE на апдейте.

from в update — це синтаксис mssql, sybase і може ще когось
у mysql придумали свій синтаксис — зручніший, до речі (повірити не можу, я хвалю mysql)

щось тіпа такого

update people p join races r on r.id=’nigga’ set p.race = r.politcorrect_name
само собою, цей запит містить ту ж саму помилку, що і оригінальний

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

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

Здесь была чисто задача на типичную граблю — забытый WHERE на апдейте.
Мускул вроде как по дефолту такие и не пропускает.

Мускул вроде как по дефолту такие и не пропускает.

Это с чего вдруг? Если пользователь хочет апдейтнуть всё, какое имеет право мускуль ему это запрещать

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

имхо в твоём примене забытый ЦРУКУ не так страшен, как неправильный джоин. В случае забытого where ты просто обновишь валидными политкорректными именами всех, а вот в случае кривого соединения — обновишь всех невалидными данными.

забытый ЦРУКУ не так страшен, как неправильный джоин

Ну не скажи. «Забытый ЦРУКУ» даже звучит жутко, как «дальний родственник Ктулху».

where нема, поправить раси з джойну, занулить всі інші значення

Ну кроме очеведного отсутствия WHERE, можно было бы ещё поговорить за структуру базы. nigg’у ещё можно nigger’ом или negro назвать например. А people.race сделать people.race_id, а race.id сделать нормальным primary key

.NET

можно прямы езапросы писать в БД?

если дела идут неплохо dou.ua/forums/topic/28464
можно и не учить

За 8 лет можно было и наскрести)

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

На каком уровне нужно знать SQL разработчику .NET?

Если кратко, то на высоком. Лично я как .NET разработчик занимаюсь на 70% написанием кучерявых романов на T-SQL. Не вылезаю из Management Studio и профайлеров.

эм
а типа database developer для этих задач?..

Это моя работа. Я занимаюсь профессионально разработкой систем где под тыщу таблиц в базе, а не сайтиками где из монги берутся коменты для статьи.

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

Система является полностью функционирующим монолитом с 2005 года. Проекту 15 лет. Работает и приносит миллионы денег. Дурачков платить, чтобы перенести сложность из монолита в ад взаимодействия микросервисов нет. Да и не получится.

сталкивался с такими неоднократно. Пока конкурентных пользователей немного и вычисления просты как угол дома — максимум проблем на таких проектах сжигание огромных бюджетов на тюнинг кверей, где латенси чтения/записи может уходить за 1 секунду, а иногда и поболее. Многие просто забивают и ждут иногда и по пол минуты.
Когда появляется загрузка и сложные вычисления, под это все дело собирают нехилый бюджет покупают кластеризирлванное железо от 100 ядер и 4тб озу , и система все равно вгоняет регулярно цпу в потолок и лагает даже в руках самых заслуженных докторов наук в области субд, а продающие железо вендоры парят всякие терадаты за миллионы баксов. цикл разработки серьезной фичи около месяца или двух на таких проектах, половина из которых уходит на непонятно что, не связанное с разработкой или qa.
Когда железо регулярно отказывает а следующих 5 млн $ нет, меняют дизайн системы берут какой-то простой и быстрый in-memory key-value с шардингом получают latency на выходе 100 мс для самых сложных вычислений вместо тех секунд описанных выше, где добавление машинки в кластер стоит 100 $ per month вместо 1000000$ За покупку для prem. За счёт того что логика в языках куда более развитых чем сиквел для работы со структурами данных разными код получается понятней и лаконичней, с точки зрения удобства покрытия тестами в том числе, код максимально ci/cd friendly и за счёт изоляции позволяет такие фичи релизить за неделю.
В большинстве же случае у тех систем где все эти тысячи таблиц не более 100 пользователей overall и редко когда надо больше 1 rps, конфликты по данным ммнимальны в таких условиях, тогда вместо все это раскладывать в 1000 таблиц можно сделать несколько денормализированных документов и добавить optimistic concurrency для целостности. В итоге работа с данными буде в сотню раз быстрее происходить, будет атомарной и консистентной.
Вообщем всему свою время.

Многие просто забивают и ждут иногда и по пол минуты.

Ну так энтерпрайз же — повесил крутилку «Please wait while we build your report» и все ок :)

Переписывать возможно и нет смысла — почитай про жизненный цикл продуктов. Если база новый пользователей уже перестала расти, то скоро продукт будут списывать в утиль. В том плане, что он еще может приносить миллионы, и прожить еще лет 10, но разрабатывать его уже не будут, а будут искать новые точки роста.

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

Энтерпрайзовский внутренний апп не может «приносить миллионы» по определению. Ну если мы не про миллионы галерам говорим :)

Может сам апп в энетрпразе и не приносит миллионы, но без него сам энерпрайз тупо встанет и не видать ни миллионов ни бизнеса. А стартапы вообще только убытки генерят и проедают инвестиции ))))
Это просто как считать.

Сам автор четко написал

Проекту 15 лет. Работает и приносит миллионы денег.

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

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

А к чему в данном случае аналогия с фейсбуком или гуглом? Они тоже внутренние аппы энтерпрайза?
К чему вообще смешивать бизнес-модель с типом целевого рынка?

Система является полностью функционирующим монолитом с 2005 года. Проекту 15 лет. Работает и приносит миллионы денег.

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

А про Фейсбук и Гугл ты вообще какую-то чушь пишешь. То что сервис имеет бесплатный доступ, а зарабатывает на рекламе не означает что он от этого стал не прибыльным. Реклама это лишь один из видов монетизациии сервиса, так же как и платный доступ

Какая разница каким образом на данном продукте зарабатывают?

На этом можно и закончить.

Если решают ввалить кучу бабла в разработку\супоорт энетрпарйз
проекта, значит есть профит, об этом он и написал.

Работает и приносит миллионы денег.

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

Как романтично ты про кровавый энтерпрайз пишешь :)

Многим это интересно, и не интересен аджайл стартап, где сегодня ты пишешь сервис на монге, завтра это уже видео чат и ты тестировщик, после завтра это UI для микро-кредитов и ты девопс :-))))

Многим это интересно

Это какой-то стокгольмский синдром в следствии долгой работы в аутсорсинге :)

Это у тебя такой синдром, энтерпрайз эентерпрайзу рознь, какистартапы.

Мне кажется, ты путаешься в терминологии которой оперируешь.

Когда кажется, креститься надо.

Не буду спешить унижать и гнобить. Спрошу сперва, а чем вы занимались 8 лет в дотнет-разработке? Явно ведь не веб-ентерпрайзом?

Веб только в конце. В основном был WPF; разработка тестовых фреймворков.

Подписаться на комментарии