Комментарии 87
Вам, как и с гастарбайтерами, нужно обо всех них беспокоиться, серверы на MongoDB нужно обслуживать, они выходят из строя, капризничают.
А сервер posgres обслуживают единороги?
Мне не очень понятно, как Cut из бэкенда и Paste во фронтенд облегчит мою жизнь
Не знаю как Вам, а вот гавнокодерам (коих, кстати, во фронтэнде почему-то собирается всегда больше, чем в бэкэнде) это точно облегчит жизнь: почти весь их ароматный продукт теперь будет кушать память и процессор не на сервере, а в браузере пользователя — больше не надо заботиться ни о памяти, ни о производительности.
У меня есть SPA, они не жрут память как не в себя. При том, что я программист в общем-то весьма посредственный.
Теперь эти тормоза будет обнаруживать у себя пользователь в браузере. И далеко не факт, что захочет сообщить об этом и пользоваться вашим ресурсом.
Знаете, какой раньше был самый посещаемый ресурс в инете? Microsoft.com — потому что большинство пользователей не умеет настроить в IE дефолтный URL.
Ну вот пытался я как-то собрать софтину под WebAssembly этот ваш. Упёрся в лимит на 1000000 функций по достижению которых чудо-браузеры (FF, Chrome) отказываются грузить бинарник (хотя он сравнительно небольшой, 9 метров всего).
Так что вебассембле передают привет плюсовые шаблоны, которые она в приемлемых количествах жевать не умеет и в ближайшее время не собирается
Только не совсем понял хронологию событий в докладе, он из прошлого(<=2016) или все же это 2018ый год?
В Силиконовой Долине
Нет, нет и нет. Вы можете сколь угодно ссылаться на то, что пошло в народ. Но на техническом ресурсе мы это не потерпим.
Основные категории прилетевших тапков были из следующих направлений:
- ~50% — за регулярки — вы это обошли.
- ~50% — это неприязнь разработчиков к подобным архитектурам с логикой в базе. Возможно это вы тоже обошли — отсутствием публикации в хабе «Разработка веб-сайтов».
Удачи в развитии!
Здесь же предлагается работа напрямую с таблицами в СУБД.
Нет — postgrest не реализует прикладной логики.
Более того, вы не будете делать верификацию связей таблиц с клиента, логирование и всего того, что эффективней провернуть на стороне, которая ближе к данным, т.е. в СУБД.
И как только вам понадобиться что-то более сложное, чем просто записать или вытащить данные по элементарному условию через предлагаемый OpenAPI, вы вспомните следующую строку статьи:
Также вы можете написать хранимую процедуру и, скорее всего, если вы будете использовать PostgREST, вы будете это делать.
И можете — это мягко сказано. В документации к OpenAPI Postgrest написано ещё конкретее:
It prevents arbitrary, potentially poorly constructed and slow client queries. It’s good for quality of service, but means database administrators must create custom views and stored procedures to provide richer endpoints.
Как бы вам не хотелось, в данной архитектуре, вы очень быстро придёте всё к тем же хранимым процедурам, за исключением сериализации данных.
Я всегда с удовольствием готов изучать что-то новое.
Расскажите, что это за зверь такой.
Какой-то не особо пока известный науке зверь получается.
А чего и как он там оптимизирует, не имея нормальных средств для диагностики (статистика, explain) и собственно оптимизации (индексы, параметры СУБД, БД и её объектов)?
Вы только что описали стандартный сценарий, в котором вся идея ORM – асбтрагироваться от SQL и «ненавистной базаданщины» — сводится на нет.
Да, именно так обычно и происходит при росте нагрузки и проблемах с производительностью — SQL-лапша, созданная в недрах ORM, шевелит волосы у DBA и, чтобы снизить энтропию, запрос фиксируется или начинается нормальная работа по оптимизации. Завод по производству (ORM) со всей его дурной мощью вдруг становится не нужен, программист получает нормально отформатированный и отдаженный SQL (или хранимку! об этом я и говорил изначально — её отлаживать проще, когда нужно ехать, а не «шашечки») и вся роль этой лапшефабрики сводится к дёрганию метода query(..) или аналога, а такой метод есть и в самом драйвере вашего любимого языка к СУБД.
Есть много статей на тему «почему ORM – зло», наблюдаю их лет 15 ежегодно. Тема очень, очень и очень холиварная, но в целом сводится к тому, что лучше тратить время на изучение SQL, чем на штуку, которая позволяет якобы от него отойти.
На самом деле, если рассуждать дальше, PostgREST и подобные прокладки — в целом тоже похожее зло. Но всё же чуть меньшее, потому что:
- меньше степеней свободы (сложнее отсрелить себе ноги, используя какую-нибудь ООП-ориентированную конструкцию, трансляция GET/POST/PATCH/PUT в SQL гораздо более примитивная вещь, чем ORM),
- поощряется изучение SQL так или иначе — когда определяете вьюшки, вы испольузете SQL и это проще отлаживать,
- аналогично с хранимками, чем больше их используете, тем глубже понимаете работу БД и делаете вещи более оптимально, SQL внутри PL/pgSQL – абсолютно родное и естественное тело (
var1 := 0;
– это на самом делеselect 0 into var1;
. А как легко и приятно писать штуки типаif (select count(1) from blabla) > 0 then ...
!).
Вот не надо так категорично, далеко не все сводится на нет.
Запрос лежит вместе с исходниками и изменяется с ними же, в то время как хранимки лежат в БД и в лучшем случае изменяются миграциями. Как результат — я всегда могу сделать git blame запросу, но зачастую не могу то же самое проделать с хранимкой.
В строго типизированных языках ORM берет на себя раскладывание результатов запроса по полям структуры или объекта с контролем типа. Можно в одну строчку выполнить запрос и получить коллекцию результатов.
Если же отбросить ORM — то то же самое придется делать вручную. На сложный запрос может уйти целая страница кода только для подготовки параметров и чтения результатов… Казалось бы, причем тут оптимизация? А при том, что чем меньше кода — тем проще его менять. Главный враг оптимизации — мысли "ну вот, я щас что-нибудь поменяю — и опять все поломается".
Ваше утверждение "хранимку отлаживать проще" ничем не обосновано. И от того что вы его повторите еще пять раз — оно не станет истиной.
Точно так же ничем не обоснована эмоциональная оценка, которую вы дали разным технологиям ("ORM со всей его дурной мощью" и "нормально отформатированный и отдаженный SQL"). Я точно так же могу написать "с появлением нормальных ORM программисты получили возможность писать нормально отлаженный и отформатированный код вместо SQL со всей его дурной мощью" — и это будет ничуть не менее правдиво (и не более).
Отматываем чуть назад и ждём обоснований ваших прошлых утверждений. Напоминаю:
> А эксперт по оптимизации ORM скажет ровно обратное :-)
Вопрос: Я всегда с удовольствием готов изучать что-то новое.
Расскажите, что это за зверь такой.
> Да ровно то же самое, только в другом месте…
Вопрос: А чего и как он там оптимизирует, не имея нормальных средств для диагностики (статистика, explain) и собственно оптимизации (индексы, параметры СУБД, БД и её объектов)?
Статистику собрать несложно. Explain делается тоже довольно просто: перехватывается запрос и делается ему этот самый explain. На всякий случай уточняю: тот факт что в какой-то момент программист увидел SQL никоим образом не нарушает абстракцию.
Индексы и параметры СУБД настраиваются точно так же как и раньше: ORM абстрагирует от DML, а не от DDL.
Ну и осталось ещё один шаг в рассуждениях сделать, чтобы понять, что раз ORM никак не помогает в оптимизации, то она, наоборот, мешает (затрудняет доступ к реальному SQL, часто производя ту самую неотформатированную, малопредсказуемую и малоуправляемую лапшу, о которой уже была речь выше).
Думаю, тут мы уже всё прояснили и копать больше некуда.
Вынуть кусок кода из ORM в хранимку, и оптимизировать там — проще, да, там сразу можно кучу фичей недоступных в ORM взять, например разбить запрос через временные таблицы, или CTE какие-нибудь взять.
Но как только это сделал — оно будет аукаться на каждом изменении схемы БД. Ну, например рефакторинги, и find usages в IDE — хранимку не видят. Поэтому оставаться в рамках ORM — дешевле в долгосрочной перспективе. Можно же прям в ORM запрос поменять, разбить на пару запросов попроще, индексы докинуть на таблички.
Что касается рефакторинга. Мне немного сложно понять, о чём тут речь, т.к. я много лет в tmux+vi и не понимаю, о какой IDE тут речь и о каких её средствах.
Но как-то похоже на то, что подразумевается, что код хранимки — это что-то такое, что где-то там запрятано в недрах БД. Это, конечно, не так (а если так — это беда и так делать нельзя). Хранимка — это обычный код, должен быть в git, версионироваться и нормально рефакториться. Другое дело, что, может быть, «find usages» вашей IDE пока не поддерживают plpgsql (а может, поддерживают? доступные плагины смотрели?).
Хранимка — это обычный код, должен быть в git, версионироваться и нормально рефакториться.
Отлично, осталось найти способ разместить его там. Так, чтобы изменения в нем автоматически применялись к БД при развертывании.
Особенно весело когда хранимка зависит от таблицы, а в таблице есть вычисляемый атрибут, который обращается к пользовательской функции. Вот как автоматически построить порядок в котором вся эта радость должна создаваться в базе, причем с учетом того что база прошлой версии уже есть и дропать ее нельзя?
А лучше переезжайте уже на Постгрес, чтобы понять, что такое нормальные хранимки, поддержка целостности, транзакционность DDL, больше современных фич стандартного SQL.
Код каждого объекта — в отдельном файле, конечно же в git. В качестве системы миграций — sqitch.org (или другая, есть много разных со своими плюсами-минусами. Только обязательно что-то выбрать надо — ничего страшного и стыдного нет, что вы ещё это не сделали, все через это когда-то проходили). Для версионирования хорошо помогают схемы (каждая версия — в отдельной схеме). Также по этим темам полезно послушать доклады Яндекса, Авито и других крупных компаний. Много чего можно найти тут: www.youtube.com/playlist?list=PL6sRAkPwcKNnwScnpKomNXechZQ3WZe1j
Это ответ на вопрос «как разместить в git».
Да, глянул документацию на sqitch внимательнее… К сожалению, эта штука не в состоянии сама установить зависимости между объектами базы. А значит, возможен вариант когда из-за забытой зависимости миграция сломается через два месяца и сразу на проде.
А еще пугает ее способность rebase, которая дропает из базы все данные...
Вот еще интересный вопрос. sqitch же требует revert-скрипта для любого объекта.
Как сделать revert для alter table Foo drop column Bar
?
Алгоритм был такой:
— сносим все хранимки/прочие объекты с БД
— прогоняем дельта-миграции
— кладем все *.sql файлы с хранимками/вьюхами/UDF в список-очередь
— накатываем по одному объекта из списка. Если при накатывании SQL кидает ошибку — кладем в конец списка и продолжаем накатывать следующий
— если мы пробежались по кругу, и очередь не уменьшилась — кидаем все ошибки в консоль.
Таким образом обрабатывались даже нетривиальные зависимости, вроде той что ты пишешь.
Работало все отлично, шустро, и без проблем.
Было это лет 7 назад. А известной статье — blog.codinghorror.com/get-your-database-under-version-control — по мотивам которой я эту тулу и делал — уже 10 лет. С тех пор, я так и не увидел ни одной тулы для миграций БД, которая реализовала бы такой механизм. В современных тулах для миграции, хранимки предполагается класть в миграции — и это совсем тупо, да. И многие так и делают, от чего хочется плакать.
В SQL Server — совершенно убогий язык T-SQL. Я видел проекты где все на хранимках в T-SQL — там совершенный ад был.
В других раскладах, например если java, где запросы в ORM — просто строки, и есть Postgres — где человеческий встроенный язык — расклад может быть другой.
С .NET/EntityFramework, ты можешь в Visual Studio нажать правой кнопкой на поле класса, которое соответствует полю таблички, выбрать rename, ввести новое имя, и весь код гарантированно корректно поправиться. Миграция БД сделается почти автоматически.
С хранимками же — тебе надо будет руками ходить и каждую править. Файлы .sql с хранимками — они не прозрачны для IDE, она не понимает даже про какую БД они. Из удобств — только поиск по тексту. Возможно, в других БД иначе, но в SQL Server/SQL Server Management Studio — оно так.
Т.е. я не говорю что совать всю логику в хранимки — плохо. Но чтобы делать хранимки надо хороший язык в БД, хороший тулинг, нужно толковых базистов. И нужно выкидывать ORM и все делать тогда в БД. Пополам-напополам — получается шиза и бардак.
Да и в целом, код и данные должны быть близко. Для этого можно тащить код к данным (хранимки, Tarantool, и т.п.), или тащить данные ближе к коду (Datomic). А ORM — это дураций костыль, возникший от того что есть хорошие БД, но они — black box — и в них нормальный язык не всунешь, и их как библиотеку к себе код не вставишь. Думаю эта проблема решится потихоньку, и ORM вообще отсохнут со временем.
Но даже для реализации банального отношения one-to-many в ORM нужно прописывать не типизированные метаданные, просто вывести SQL запрос из класса ORM не может. Для этого надо выкурить на много больше доков по ORM, чем знание пары тройки SQL инструкций, которые она генерирует. То есть возни много, а на выходе пшик.
Миграция с переименованием полей не на столько частый рефакторинг чтобы из-за него тащить с собой EF (у меня контекст аналогичный, низкая нагрузка, сложные данные, стек другой). И тот же DataGrip в раз сделает все переименования в хранимках, в t-sql в т.ч.
Но даже для реализации банального отношения one-to-many в ORM нужно прописывать не типизированные метаданные, просто вывести SQL запрос из класса ORM не может.
Да ладно? Entity Framework Code First:
public class Foo
{
public long Id { get; set; }
[Required]
public Bar Bar { get; set; }
}
public class Bar
{
public long Id { get; set; }
public ICollection<Foo> Foos { get; set; }
}
Все, one-to-many автоматически вывелось из этих классов! Если совсем минимизировать пример то можно даже из двух навигационных свойств оставить только одно.
Сложности возникают только когда есть несколько параллельных связей. Но даже там при желании можно сделать все типизировано.
И как только вам понадобиться что-то более сложное, чем просто записать или вытащить данные по элементарному условию через предлагаемый OpenAPI+1. Потом появляется задача вроде «если на картинке имеется кошка, то...»(или в тексте говорится про кошек) и тут вдруг оказывается, что на движке БД этого не сделать, и всё-равно нужен бэкенд.
По теме «вся логика — на плечах бд»: кажется пару лет назад проскакивала тема, что это плохая тема, что БД со временем начинает загибаться от кучи триггеров, дебажить это становится очень сложно, и всё плохо с парралелизмом. Это еще актуально?
Крупные, очень крупные проекты не боятся хранимок. Их боится в основном те, кто в целом СУБД боится.
madlib.apache.org
Загибаться БД может по массе причин. В основном это монструозные бездумные запросы от ORM-ок. Хватит уже валить на хранимки и хватит их бояться.
Скорость разработки просто потрясающая.
Но, пройдя многолетний путь, мы упёрлись в производительность постгреса. Использовали все механизмы распараллеливания, но всё равно. Такой сервис довольно легко завалить умеючи.
В итоге концепцию пока сохранили, но используем программные обёртки в нашем postgrest для хитрого выборочного кэширования.
В целом концепция интересная, живая, но не без нюансов на высоконагруженных сервисах.
На моих глазах целая команда рубистов заменялась одним человеком, готовым писать SQL и коллекции тестов в postman/newman.
Что именно с производительностю? PostgREST ведь stateless, запускайте его на N машинах, часть из которых направляйте на read-only реплики.
Как я понимаю, проблема была в Постгресе самом? Что именно тормозило-то?
запускайте его на N машинахЕсть предположение, что 1 хорошо написанный backend может заменить N машин с обычным PostgRest. Самое первое что лезет на ум — кеширование запросов.
Плюс бесконечно добавлять N машин не получится, рано или поздно, расходы на постоянную синхронизацию огромного количества данных будут класть реплики, и нужно будет уже думать над горизонтальном масштабировании (данные пользователей от 1 до 100 лежат на серверах №1, данные пользователей 101-200 на серверах №2), и уже это будет очень сложно и трудоёмко реализовывать силами лишь PostgRest.
2. Какое нафиг обновление толстого клиента и разные ОС? Ау, речь идет о веб-приложении! Главное достоинство веб-приложений — всегда актуальная версия клиента. Это работает независимо от того толстый там клиент или тонкий.
3. Вот именно, на уровне БД не должно быть никакой логики кроме контроля доступа. Тестировать отсутствующую логику очень просто, даже если это БД.
это не я решил, а весь мир решил и уже давно. Похоже, я недостаточно ясно эту мысль донёс.
noBackend, или Как выжить в эпоху толстеющих клиентов