Рубріки: Базы данных

Как перестать ненавидеть и полюбить ORM

Володимир Рожков

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

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

История взаимодействия с ORM

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

Впоследствии я успешно пользовался JPA/Hibernate и имел неприятность только со специфическими вещами типа bigint, который не хотел мапиться то ли из-за бага Хибера, то ли из-за особенностей MariaDB.

А после ActiveRecord я не очень представляю, как можно быть производительным без ORM. Во всех своих проектах SQL мне приходилось писать только для запросов, связанных со статистикой.

Известна моя любовь к Rails, но ActiveRecord я люблю больше всего, вот, например запрос на вытягивание очередного ежедневного сбора для @Donate1024Bot

Post.where(state: "approved")
    .where.not(amount: nil)
    .where.not(goal: nil)
    .where(posted_count: 0)
    .where(scheduled_at: Time.now.utc.to_date)
    .order(:id)
    .first

Эффективная работа с ORM

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

Главное — хорошо знать и понимать SQL. Когда вы уже понимаете как сделать нужный вам запрос, то не будет никаких проблем с тем чтобы конвертировать его в эффективный ORM-код. Мне кажется что часто люди жалуются на код программистов, которые начали пользоваться ORM без хороших знаний SQL и нарубили дров. Такое, конечно, никуда не годится.

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

Все ORM умеют это делать, но, по неизвестным причинам, это не везде включено по умолчанию, например, в Spring/JPA это нужно конфигурировать отдельно. Одно из огромных преимуществ ActiveRecord — это такой лог. Например, запрос сверху покажет нам следующее:

Post Load (56.3ms)  SELECT "posts".* FROM "posts" WHERE "posts"."state" = $1 AND "posts"."amount" IS NOT NULL AND "posts"."goal" IS NOT NULL AND "posts"."posted_count" = $2 AND "posts"."scheduled_at" = $3 ORDER BY "posts"."id" ASC LIMIT $4  [["state", "approved"], ["posted_count", 0], ["scheduled_at", "2023-09-18"], ["LIMIT", 1]]

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

Третье — понимать, что такое  N+1 и как в вашем ORM-фреймворке этого избежать. Кажется, что N+1 – это самая распространенная проблема с ORM, на что ругаются те же опытные программисты, хотя она очень легко обнаруживается и исправляется. Просто почитайте как у вас делается  includes или  FetchMode.EAGER и больше не будете с тем хлопот.

Думаю, что 95% всех проблем с ORM сводится именно к N+1 и непониманию, как с ним справиться.

Четвертое — понимать цену создания объектов и использовать методы, позволяющие избежать этого. Например, если нам нужно взять из таблицы только одно поле,  idто вместо этого  ids = User.all.map(&:id) можно использовать  ids = User.all.pluck(:id)которое не будет создавать объекты  User, а получит только массив id. Rails любезно печатает статистику по количеству инстанцированных объектов в лог, поэтому там сразу понятно, где это уже влияет на быстродействие.

Люблю ORM, использую во всех проектах, советую делать то же самое и вам.

Практический совет

Включить логи своего ORM и посмотреть запросы, которые он генерирует. Подумать, что можно улучшить и почитать документацию или Tips&Tricks к своему фреймворку.

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

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Останні статті

Токсичные коллеги. Как не стать одним из них и прекратить ныть

В благословенные офисные времена, когда не было большой войны и коронавируса, люди гораздо больше общались…

07.12.2023

Делать что-то впервые всегда очень трудно. Две истории о начале карьеры PM

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

04.12.2023

«Тыжпрограммист». Как люди не из ІТ-отрасли обесценивают профессию

«Ты же программист». За свою жизнь я много раз слышал эту фразу. От всех. Кто…

15.11.2023

Почему чат GitHub Copilot лучше для разработчиков, чем ChatGPT

Отличные новости! Если вы пропустили, GitHub Copilot — это уже не отдельный продукт, а набор…

13.11.2023

Как мы используем ИИ и Low-Code технологии для разработки IT-продукта

Несколько месяцев назад мы с командой Promodo (агентство инвестировало в продукт более $100 000) запустили…

07.11.2023

Университет или курсы. Что лучше для получения IT-образования

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

19.10.2023