LINUX.ORG.RU

ORM vs SQL

 ,


0

3

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

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

Но приведу пример. У меня есть API-эндпоинт, возвращающий список некоторых сущностей. Там есть вариантов сортировки штук 10, штук 20-30 вариантов опциональной фильтрации и пагинация. Причём для некоторых вариантов фильтрации нужно делать дополнительные JOIN или подзапросы. Я это реализовал через Doctrine DBAL - и получилось довольно удобно и вполне читабельно. Генерируемый SQL-запрос оптимальный и вполне шустро работает.

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

Хотелось бы услышать противников использования ORM и квери билдеров, как вы решаете такие задачи? И на что маппите результаты запросов? На обычные массивы, не на объекты?

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

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

В 9.5 появилась интересное INSERT...ON CONFLICT action. В ОРМ парой строк не отделаться при переходе с 9.4 и желании использовать СУБД на всю катушку, а не как хранилище таблиц.

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

если проект нормально приёмочными тестами покрыт, то смена версии PostgreSQL делается достаточно безболезненно

Речь не про тесты. Допустим, проблема ясна. Или появилась новая возможность, которую бы хотелось задействовать. При голом SQL придется бегать по всему проекту и править запросы. В случае же с дополнительным слоем абстракции внутри ORM пишется новый (под)класс под обновленный диалект SQL.

То есть, каждый класс привязан к «таблице». Таблица привязана к «базе». У каждой базы есть «драйвер доступа». А еще у базы есть «драйвер SQL».

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

Ты, видимо, в каком-то идеальном мире живёшь) В любом более-менее сложном проекте даже при использовании ORM есть и чистые SQL-запросы. Это неизбежно, т.к. ни одна ORM не покрывает всё. Причём чем старше проект - тем больше таких чистых SQL-запросов в нём будет. Отдельный разговор если у вас есть DBA, которые в целях оптимизации частенько выдают такие запросы, об которые очень многие ORM тупо ломаются. Причём даже на довольно простых и обыденных операторах. Ну, например, сделай UNION ALL в Doctrine.

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

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

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

В ОРМ парой строк не отделаться

Как бы ORM и так знает какие сущности новые, какие старые, а какие удалили и сформирует тебе отдельно bulk insert/update/delete.

no-such-file ★★★★★
()
Ответ на: комментарий от dimuska139

сделай UNION ALL в Doctrine

UNION ALL как бы предполагает, что запрос аналитический, для получения датасета или агрегации и т.о. ORM тут нафиг не упёрлась.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)

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

Читал, что ларавел критиковали из-за ОРМ, мол, это лишнее. Я считаю, что простых задач ОРМ не нужен.

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

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

fernandos ★★★
()
Ответ на: комментарий от no-such-file

UNION ALL как бы предполагает, что запрос аналитический

Ну как бы нет, вовсе не обязательно. Если мне нужно вытащить данные из нескольких таблиц, то почему бы не использовать UNION ALL.

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

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

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

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

Ну, например, сделай UNION ALL в Doctrine

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

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

Руки отрывать за такое, и все дела.

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

Хорошо спроектированные ORM¹ состоят из двух частей: собственно ORM и query builder к нему, который можно использовать и без ORM для построения произвольных запросов. Для стандарнтых CRUD вещей удобно использовать ORM, а для всякой аналитики нужен как раз построитель запросов. Зачем он нужен? Чтоб можно было, например, огромный запрос разделить на отдельные логические части, так гораздо проще писать и отлаживать. Или чтобы повторяющиеся фрагменты запросов вынести в отдельные функции, а не копипастить по 10 раз. Или чтобы строить динамические запросы для всякого поиска по параметрам и т. д. И да, поддерживать одновременно разные СУБД обычно плохая идея, но построитель запросов и с этим очень помогает, потому что многие детали абстрагирует, типа экранирования или синтаксиса для подстановки параметров. А то, что не абстрагируется, можно вынести в отдельные функии.


¹ Пример хорошо спроектированной ORM - SQLAlchemy для питона.

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

Клоун, пойди добавь в существующий билдер (в котором этого нет) возможность update таблицы c join’ом. Или такой же update c джойном на другую таблицу, где другая таблица результат рекурсивной cte. И потом покажи как это выглядит. Ну или реализуй возможность вызова оконной функции с вызовом обычной агрегатной в качестве аргумента оконной. И это самые простые кейсы, элементарные просто. То есть мы не говорим тут о каких-то особых продвинутых фишках конкретных БД типа постгреса.

Вы оба идиоты с димушкой. Вы в упор не видите что ваш qb-инструмент из себя представляет - полное говно. При этом SQL вы не знаете даже на уровне SQL1999. Что вам, что вашему qb до sql99 как до луны.

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

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

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

Дурачок, эскейпинг содержимого литералов и идентификаторов - это не построитель запросов (query builder) делает, а клиентская библиотека твоего языка, т.н. «драйвер». Это в любом ЯП и драйвере так. Оно же эти литералы формирует приводя типы. квери-билдер тут ни при чем от слова совсем, дурачок.

многие детали абстрагирует

Никаких деталей query builder не абстрагирует. Он не может этого делать в принципе там этого нет. Портаблельность между БД они тоже не обеспечивают, потому что не могут в принципе.

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

Руки отрывать за такое, и все дела.

За такое - это за что? Например, мне нужно сделать WHERE similarity(u.name, 'Alex') < 1 - что тут плохого?

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

Эм, и к чему ты это? Я в курсе про построители запросов. Говоря «можно использовать и без ORM для построения произвольных запросов» ты лукавишь. Конечно, квери-билдеры достаточно гибки, но о «произвольных запросах» речь идти, к сожалению, не может. Как я уже писал выше, с помощью квери-билдера Doctrine ты UNION ALL не сделаешь - то есть ограничения-то имеются.

Пример хорошо спроектированной ORM - SQLAlchemy для питона

Я чуть чаем не подавился. Вообще-то в питон-сообществе расхваливают SQLAlchemy лишь потому, что альтернатив там вменяемых особо и нет, если речь не о Django. Всякие Gino, PonyORM, TortoiseORM и т.п. - это такой мусор, что на фоне них, конечно, SQLAlchemy выглядит достойно. Но квери-билдер в Алхимии, мягко говоря, такой себе. Почему? Потому что он крайне далёк от SQL и, глядя на примеры его использования (если речь не о совсем примитивных вещах), зачастую даже непонятно, какой запрос в базу уйдёт. Для сравнения, квери-билдеры в какой-нибудь Doctrine или TypeORM гораздо более читабельные.

Кроме того, считаю, что хорошо спроектированная ORM - это такая, где модели - чистые объекты (или с аннотациями/декораторами у полей), которые ни от чего не наследуются, а из методов имеют только. геттеры и сеттеры. А в Алхимии Entity наследуются от Base.

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

Покажи мне, не идиот, как красиво на чистом SQL построить запрос на выборку из БД продуктов интернет-магазина. Фильтров может быть штук 20, допустим, и 5 вариантов сортировки. Естественно, фильтры могут быть не все, кроме того, некоторые из них приводят к подзапросам или дополнительным (опциональным) джойнам. Покажи пример реализации такой выборки (на любом языке программирования) без ORM и без квери-билдеров.

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

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

За такое - это за что? Например, мне нужно сделать WHERE similarity(u.name, ‘Alex’) < 1 - что тут плохого?

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

Завтра тебе захочется заменить эту конструкцию на «не равно». Или ввести «уровни похожести».

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

Да шо ты споришь с нубами. ORM это уже плохо знаешь почему? Потому, что её учить нужно! 🤣

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

Тоже верно. ORM должна быть легко расширяема. В идеале

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

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

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

И это при том, что самое важное, запрос совсем-совсем примитивный, там даже SQL-то нет, что-то в рамках SQL-92 в лучшем случае. Почему? Потому что так положено? НЕТ. Потому что QB не может даже в SQL-99, а пользователь QB - идиот. Да что говорить, некоторые QB к моменту релиза джойны толком-то не могли. Некоторые я не удивлюсь, если до сих пор не могут. Джойны, карл! Чтобы думать, что qb - это инструмент, я не знаю кем надо быть, это не к вопросу об ступени развития программиста, это о чем-то другом уже…

Я понимаю да, что для тебя эти твои 20 вызов addWhere() о которых ты так много говоришь - это прям вершина. Но этот вот qb-говнокод который ты породил, он к базам данных и SQL отношения не имеет и не отменяет того факта, что QB - это вредное говно, за внедрение в проект которого надо отрубать руки.

У тебя был мега-примитивный запрос, ты пытался этот предикат соорудить работой со строками, но так как ты криворукий, у тебя получился говнокод. В блоге Кумара ты прочитал про кверибилдер. На этом qb ты сделал сконструировал предикат аж на целых 20 параметров. Теперь ты чувствуешь себя экcпертом SQL. Всё понятно, но высказываться по теме SQL, баз данных и пр. и программирования тебе не стоило бы.

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

Ты конечно можешь зарабатывать макакированием select * from table на qb. Но тем, не менее, ты обосрался.

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

любой даже самый-самый простой запрос на QB превращается в нечитаемую парашу, неподдерживаемое и неотлаживаемое говно

Ага, вот то ли дело собирать строку с SQL-запросом в куче if-аков. Вот это красота и надёжность!

QB - это вредное говно, за внедрение в проект которого надо отрубать руки

DBA, с которыми я общался, считают иначе. А вот ORM не любят - это да. Точнее не любят разрабов, которые не умеют пользоваться ORM.

Никаких деталей query builder не абстрагирует

Ты походу совсем некомпетентен. Шаблон «строитель» (квери-билдер - это он и есть) как раз скрывает построение SQL-запроса за вызовом методов. То есть уровень абстракции, если что. Ты, случаем, не вордпресс-вебмастер?

Я от тебя так и не дождался примера построения сложного запроса с фильтрами без qb и ORM. Он будет, или ты, пустослов, стесняешься свой говнокод продемонстрировать? Я серьезно, покажи, как надо - мне интересно. Если ты считаешь, что QB не нужны, то продемонстрируй альтернативный подход.

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

Ты походу совсем некомпетентен. Шаблон «строитель» (квери-билдер - это он и есть) как раз скрывает построение SQL-запроса за вызовом методов. То есть уровень абстракции, если что.

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

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

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

Всё ясно: очередной балабол, который не может подтвердить свои слова примером кода. Что и требовалось доказать. Удачи!

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

Как я уже писал выше, с помощью квери-билдера Doctrine ты UNION ALL не сделаешь - то есть ограничения-то имеются.

Зачем-то налёл кривой квери-билдер и спорит сам с собой.

https://docs.sqlalchemy.org/en/14/core/selectable.html?highlight=union_all#sqlalchemy.sql.expression.Select.union_all

А в Алхимии Entity наследуются от Base.

Не хочешь — не наследуй. Алхимия с самых первых версий позволяет использовать в качестве моделей произвольные объекты, а sqlalchemy.ext.declarative, о котором ты слышал звон, уже потом добавили. Можно вообще ванильные датаклассы использовать:

https://docs.sqlalchemy.org/en/14/orm/mapping_styles.html#declarative-mapping-using-a-decorator-no-declarative-base

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

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

Чего за бред вообще) Я тебе привёл пример известной ORM, квери-билдер которой имеет конкретные ограничения. Квери-билдер Алхимии тоже имеет какие-то ограничения, даже если UNION ALL он и умеет. Любой квери-билдер любой ORM имеет некие ограничения - это логично и естественно.

Насчет того, что в алхимии можно не наследоваться от Base не знал - за инфу спасибо.

Upd: поглядел я это использование ванильных датаклассов - хрень полная. Эти дата-классы остаются приколоченными к Алхимии. Например, на кой там __table__ = и __sa_dataclass_metadata_key__? Зачем этот мусор?

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

Я стараюсь избегать ORM в первую очередь потому, что это непрозрачный слой взаимодействия с критически важными данными. SQL — это стандарт, хоть и со спецификой в разных субд, ты можешь пользоваться им одинаково из разных языков. Васяно-орм тысячи в разных языках, учить их все лень; делать взаимодействие между разными ЯП тошно. Сделать миграцию данных в проекте с двумя орм (на двух ЯП)— тот ещё квест.

У меня есть API-эндпоинт, возвращающий список некоторых сущностей. Там есть вариантов сортировки штук 10, штук 20-30 вариантов опциональной фильтрации и пагинация. Причём для некоторых вариантов фильтрации нужно делать дополнительные JOIN или подзапросы.

Возможно мне посчастливилось не работать в говномагазинах и прочих веб-сайтах. Когда встречались похожие задачи, просто велосипедил простенький QB, но этих случаев по пальцам пересчитать. Я думаю, что тащить в проект орм, чтобы покрыть один сложный кейз — это оверкилл. В квери-билдерах IMHO важно вовремя остановиться. Они должны быть тупыми и делать ровно то, что ты хочешь: явно и очевидно. Единственное предназначение — избавиться от лапши из конкатенации строк, оставив максимально близкое к SQL DSL.

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

filosofia
()

Регулярно читаю на форумах, что ORM юзать не надо

Можно попробовать добавлять в игнор людей, которые подобное говорят.

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

Например, на кой там table = и sa_dataclass_metadata_key?

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

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

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

Я тоже в интернет-магазинах не работал, но привёл просто такой пример для наглядности. Так в любом проекте есть API-эндпоинты с опциональной фильтрацией в том или ином виде.

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

Странно, что так получилось, ведь любая ORM из коробки предусматривает возможность использования чистого SQL. Это продумано разработчиками обычно, причём при этом и маппинг результатов чистых SQL-запросов на объекты там работает.

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